借鉴
分布式id算法有很多,当前是借鉴美团的Leaf-segment 因为需要递增.所以将子增放在了redis中进行,当redis挂掉的时候只会丢失一个setp数据。
算法思想
- 本地缓存业务id对应的最大值,子增后直接对比本地最大值(或者采用lua脚本redis中直接对比,并返回下一个id);
- 数据库中保存每个业务id对应的最大值和步伐;
- 第一次获取的时候将该业务id的最大值和step缓存到redis中(hset结构,currentId,maxId);
- 服务通过hincrby子增 获取当前的id 然后后对比本地最大值(重复1步骤),如果大于最大值了(或者当达到某一个比例的时候进行异步的重置最大值),进行加锁重置
模型

实现地址
可以通过下面三个地址下载核心代码
- sequment
- sequence-api
- sequence-client
- 如果代码不全的话可以通过初始化代码拉去全部代码内部包含子增部分
代码有待优化部分
- 当前采用的结构是本地缓存最大值
- 本地缓存最大值采用google的guava中带有过期时间的集合进行保存,防止积攒大量无用的key
- 如果采用redis中进行比较,构建一段lua脚本在获取下一个id的时候对比以下最大id如果小于直接返回,否则-1,进行加锁,更新最大值,并且返回当前id
- redis存储结构优化
- 当前使用string数据结构单独存储key子增和最大值 如果redis 使用的是分片模式会,有可能导致不能进行原子操作,最大值和当前值分布在不同的redis机器上面
- 这里需要将tag redis中的描述修改为hset结构,这样可以将该配置锁定在一个redis节点中,进行可以进行(lua脚本)原子操作行为
- 更新最大值
- 当前采用的是到达最大值了进行更新
- 后续可以采取当到达50%的时候进行开启线程异步更新最大值,这样可以防止到达最大值的时候全部卡提高效率
文章介绍了如何借鉴美团的Leaf-segment算法实现分布式ID,重点在于使用Redis进行递增操作,并通过本地缓存和lua脚本保证对比与更新的原子性。当ID达到最大值的50%时,异步更新最大值以提高效率。
4370

被折叠的 条评论
为什么被折叠?



