分布式系统生成全局唯一 ID 的方式请教

288 天前
 jiobanma

咨询各位大佬们一个问题目前有两台服务器负载,使用 apache 的 SnowflakeShardingKeyGenerator 生成雪花算法作为 id ,业务上需要生成的 id 是递增的。 之前两台服务器的 SnowflakeShardingKeyGenerator 的 workId 都是默认的,高并发情况下,两台服务器的时间可能会有误差 就会导致生成的 id 是重复的。但是两台服务器根据不同的 workId 去生成虽然能解决重复的问题,但是会导致生成的 id 不是连续递增的。 有什么其他的方式实现吗(排过坑的[旺柴])。

8295 次点击
所在节点    Java
114 条回复
my3157
288 天前
用一个专门的服务批量生成 ID , 其他服务直接从这个服务拿
mineralsalt
288 天前
没用过 SnowflakeShardingKeyGenerator, 但是如果是我实现这样的需求, 能想到 2 种办法, 第一就是 redis 加锁, 但是会影响并发效率. 第二种就是发现 id 重复时递归生成一次,直到不重复为止
mineralsalt
288 天前
1L 这种多引入一个服务感觉太重了, 多一个服务就多一份负担和不稳定性, 不是太优雅
thevita
288 天前
2L 提的第一个方法与 1L 本质上是一样的,都是引入一个全局一致的协调者(目前看这其实是比较现实的办法,功能简单,稳定性和性能应该能做很多优化,当然具体看你场景能否接受)
thevita
288 天前
2L 第二种也是一个办法,相当于 用 db 作为一致性保证?,乐观冲突检测的方式来做,但是 db 的事务的貌似还是得依赖全局锁的方式来支持 insert id 有序
zhzy0077
288 天前
2 台服务器能承载的业务直接用数据库的 auto increment 不行吗
CocaCola001
288 天前
我觉得还是新建一个服务用来生成 id 比较好,后期也方便扩展
thevita
288 天前
还不如看看你的需求只是要 “递增“ 呢,还是真的需要严格的全局有序
SenLief
288 天前
有没有考虑过最简单的方案,使用一个大数,一台往上递增,一台往下递增
luciankaltz
288 天前
> 两台服务器的时间可能会有误差 就会导致生成的 id 是重复的

snowflake 算法初始化的时候会填入一个 machine id ,为什么两台服务器上生成出来的 id 会重复呢(
还是说你故意设置成了一样的 machine id ,是希望所有生成出来的 id 在全局上单调递增并且唯一?

如果是的话那就必须引入一个单点的算号服务,不管是一个 app 服务还是 db 的自增
veike
288 天前
ulid 可行?
Masoud2023
288 天前
想了半天为什么这东西能重复,一仔细看帖子原来没改 workerId...

你如果非想要连续递增的 id ,那么只能考虑做个服务专门搞这种自增

是不是某些架构设计出问题了,感觉不应该有这种问题..
thevita
288 天前
想到一个比较破的方案:

就是你在 db 里面 预先 “生成, 分配” 一批 id (假设这里你的 全局有序 id 是主键)

这样就能让服务来`抢` next id, 对 行加锁了,并发应该会好一些,

就是不能回滚,需要让签名的 id 失效
jiobanma
288 天前
@mineralsalt #2
@thevita #4
@CocaCola001 #7 这个比较简单 缺点就是可能会有性能问题已经服务掉线之后的问题
@luciankaltz #10 目前都是默认的 没有传参,所以你说的 machine id 应该是个默认值,两台服务器应该是一样的值
@veike #11 uuid 缺点太多了
nekolr
288 天前
大致上是趋势递增的就可以了呀,或者像楼上几位说的,独立出来一个服务
dw2693734d
288 天前
@jiobanma 能讲讲 uuid 缺点吗
bugmakerxs
288 天前
https://github.com/Meituan-Dianping/Leaf/blob/master/README_CN.md
为什么要连续?简单点引入这个就行
nekolr
288 天前
@nekolr 没注意看楼主要求,楼主想要的是严格的单调递增是吗?如果是用雪花的话,那只能独立出来一个服务
silentsky
288 天前
很简单的事情 搜 Redisson IdGenerator
bugmakerxs
288 天前
另外的简单方案是 timestamp + (redis.incr(key) % 100000)
服务器时钟用 ntp 同步

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/959560

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX