赞
踩
写这篇博客的原因也是最近在和朋友讨论一个自己尝试写的一个“号段模式”的主键生成工具项目分布式号段模式(Theta)
他说他在“鹅厂”工作时候都没听说(segment)过这东西(难道大厂不用这种的么?都是雪花?),他一开始还以为是Java 里面concurrentMap里面的分段锁机制,接下来进入本章重点。
全局唯一性:不能出现重复的ID号,保证生成的 ID 全局唯一,这是最基本的要求。
趋势递增:有利于保证DB插入、查询等操作的性能。
单调递增:保证下一个ID一定大于上一个ID,例如版本号、排序等特殊需求。
信息安全:如果ID是连续的,容易被猜测出url,ID号码的数量,对业务产生影响。所以在一些应用场景下,会需要ID无规则、不规则。
PS:上述需求对应不同的场景,3和4需求还是互斥的,无法使其在同一个方案满足。
同时除了对ID号码自身的要求,业务还对ID号生成系统的可用性要求极高,想象一下,如果ID生成系统瘫痪,整个电商系统都无法完成业务,这就会带来一场灾难。
单机数据库自增
老生常谈的 Auto Increment,也是各种数据库都有的自增算法。
集群数据库
水平切分后的数据库自增,并且在不同的数据库设置不同step(步长)
号段模式
JVM本地缓存step和maxid,对应服务的主键生成规则,在次基础以数据库排他锁和事务特性来维护maxid和step。而且目前主流的方式会对step,进行双buffer缓存实现实现,这样可减少对数据的方位。
雪花算法
雪花算法是 64 位 的二进制,一共包含了四部分:
1位是符号位,也就是最高位,始终是0,没有任何意义,因为要是唯一计算机二进制补码中就是负数,0才是正数。
41位是时间戳,具体到毫秒,41位的二进制可以使用69年,因为时间理论上永恒递增,所以根据这个排序是可以的。
10位是机器标识,可以全部用作机器ID,也可以用来标识机房ID + 机器ID,10位最多可以表示1024台机器。
12位是计数序列号,也就是同一台机器上同一时间,理论上还可以同时生成不同的ID,12位的序列号能够区分出4096个ID。
号段模式
对数据库自增主键的一种优化,只不过这个自增需要我们来维护其范围,这样主动权交给我们手里,我们就可以对其主键进行客制化定义,这样返回的主键,解决了主键不方便扩展。(详细可以了解下美团Leaf:美团分布式ID生成服务开源为此还优化了双Buffer模式,以减少对数据库的依赖 )
利用redis的incr原子性操作自增。可以用时间,日期组合进行标识唯一
实现类型 | 优点 | 缺点 |
---|---|---|
数据库自增ID | 实现简单,ID单调自增,数值类型查询效率高 | 单点问题,在高并发时可能会有宕机的风险 |
数据库多主集群 | 解决了单点问题,一定程度上提高了稳定性 | 可拓展性不强,随着业务规模的不断扩大, 集群也会随之增加,但是新主节点的加入较为麻烦,需要人工操作 |
号段模式 | 不强依赖数据库,提高了效率 | 当为了保证高可用而使用多主集群时,仍然需要去修改起始值和步长(可以优化) |
雪花算法 | 1.可以根据业务特性自由分配比特位,较为灵活。2.不依赖第三方系统,独立部署 | 强依赖机器时钟,如果出现时钟回拨则会导致系统不可用 |
Redis | 简单且高效 | 持久化恢复存在问题,如RDB重复ID,AOF速度慢 |
关于Theta
灵感是来自于Leaf ,由于每个业务想要的主键Id又是不一样,想尝试做一个完全客制化的主键生成工具,工具的初衷就是为了让用户通过配置实现一套自定义的主键,所以底层也是参考使用
号段模式
进行实现。还有很多不足的地方
关于Theta构思:
首先想到的是使用MySQL基于,MVVC支持的Innodb引擎来维护每次序列号生成的顺序,防止出现重复的 主键。同时我们还需要使用到数据库的事务,当然这也是为了防止出现多个线程,同时操作数据库,每条线程 使用了重复的序列号。也就是说,每当我们需要生成一个序列号的时候,Theta会帮助我们去调度事务, 去给用户当前使用的唯一序列号进行自增,也就是说ThetaSegment是通过数据库的X锁 保证了多服务节点的序列号唯一(目前1.0.0的问题如果当前序列号大于了最大时间,Theta 会帮助我们重置最最大个数的,于此同时为了防止出现问题我们还会判断此时的更新时间,判断当前 的序列号配置是否再之前被其他线程重置过,当然这个方法不是一个最终的解决办法,我最终可能会按照Leaf 的双Buffer实现方式继续优化)。
关于使用和源码:https://github.com/zBo1997/Theta 希望各位大佬手下留情,觉得这个项目是你想象中“segment”不妨提出issue,或者点个start 完善Theta
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。