如何在并发场景下安全设置实例编号

2021-07-02 10:53:55 +08:00
 Fu4ng
遇到一个不大不小的问题,虽然目前这个方法能解决一般场景。
但总觉得有更巧妙的解法。

背景:
需要保证服务实例编号唯一,
如果是实例编号重复,则有风险产生重复的编号

目前解决办法:

实例初始化时,按序执行以下步骤
1.无脑 setNX(key,0,永不过期),确保实例能取到值
2.val := incrby(key,1)
3.对 val 取余 1000,设为实例编号

存在问题:
1.如果在一台实例挂了 1000 次,则会和其他实例编号重复
1730 次点击
所在节点    程序员
12 条回复
BBCCBB
2021-07-02 11:00:23 +08:00
snowflake 吗?

1. 如果在同一个局域网, 可以用 ip 来判定吧?
2. 启动时数据库插入一条纪录. 可以参考 uid-generator
3. zk 这种? 参考美团 leaf.
swulling
2021-07-02 11:13:35 +08:00
UUID4 就挺好的,唯一 ID 除非业务真的有需求(比如单调递增),否则建议都用 UUID 。
Fu4ng
2021-07-02 11:18:21 +08:00
@BBCCBB 感谢老哥。
1.因为跨机房所以不能用第一个方法。
2.引入数据库有点太重了。
3.不想引入太多依赖,在想能不能只使用 redis 解决。
yufpga
2021-07-02 11:48:40 +08:00
我不明白为什么要取余数. 按照现有的逻辑,可以在 redis 中维护一个已使用的编号集合,先取号,然后 sadd {:key:} {:取的号:}, 如果 sadd 返回值是 1, 说明该号没有被占用,取号成功; 如果返回值是 0,说明该号已被占用,取号失败,就继续取。关键在于要处理实例下线之后,要将下线实例从集合中剔除。
cpstar
2021-07-02 11:58:07 +08:00
实例编号,UUID 一劳永逸。
递增的编号,除了人阅读起来好看,机器处理起来,1 和 2 这两个实例,哪台设备能知道这两个是有所谓的先后顺序,就是两个字符而已。
err1y
2021-07-02 12:05:09 +08:00
uuid
Fu4ng
2021-07-02 12:43:56 +08:00
@yufpga 业务逻辑里生成的单号 留给实例编号的位数 的三位
Jooooooooo
2021-07-02 15:14:04 +08:00
搜一下雪花

如果不太要求长度, 拿到当前时间(毫秒) + 设备自身编号 + 随机数 几乎不可能重复
aitaii
2021-07-02 15:18:47 +08:00
雪花算法,分布式部署,加上机器号唯一标识,一毫秒生成 4194304 个不同 id
链接: https://zhuanlan.zhihu.com/p/85837641
atalia
2021-07-02 16:13:39 +08:00
为什么要取余 1000,只有 3 个字符串大小的编号吗
clf
2021-07-02 16:29:11 +08:00
雪花算法+1

自定义 workerId 和 datacenterId,我一般用 datacenterId 区分服务器,workerId 区分业务;生成的 ID 呈现增长趋势,存入数据库后检索效率也不错。
sunjiayao
2021-07-02 16:49:57 +08:00
取硬件 CPU 的序列号去 Redis 注册下吧。自己实现个自增序列号
如果一台机器部署多个服务需要手动配置下服务编号(或者根据序列号 + 服务监听的端口作为硬件唯一标识)

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

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

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

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

© 2021 V2EX