1
hbolive 2020-12-26 16:51:54 +08:00
单纯依靠算法,16 还是 18 位,都没法保证吧重复吧。
所以应该有其他机制校验下生成的 ID 是否重复。 |
2
laminux29 2020-12-26 16:55:08 +08:00
为啥订单号就不能老老实实从 1 开始自增?为啥订单号就不能常见的无符号 32 位整型?
|
4
pxw2002 2020-12-26 17:02:13 +08:00 via Android
有几位根据日期时间生成
就不会重复了吧 |
7
Aluhao OP @laminux29 自增要先写数据库,很多多业务是先拿订单号请求接口成功后才写入数据库。
还有就是自增从 1 开始,容易被人查数据。 |
8
jimmyismagic 2020-12-26 17:11:59 +08:00
业务方的订单号和你内部的订单号完全可以分开啊,重复就重复呗
|
9
Aluhao OP @jimmyismagic 这个就是内部订单号,不能重复的。
|
10
jimmyismagic 2020-12-26 17:22:04 +08:00
@Aluhao 所以他到底是甲方还是乙方?乙方糊弄过去就行了,甲方就怼回去,不懂瞎指导
|
11
bsg1992 2020-12-26 17:24:44 +08:00
时间戳 不就解决了吗
|
12
crclz 2020-12-26 17:28:38 +08:00 3
你说的 16 位是“个十百千万”的位吧,不是 bit 吧。
如果是 16 个字符,那么约束我猜就是前端 js 的 number 超过 53~54bit 就会损失精度吧。 一个解决方案是传字符串。 如果非要数字,也不是不可以。你去看看 snowflake 算法。https://github.com/beyondfengyu/SnowFlake/blob/master/SnowFlake.java 把第 18 行里面的几个东西改一下,就可以应对不同的位数,本质是(使用年限,机器数量,数据中心数量,每秒并发数量)的权衡。当然首先得去看看 showflake 的结构再来改。 |
13
Jooooooooo 2020-12-26 17:29:29 +08:00
用时间戳+机器码
每个机器上维护一个当前时间戳可用的序号 你并发不至于那么大 |
14
Aluhao OP @jimmyismagic 要拿内部唯一订单号去关联对方订单信息,要先请求传 16 位订单号过去。
|
15
xuanbg 2020-12-26 17:31:15 +08:00 1
魔改雪花算法,41 位时间戳不要动,10 位设备去掉,差不多就是 16 位数字了。
但是,我估计你要的是 yyyyMMdd+2 位业务代码+2 位 xx+4 位流水号,流水号还要加密的那种。在我的 github 里面有,请自取 |
16
DarkCat123 2020-12-26 17:31:32 +08:00
@laminux29 容易被人遍历数据,分析…… 而且不利于分布式数据库的 hash 分区。
原来的 18 位用的是 snowflake? 我建议要不要魔改下 snowflake, 牺牲一下时间来换位数降低(我记得原来的 snowflake 可以用 69 年)。 要不然考虑找个 md5 sha1 之类的 hash 之后转 hex 看看能不能到 16 位吧。 |
17
Aluhao OP @Jooooooooo 主要是只限制 16 个数字,长一点都好解决。
|
18
DarkCat123 2020-12-26 17:32:06 +08:00
@xuanbg 老哥好巧,我们同时提到了魔改 snowlflake……
|
19
jimmyismagic 2020-12-26 17:34:53 +08:00
@Aluhao 那你从 1 开始不就行了,对方唯一,需要你传的唯一,对方根本不关心你传的什么,楼上的 snowfake 一般用的很多,分布式 id 用的比较多,单机也没什么问题,16 位 50 多个比特完全够了
|
20
dorothyREN 2020-12-26 17:43:05 +08:00
13 位时间戳 加 3 位随机数或者 3 位自增数字
|
21
lmmortal 2020-12-26 17:43:26 +08:00 via Android 1
可以借鉴一下身份证号最后一位的校验算法
|
22
lin07hui 2020-12-26 18:03:19 +08:00
10 进制转 16 进制,不香吗
|
23
lawler 2020-12-26 18:23:14 +08:00
@dorothyREN #20 就这个方案里的自增就可以了。
@Aluhao #7 redis incr,mq 要觉得不行,不妨把解决 10w/tps 的方案分享出来? 要觉得可以遍历,不妨把不能遍历的纯数字索引方案分享出来? |
24
ytmsdy 2020-12-26 18:31:32 +08:00 via iPhone
时间戳,加两个随机数,外加一个校验位。绰绰有余了!
|
25
yuzo555 2020-12-26 18:40:12 +08:00
“容易被人遍历数据”这个不是自增的问题,是你们程序权限控制的问题
|
26
Soar360 2020-12-26 19:49:48 +08:00
20-1226-19-123456
|
27
dorothyREN 2020-12-26 20:16:37 +08:00
@lawler #23 13 位时间戳+3 位数字,1 毫秒 1000 个单号,肯定够用了
|
29
jimmyismagic 2020-12-26 21:24:38 +08:00
@jzmws js 太傻了,前端技术不行让后端想办法
|
30
dream7758522 2020-12-26 21:41:24 +08:00 via Android 1
很简单啊,时间戳→md5,16 位。→生成的 md5 中的 abcdef 用 123456 改写。
举例:0123456789012345→md5,16 位→199aa7dcadfdb4e4→其中的字母字母用 123456 替换→1991174314642454 。 觉得容易反算的话,可以加盐 |
32
Lemeng 2020-12-27 00:56:21 +08:00
重复 16 位 18 位都少。
|
33
catror 2020-12-27 01:36:49 +08:00 via Android
任何一个生成 int64 ID 的算法都行,int64 的 16 进制编码结果就是 16 位
|
34
mxT52CRuqR6o5 2020-12-27 02:25:49 +08:00 via Android
加密一个自增序列可以得到看上去随机的序列,不会重复,魔改加密算法让密文空间和明文空间在 16 位纯数字内
|
35
mxT52CRuqR6o5 2020-12-27 02:26:55 +08:00 via Android
要是没有随机性的要求的话直接魔改 snowflake 就是了
|
36
hijoker 2020-12-27 04:09:34 +08:00
13 位毫秒数+3 位随机数, 数据库这个字段设置类似唯一约束的东西, 如果真有重复,插入报错,根据报错信息重新生成随机数并重试插入
|
37
oneisall8955 2020-12-27 09:28:48 +08:00 via Android
@jzmws #28 我公司 long 类型都转字符串出去给前端了
|
38
mostkia 2020-12-27 12:38:31 +08:00
一般都时间戳+盐保证唯一性
|
39
neptuno 2020-12-27 13:46:31 +08:00
时间戳+(用户 id 转成 3 位数)?是不是最简单+重复率低
|
40
ciddechan 2020-12-28 09:04:41 +08:00
@dream7758522 这种的会不会分不出是真的 123456 还是替换的 123456
|
41
wangritian 2020-12-28 09:29:13 +08:00
1.雪花算法:毫秒时间戳+集群号+机器号+进程号+自增序号
这里最关键的是进程常驻,需要 swoole/workerman 插件 2.额外写一个单实例部署的 id 生成器,加锁单线程运行,性能没有 1 好 |
42
nano91 2020-12-28 10:18:32 +08:00
16 位 MD5 ?拿老 18 位订单号做一次转换
|
43
afewok 2020-12-28 13:09:11 +08:00
但凡深入调研下业界和 github,都不会问出这个问题。
|