全局唯一递增的id_分布式全局唯一ID与自增序列

包含时间顺序的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客户端。

1

2

3

4

org.apache.curator

curator-recipes

建立zookeeper连接,打开zkclient后,如果重复会使用,可以将其放入全局map中,作统一管理。

address:zookeeper的地址

RetryNTimes:重连策略(重连重试次数,重连间隔毫秒)

1

2CuratorFramework zkClient = CuratorFrameworkFactory.newClient(address,new RetryNTimes(10, 5000));

zkClient.start();

获取分布式锁

按照业务逻辑,选择合适的锁,此处用的是可重入共享锁,即一个客户端在拥有锁的同时,可以再请求获取。

大专栏  分布式全局唯一ID与自增序列="gutter">1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17InterProcessMutex lock = new InterProcessMutex(zkClient, lockPath);

try {

if (lock.acquire(time, unit)) {

consumer.accept(lockPath);

return true;

}

return false;

} catch (Exception e) {

logger.error(e.getMessage(), e);

} finally {

try {

lock.release();

} catch (Exception e) {

logger.error(e.getMessage(), e);

}

}

return false;

获取下个序号

判断序列名称是否已经存在,如果不存在创建,存在则增加step并写入

creatingParentsIfNeeded:当zk节点的父级不存在的时候,迭代创建

sequenceName:序列名称

step:自增步长

1

2

3

4

5

6

7

8

9String path = "/seq/"+sequenceName;

boolean exists = zkClient.checkExists().forPath(path) != null;

if (!exists) {

zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path, (step + "").getBytes());

} else {

byte[] bytes = zkClient.getData().forPath(path);

Long seq = Long.valueOf(new String(bytes));

zkClient.setData().forPath(path, (seq + step + "").getBytes());

}

因为需要实时修改zookeeper的节点信息,可以考虑建立序列池,例如直接取走10000个序列,由各个服务内部自己去生成,具体实现主要依赖到CAS,通过compareAndSet去实现单机内部的序号递增,避免锁的滥用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值