【解决方案】分布式系统如何生成全局ID

考虑分布式:如何有一个全局Id,保证Id唯一,考虑到分库分表之后,还可以保证这些全局Id的生成规则 保证一直性的。

一、基本要求:

1、全局唯一
2、趋向递增(满足mysql的索引的特点)
3、尽量保证下一个id比上一个高
4、信息安全方面;保证id不容易被猜到
5、包含时间戳(了解这个id的生成时间)

二、高性能需求:

1、高可用:不能出问题呀99.999%情况下要成功创建
2、低延迟:毫秒级
3、高并发:支持高QPS(Query Per Second) = 并发量/平均响应时间 ;同时10万的情况要生成id

三、雪花算法产生之前的的解决方法:

1、UUID: 32位的16进制,是JDK自带的工具类;唯一性可以实现,但是它无序

// UUID 36位的16进制的 0e8500ab-a173-4d54-9eaa-e81477ea4470
System.out.println(UUID.randomUUID());

无序可以导致什么问题呢?
TODO: 了解一下B+tree,会导致索引的分裂,索引不好创建,索引不好查询
Innodb存储引擎的特点主键可以实现聚簇索引,,数据存入索引叶子节点上,可以直接存储值,而且是从左向右递增的,但是UUID是无序的,就是导致索引出现分裂。
2、数据的自增主键: mysql 通过replace into实现,(replace into 表中索引如果存在就替换掉)
有序性,唯一性,递增,但是集群分布不可以不能实现并发执行,不合适大数据量,每次插入数据都需要读写数据库。
3、redis: redis6.0支持多线程,redis单线程的天生保证原子性,
但是需要设置不同的增长步长。但问题是,这里需要维护配置麻烦。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jwnx5GSW-1595769830530)(en-resource://database/3758:1)]

四、boss 雪花算法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4p8lv5rX-1595769830538)(en-resource://database/3762:1)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Mbj0knD-1595769830544)(en-resource://database/3764:1)]
64位Long类型的整形基础数据类型,
1、0符号位:最高位为0,表示取正数
2、41位时间戳:11111111111111111111111111111111111111111
3、转化成10进制:2199023255551L

public static void main(String[] args) {
        Date date = new Date();
        date.setTime(2199023255551L);
        System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date));
    }

结果:2039-09-07
也就是可用到这个时候,这是当41位全部都满的情况

4、10位工作进程为:5+5也及时是workerId 和 datacenterId 机器码和机房码 也就是最好1024个节点(可以自己修改源码,根据业务修改对应的workerId和datacenterId的位数)
5、12位,序列号: 每台机器每毫秒内最多产生4096个序列号

PS:常见的使用:

1、HuTool

<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.3.9</version>
 </dependency>
/**
 * @introduce: 使用huTool工具包,Id生成工具类 
 * @author: xingMeiLing
 * @DATE: 2020/7/15
 **/
public class Test3 {
    private long workId= 0;
    private long dataCenterId =1;
    private   Snowflake snowflake =  IdUtil.createSnowflake(workId,dataCenterId);
    @PostConstruct
    public  void init(){
        try {
            workId = NetUtil.ipv4ToLong(NetUtil.getLocalhostStr());
        } catch (Exception e){
            workId = NetUtil.getLocalhostStr().hashCode();
        }
    }
    public  synchronized long snowflakeId(){
        return snowflake.nextId();
    }
    public synchronized  long snowflakeId(long workId,long dataCenterId){
        Snowflake snowflake =  IdUtil.createSnowflake(workId,dataCenterId);
        return snowflake.nextId();
    }

    public static void main(String[] args) {
        System.out.println(new Test3().snowflakeId());
    }
}

优点:

• 毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。

作为DB表的主键,索引效率高。

• 不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。

高性能高可用:生成时不依赖于数据库,完全在内存中生成。

容量大:每秒中能生成数百万的自增ID。

• 可以根据自身业务特性分配bit位,非常灵活。

缺点:

• 强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。

• 可能会出现不是全局递增的情况。

2、解决时钟回拨问题:

  • 百度UidGenerator
  • Leaf美团

3、mybatisPlus-Core的IdWorker类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邢美玲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值