包含时间顺序的ID
此场景最简单的实现方案,就是采用 twitter 的 Snowflake 算法。
ID总长64位,第1位不可用,41位表示时间戳,10位表示生成机器的id,后12位表示序列号。
- 为什么第一位不可用?第一位为0,可以确保ID在java的long类型数据一直为正整数递增
- 同一时间戳即毫秒内,能产生多少个ID? 2^12 = 4096 个ID [ 0 ~ 4095 ]
- 唯一性?通过机器ID预先已经做了一次空间隔离,再通过时间戳做了一次时间隔离,最后通过时间戳内的计数实现了一定程度内的唯一
- 高性能?可以通过增加IDWorker来缓解高并发时的单机负载压力
- 缺点?时间受限,41位可以表示69年(不过可以减少机器位来增加时间位数)
自增序列
原理
根据key获取分布式锁,获得锁后取得序号,并偏移配置的偏移量,替换原先的序号,最后释放锁。
基于zookeeper实现
基于zookeeper可以很快实现自增序列服务,引入apache的curator封装的zookeeper客户端。
|
|
建立zookeeper连接,打开zkclient后,如果重复会使用,可以将其放入全局map中,作统一管理。
address:zookeeper的地址
RetryNTimes:重连策略(重连重试次数,重连间隔毫秒)
|
|
获取分布式锁
按照业务逻辑,选择合适的锁,此处用的是可重入共享锁,即一个客户端在拥有锁的同时,可以再请求获取。
大专栏 分布式全局唯一ID与自增序列="gutter">
|
|
获取下个序号
判断序列名称是否已经存在,如果不存在创建,存在则增加step并写入
creatingParentsIfNeeded:当zk节点的父级不存在的时候,迭代创建
sequenceName:序列名称
step:自增步长
|
|
因为需要实时修改zookeeper的节点信息,可以考虑建立序列池,例如直接取走10000个序列,由各个服务内部自己去生成,具体实现主要依赖到CAS,通过compareAndSet去实现单机内部的序号递增,避免锁的滥用
来源:oschina
链接:https://my.oschina.net/u/4324543/blog/3332663