原始雪花算法
雪花算法是twitter提出的分布式id生成器方案,也叫发号器方案。这里简单介绍下雪花算法
这个就是原生的雪花算法分配
- 41bit时间戳:这里采用的就是当前系统的具体时间,单位为毫秒
- 10bit工作机器ID(workerId):每台机器分配一个id,这样可以标示不同的机器,但是上限为1024,标示一个集群某个业务最多部署的机器个数上限
12bit序列号(自增域):表示在某一毫秒下,这个自增域最大可以分配的bit个数,在当前这种配置下,每一毫秒可以分配2^12个数据,也就是说QPS可以到 409.6 w/s。
存在的问题
时间回拨问题:由于机器的时间是动态的调整的,有可能会出现时间跑到之前几毫秒,如果这个时候获取到了这种时间,则会出现数据重复
- 机器id分配及回收问题:目前机器id需要每台机器不一样,这样的方式分配需要有方案进行处理,同时也要考虑,如果改机器宕机了,对应的workerId分配后的回收问题
机器id上限:机器id是固定的bit,那么也就是对应的机器个数是有上限的,在有些业务场景下,需要所有机器共享同一个业务空间,那么10bit表示的1024台机器是不够的。
业内方案
业内的方案中对以上三个问题有这么几种处理,但是都没有彻底解决,我们这里表述下
1.时间回拨问题:
采用直接抛异常方式:这种很不友好,太粗暴
采用等待跟上次时间的一段范围:这种算是简单解决,可以接受,但是如果等待一段时间后再出现回拨,则抛异常,可接受,但是不算彻底解决
2.机器id分配及回收:
采用zookeeper的顺序节点分配:解决了分配,回收可采用zookeeper临时节点回收,但是临时节点不可靠,存在无故消失问题,因此也不可靠
- 采用DB中插入数据作为节点值:解决了分配,没有解决回收
3.机器id上限
该问题在业内都没有处理,也就是说如果采用雪花算法,则必定会存在该问题,但是该问题也只有需要大量的业务机器共享的场景才会出现,这种情况,采用客户端双Buffer+DB这种非雪花算法的方案也未尝不可。
Butterfly方案
1.时间回拨问题
这里采用新的方案:大概思路是:启动时间戳采用的是“历史时间”,每次请求只增序列值,序列值增满,然后“历史之间”增1,序列值重新计算。具体方案请见后面的方案介绍
2.机器id分配和回收
这里机器id分配和回收具体有两种方案:zookeeper和db。理论上分配方案zk是通过哈希和扩容机器,而db是通过查找机制。回收方案,zk采用的是永久节点,节点中存储下次过期时间,客户端定时上报(设置心跳),db是添加过期时间字段,查找时候判断过期字段。
3.机器id上限
这个采用将改造版雪花+zookeeper分配id方案作为服务端的节点,客户端采用双Buffer+异步获取提高性能,服务端采用每次请求时间戳增1。
以上是方案的简述,对于方案的具体实现请看方案介绍
