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

2023-07-25 14:53:59 +08:00
 jiobanma

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

9648 次点击
所在节点    Java
114 条回复
daye
2023-07-26 11:24:42 +08:00
哈哈,改算法把 workId 放到 id 尾部的方式是不符合 OP 要求的递增,我的方案对项目改动最小
aragakiyuii
2023-07-26 11:25:41 +08:00
uuid version1
sillydaddy
2023-07-26 11:25:54 +08:00
「代码中存在大量的根据雪花算法生成的 id 排序比大小的操作」。
问题是,你把 workerID 改了,也不影响这种排序比较啊!!因为对于分布式应用来说,数据的产生本来就没有绝对的先后顺序。无论你怎么设置新生的数据的顺序,都是合理的啊!

你们公司的应用,对 2 台机器产生的新数据的排序标准是啥?
你们公司的应用,需要按照绝对时间来排序吗?
你们公司的应用,是抢票程序吗?
你确定,绝对时间存在吗?
daye
2023-07-26 11:26:12 +08:00
@Aresxue 哈哈,改算法把 workId 放到 id 尾部的方式是不符合 OP 要求的递增,我的方案对项目改动最小
vevlins
2023-07-26 11:35:23 +08:00
严格递增,提前生成一批放在 redis 里面,每次 pop 出来一个呢
pkwenda
2023-07-26 11:41:25 +08:00
@trzzzz 因为分表了
leonshaw
2023-07-26 11:43:53 +08:00
@zhh0000zhh #94 严格来说问题本身就是不准确的,两个类空间隔的事件在不同参考系看来可能有不同的顺序(两台相对静止的服务器所处引力场不同,参考系也会不同),所以分配 ID 应该以哪个参考系观测到的顺序为准?回答了这个问题就等于引入了一个参考系作为仲裁。
sillydaddy
2023-07-26 11:45:53 +08:00
我能想像到,这个困境的大概来源了:

OP 公司的代码逻辑很可能是,用 id 的大小比较,去作为事件发生先后(时序)的依据。

这种代码逻辑,当然可以用全局递增的 id 这种方案来解决。不过也可以用其他方案来解决啊,比如保证后续任务的 id 比前置任务的 id 要大,即使分配到了不同的负载。例如可以在一台机器上提前生成任务的 id ,把 id 传递给其他负载。

用全局递增 id 的方案来解决,相比之下就是傻大黑粗!
zpfhbyx
2023-07-26 12:12:48 +08:00
自己写个 list 啊. 然后线性生成 id 扔到 list 里面. 都从这个取就行了.无非就是维护一个池子..
ashuai
2023-07-26 13:19:48 +08:00
给服务器 id ,强性伸缩的话用自发现服务分配 id ,一个 byte 循环用就行,所谓的全局唯一 id 用服务器 id 加时间戳就行
yaodong0126
2023-07-26 15:22:54 +08:00
@mineralsalt 多运行一个服务和使用 redis 加锁有本质区别,之所以使用 ID 生成服务,那就说明业务使用 redis 已经无法满足当前需求,你觉得没区别是因为你的业务量级并没有达到需要一个 ID 生成服务的程度

另外,你说的几个缺点,如果一个公司的业务到达这个规模,还在纠结几百兆内存的话,那还是倒闭算了,而且谁也没有规定这个服务必须使用 java ,你觉得 java 消耗内存,那选择其他的就是了

你最后提到的一点,“但是一个小项目”,显然和题主的需求严重冲突,没必要强行回答,甚至于说一个小项目我连 redis 都不需要就可以实现一个唯一 ID 生成的功能
qingshengwen
2023-07-26 16:52:44 +08:00
@jiobanma #49 并不能理解,我的意思跟 @lovelylain 一样,时间戳是在最高位的,一定能做到大致自增。所以得看你雪花算法的具体实现
bisyao
2023-07-26 20:51:23 +08:00
用 zookeeper 。它就是为了解决此类问题(全局序 total order) 而生的。
bisyao
2023-07-26 20:53:40 +08:00
如果不要求全局序,可以考虑使用 lamport timestamp ,保证因果顺序。

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

https://yangjunhui.monster/t/959560

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

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

© 2021 V2EX