分布式全局唯一ID

1、什么是分布式全局唯一ID?为什么需要分布式全局唯一ID?

分布式全局唯一ID,主要体现在分布式微服务中或者是体现在分库分表的架构中。

分布式微服务表现:在整个的项目架构中,可能会存在多个模块,比如:多个订单模块、多个用户模块、多个支付模块,作为分布式微服务,各个模块都是存在不同的服务器上的,如何保证各个模块之间的数据是全局唯一的,就需要使用分布式全局唯一ID解决。

分库分表表现:主要体现在对于但数据库而言,数据量很大,需要对数据进行分库分表,如果进行分库分表的话,不同的库与不同的表之间的数据,如果使用自增实现唯一,那也只能保证在单个数据库中是唯一的,但是在多数据库中就是不唯一的,所以需要分布式唯一ID。

2、分布式唯一ID解决方案?

  • 第一,使用数据库自增。

刚才已经说过了,在分库分表中使用数据库的主键自增是不能实现全局唯一ID的,但是,为什么还需要提到数据库自增呢?

其实,是使用不同的数据库自增策略实现数据库全局唯一ID。

如图,现在分库分表,形成了两个数据库,每一个数据库有两个表,一共形成四张表,那么,在添加数据库的时候,不管谁的先后顺序,对每一个数据库每一次自增递加所有数据表的数量,这样,就能保证全局唯一,即使有个别的数据库宕机,也能保证数据库数据唯一。

缺点:对于扩展数据库来说,是非常不友好的。

  • 第二,使用UUID。

UUID是java中内置的产生随机数的一个方法,并且也是唯一的,但是不推荐使用这个方法,因为这个方法生成的随机数包含数据和字母,并且无序,用它来作为主键索引,对于数据库数据的查找没有有序的索引效率高,再加上,UUID对于空间的使用也是很大的。

  • 第三,使用Redis自增。

Redis实现数据的递增,使用incr命令实现,对于Redis这种基于内存的NoSql数据库,效率是很高的,并且也是全局唯一的,但是,这个方法过于依赖Redis,并且,对于系统来说与Redis是需要交互获取这个全局唯一ID的,若出现网络不好,就会影响效率。

  • 第四,使用雪花算法。

雪花算法(snowflake)会使用当前的时间戳,作为全局的唯一ID,并且雪花算法是一个毫秒级的算法,他的速度也很快,可以在每秒中产生数百个全局ID。

3、了解雪花算法

雪花算法,之所以叫雪花算法是因为,就像是天空下雪花一样,在同一秒中,可以下很多的雪花,也体现了他的效率。雪花算法,占用空间8个字节,一共64位。

  • 第一部分,占一位。表示数据的正负。

  • 第二部分,占41位。表示时间戳。

  • 第三部分,占10位。表示最多可以部署多少台机器。1024台

  • 第四部分,占12位。表示序列号。

    雪花算法之所以能做到全局唯一是因为他的核心是使用当前的时间戳作为ID,时间戳是唯一的,并且在产生时间戳的时候,nextId()底层采用了synchronized关键字修饰表示其是一个同步方法。就更加保证了其唯一性。

4、雪花算法的基本使用

//引入工具类库
<!--  分布式全局唯一ID 是哦也能够HuTool工具  -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.13</version>
</dependency>
public void HuTool_Simple_Use() {
        /**
         * 实现一:简单使用
         * 分布式全局唯一ID,也能够IdUtil.getSnowflake()方法得到雪花算法
         * 该方法内部使用了synchronized关键字修饰,保证了同步实现。
         */
        Snowflake snowflake = IdUtil.getSnowflake();
        System.out.println(snowflake.nextId());
        System.out.println(snowflake.nextId());
        System.out.println(snowflake.nextId());
        System.out.println(snowflake.nextId());
}

5、雪花算法结合Mybatis-Plus实现全局唯一

    第一,引入项目依赖
        <!--  mysql driver  -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--  mybatis-plus  -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.0</version>
        </dependency>
        <!--  lombok  -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
        <!--  web  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    第二,数据库建表
CREATE TABLE `t_users` (
  `userid` bigint(20) NOT NULL,
  `username` varchar(22) DEFAULT NULL,
  `userage` int(11) DEFAULT NULL,
  PRIMARY KEY (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    第三,编写三层架构
//Controller层

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/simple")
    public void HuTool_Simple_Use() {
        /**
         * 实现一:简单使用
         * 分布式全局唯一ID,也能够IdUtil.getSnowflake()方法得到雪花算法
         * 该方法内部使用了synchronized关键字修饰,保证了同步实现。
         */
        Snowflake snowflake = IdUtil.getSnowflake();
        System.out.println(snowflake.nextId());
        System.out.println(snowflake.nextId());
        System.out.println(snowflake.nextId());
        System.out.println(snowflake.nextId());
    }

    @RequestMapping("/addUser")
    public String HuTool_Mybatis_Plus() {
        /**
         * 实现二:与mybatis-plus结合使用
         * 需求:添加一个用户,用户的主键,开发人员不需要编写,有HuTool工具自动生成
         */
        Users users = new Users();
        users.setUsername("惠豆");
        users.setUserage(13);
        Integer integer = userService.addUser(users);
        return "添加用户成功!";
    }
}  
//Service层

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    // 添加用户
    public Integer addUser(Users users) {
        return userMapper.insert(users);
    }
}
//Mapper层

@Repository
public interface UserMapper extends BaseMapper<Users> {

}
//POJO层

@Data
@TableName(value = "t_users")
public class Users {

    /**
     * TableId注解表示其是一个主键
     * ASSIGN_ID 表示的是雪花算法
     */
    @TableId(type = IdType.ASSIGN_ID)
    private Long userid;

    private String username;

    private Integer userage;

}
application.yml配置文件

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/school
    username: root
    password: root
//主启动类

/**
 * @Description: 分布式全局唯一ID 使用HuTool工具
 * @Author: huidou 惠豆
 * @CreateTime: 2022/6/10 14:45
 */
@SpringBootApplication
@MapperScan(value = "com.hui.mapper")
@Slf4j
public class UniqueID {
    public static void main(String[] args) {
        SpringApplication.run(UniqueID.class,args);
        log.info("#############  启动成功  #############");
    }
}
在结合mybatis-plus中,在添加用户的时候,根本就不需要开发者自己编写用户ID,只需要在实体类上标注主键,并且标注主键的类型是使用雪花算法,如下:
@TableId(type = IdType.ASSIGN_ID)
private Long userid;
全部评论

相关推荐

11-14 16:15
已编辑
湖南工业大学 Java
点赞 评论 收藏
分享
bg:双非本,一段中小厂6个月测开实习今天发这个帖子主要是想聊一聊我秋招以来的一个发展我是在8月底辞职,打算秋招,可是看网上都说金九银十就想着自己就是一个普通本科生,现在九月份都是一些大神在争抢,所以9月份基本上没投,等到了10月份才开始秋招,可是这个时间好像已经有些晚了,今年秋招开启的格外早,提前到了7,8月份,我十月才开始,官网投了很多公司,没有任何一个面试机会,这个情况一直到了十月底才有了第一个面试,当时没有面试经验,所以不出意外的挂了后续就是漫长的投递,但是毫无例外没有面试,没有办法我只能另辟蹊径开始在BOSS上边投递,然后顺便也根据BOSS上边这个公司名称去浏览器搜索看看有没有官网投递渠道,毕竟官网上投递后还是可以第一时间被HR看到的,然后一直不停投递,一开始第一个星期基本上都是投的正式秋招岗位到了第二个星期才开始实习和正式一起投,到十一月底的时候已经沟通了700➕才有一共1个正式的,5个要提前实习的,3个实习的面试,最后结果是过了1个要提前实习的和2个实习的每次面试我都会复盘,发现这些小公司面试官问的五花八门,有的专问基础,有的专问项目,有的啥都问,不过自己也是看出来了一下门道,就是小公司不像大公司面试官那样能力比较强基本上你简历上边的他都会,然后会根据简历来问,小公司面试官他们更多的是看自己会什么,然后看看你简历上边哪些他也是会的然后来问,经过不断的复盘加上背各种各样面试题,到了11月底12月初才有了1个要提前实习的offer还有2个实习的offer,而且薪资待遇对我来说已经很可观了可是啊,人总是这样得了千钱想万钱,我又开始不满现状,但是此时的我面试能力经过这么多面试和复盘已经很强了,然后在十二月份运气爆棚,被极兔和小鹏补录捞起来面试,还有个百度测开的实习面试,这个时候因为有了offer所以感觉有了底气,面试也很自信,最后结果是全部都过了那个时候我感觉自己真的很厉害,我问了极兔那边的HR像我这样的双非本收到offer的在极兔有多少?他告诉我产研岗90%都是硕士,10%里边基本上都是211,985,想我这样的很少很少,那一刻感觉自己超级牛逼,小鹏就更不用说了,最后也是不出意外选择了小鹏所以我就我个人经历想对和我学历履历差不多的牛友一些建议第一:秋招一定要趁早,真到了9,10月,那个时候可能你投的结果可能还不如7,8,11月,第二:最好先拿小公司实习或者正式练练手,提升一下面试能力,我个人觉得因为小公司问的五花八门所以你会更加横向去提升自己能力,而且大公司其实面试没有那么难,除了一些非常卷的岗位,公司大神比较多会问的很难,一般好点的公司都不会问的那么难,他们也知道都是应届生不会要求那么高第三:当有一定能力后,就是坚持了,对于我们这样的学历,没有特别强的履历情况下,就是要抓住提前批和补录的机会,这个时候各方面不会卡的很严,是我们很好很好的一个机会第四:就是运气也是很重要的一部分,不过这个很难去说什么最后祝各位牛友都能收获自己满意的offer😁😁😁
秋招,不懂就问
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务