import random
class IDGenerator:
@classmethod
def gen_primary_id(cls, length=11):
prefix = random.choice('123456789')
return prefix + ''.join([random.choice('0123456789')
for i in range(length)])
据说系统运行了几年,没碰见过碰撞的情况。我感觉我数学没学好,谁能告诉我这是哪一块的知识
1
GM 2021-04-25 18:36:40 +08:00
你什么意思?明天来我办公室一下!
/狗头 |
2
xupefei 2021-04-25 18:37:39 +08:00 via iPhone
高中数学,排列组合。
|
3
thevita 2021-04-25 18:39:19 +08:00
数据量多吗
|
4
0DBBFF 2021-04-25 18:40:56 +08:00
我数学也不太好,是 9 * 10 的 11 次方吗? 这么多感觉碰撞几率是不是也不高啊
|
5
guisheng 2021-04-25 18:41:35 +08:00 via iPhone
随机用到了极致
|
6
snw 2021-04-25 18:41:36 +08:00 via Android
不怕碰撞吗?生成 10 万个 ID 大约有百万分之一概率发生碰撞。
|
7
skyleft 2021-04-25 18:46:26 +08:00
性能很差,b+tree 节点大量页分裂
|
8
sujin190 2021-04-25 18:48:02 +08:00
好歹加个日期啊,不会随着使用时间变长碰撞概率变高,所以楼主你想说的其实是你们司系统没啥人用的意思么,哈哈哈
|
9
EPr2hh6LADQWqRVH 2021-04-25 18:48:48 +08:00
主键都唯一的,重复数据库就抛错了,用户一重试随机到别的就过了,不是没碰撞过,是没引起注意。
|
10
ch2 2021-04-25 18:49:26 +08:00 7
但凡他知道有个包叫 uuid
|
11
wellsc 2021-04-25 18:50:52 +08:00 via iPhone
简单实用,不需要任何第三方包就解决需求
|
12
janxin 2021-04-25 18:53:29 +08:00 8
没毛病,不要动
赶紧提离职 |
13
labulaka521 2021-04-25 18:58:11 +08:00
能跑就行
|
14
fucku 2021-04-25 19:03:07 +08:00
又不是不能用
|
15
Vegetable 2021-04-25 19:10:10 +08:00 3
哪怕是这个功能,我也会使用 str(randint(10**length,10**(length+1)))
|
16
mixz 2021-04-25 19:10:16 +08:00
简单快速,赞
|
17
gstqc 2021-04-25 19:11:32 +08:00 via Android 2
贵司还没倒闭说明还是有两把刷子的
|
18
CallMeReznov 2021-04-25 19:12:54 +08:00 4
|
19
imjamespond2020 2021-04-25 19:23:23 +08:00 via Android
改成 ubixtimestamp-uuid
|
21
Jooooooooo 2021-04-25 19:34:49 +08:00
可以用抛唯一键冲突重试的方法解决
|
22
sillydaddy 2021-04-25 19:47:44 +08:00 via Android
@snw #6
概率应该比百万分之一高多了。对应的概率计算参考“生日问题”: https://zh.m.wikipedia.org/wiki/%E7%94%9F%E6%97%A5%E5%95%8F%E9%A1%8C 我估计生成 10 万个 id 发生碰撞的概率应该大于千分之一。 |
23
jeffwcx 2021-04-25 20:43:24 +08:00
哈哈,这还不如 uuid 呢,如果需要 id 的顺序性可以用 snowflake
|
24
snw 2021-04-25 20:51:39 +08:00
@sillydaddy
我刚才公式拉错了。用 excel 又模拟了一遍,10 万个 id 碰撞概率大约 4.877%。 |
25
mind3x 2021-04-25 21:02:59 +08:00 via Android
@sillydaddy 根据近似公式 1-1/exp(n^2/(2N)),n=10 万,N=900000000000,概率大于千分之 5 了。
|
27
mind3x 2021-04-25 21:06:42 +08:00 via Android
@v2exblog 就在 @sillydaddy 贴过的 Wikipedia 连接里
|
28
pkupyx 2021-04-25 21:28:29 +08:00
也许数据库上有唯一索引重复就回滚吧
|
29
jdandelion573 2021-04-25 22:09:40 +08:00 via Android
说明数据库没人用
|
30
ila 2021-04-25 22:13:32 +08:00 via Android
要看其它代码
|
31
ytmsdy 2021-04-25 22:47:36 +08:00 6
冲突肯定是发生过的,只不过无法复现罢了!
|
32
lightingtime 2021-04-26 00:07:31 +08:00
判断一下使用场景啊,qps 如果只有几,那么碰撞了就重新生成 a
|
33
george404 2021-04-26 08:01:09 +08:00
不得不佩服,大道至简,哈哈!!
|
34
auh 2021-04-26 08:12:32 +08:00
这一看就是组长干的事情。往往小兵在没有征得老大同意的情况下,是不敢这样操作的。
|
35
wunsch0106 2021-04-26 08:48:31 +08:00
我甚至觉得这是个段子
|
36
jetyang 2021-04-26 08:50:29 +08:00 1
重复了会插入报错,报错就再生成一个,大家不都是这么做的吗?抠鼻
|
38
securityCoding 2021-04-26 08:57:18 +08:00 via Android
233 还不如直接时间戳呢
|
39
dangyuluo 2021-04-26 08:58:52 +08:00
虽然代码很烂,但是公布自己就职公司的代码(勉强算得上是算法)好么?
|
40
soulzz 2021-04-26 09:00:16 +08:00
赶紧跑路
|
41
weizhen199 2021-04-26 09:02:45 +08:00
@skyleft 你这么一说我突然好奇了。很多时候都会用 guid 来做主键。这样效率会很低?
|
42
HashV2 2021-04-26 09:06:15 +08:00
return str(random.randint(10**10, 10**11-1))
|
43
HashV2 2021-04-26 09:06:41 +08:00
快跑吧
|
44
jinhan13789991 2021-04-26 09:19:42 +08:00
失败了再重试啊,总会成功的。而且及时发现了问题,也很难复现。
有可能这个项目是压缩了开发周期,当初做他的程序员为了尽早完成。 |
45
Leviathann 2021-04-26 09:22:14 +08:00 via iPhone
为什么就是不想用自增 id
|
46
Felldeadbird 2021-04-26 09:24:41 +08:00
没说数据量啊。到百万或者千万 应该会出现过碰撞啊。
|
47
Rache1 2021-04-26 09:26:15 +08:00
python 这个 for 语法糖,真酸爽
|
48
zjsxwc 2021-04-26 09:29:06 +08:00
id 冲突了就 rollback 吗
2333 |
50
MinQ 2021-04-26 09:36:26 +08:00
我自己的方案是 snowflake 的 timestamp 设定一个 19 年的时间,然后往前位移 N 位缩短长度,最后转 Base32 截取,这样只需要 1X 位字母数字就能拿来做主键了
要是觉得 Base32 看着不爽可以对着码表自己做个转换 |
51
tabris17 2021-04-26 09:44:13 +08:00
说明贵司业务量不大
|
52
tankren 2021-04-26 09:53:33 +08:00
uuid 有现成的吧
|
53
ganbuliao 2021-04-26 09:56:41 +08:00 1
你们有日志吗?我觉得是碰撞到了了你们也不知道。就是插入数据报错,客户重试一下就好了还以为是网络抖动 、、):dog
|
54
domodomo 2021-04-26 10:03:43 +08:00
说明你们公司挺小的……
|
56
echowuhao 2021-04-26 10:23:57 +08:00
如果每个表不大,看不出什么问题。
拿出来讨论的都是大公司的问题,其实大部分是小公司,没有那么多数据,如果在分库分表,那就更少了。 |
57
37Y37 2021-04-26 10:36:15 +08:00
简直神了,我都没想到这方法
|
58
msg7086 2021-04-26 10:42:35 +08:00
随机生成主键嘛,除了代码烂一点以外没啥问题。
我如果需要随机主键我也会这样生成(当然不会写成这屎样就是了)。 碰撞是小问题,重试就行。 |
59
Cy1 2021-04-26 10:43:43 +08:00
@weizhen199 guid 相比自增 ID 效率上肯定会低,但很低也不至于。既然选择了 guid 了,就别幻想有自增 ID 一样的性能了,底层的数据结构本身就决定了这个时候
|
60
lichdkimba 2021-04-26 10:49:38 +08:00
用户够少就不会有任何问题!
|
61
preach 2021-04-26 11:00:36 +08:00
握草 牛比 我居然还 copy 试了试
|
63
Vegetable 2021-04-26 11:14:47 +08:00
|
64
joyhub2140 2021-04-26 11:37:10 +08:00
加点时间戳啊还是能用的,但扛不住高并发,不过这个系统几年下来都没碰撞,应该没啥人用吧
|
65
tairan2006 2021-04-26 11:39:01 +08:00
@MinQ mysql8 已经有 uuid 和 binary 互转了
|
66
Huelse 2021-04-26 11:40:56 +08:00
random 模块产生碰撞的概率还是很低的,其本身就能规避一段时间问题
希望有大佬能通过数学方式考证下,楼上有几位的公式感觉少考虑了一些影响因素 |
67
jsuly 2021-04-26 11:48:38 +08:00
我很好奇, 为什么要自己生成主键呀,不是都是主键,自增吗
|
68
Latin 2021-04-26 11:50:47 +08:00
人家离职的原因就是不想堆屎山了吧
|
69
MinQ 2021-04-26 11:57:02 +08:00
@tairan2006 看到了,那个还是挺方便的,虽然公司还在用 5.7
|
70
wsseo 2021-04-26 12:37:27 +08:00
楼主跑路把
|
71
pepesii 2021-04-26 12:37:57 +08:00
你这就没明白了把,哈哈,这是明年的优化点,不然哪儿来的 KPI
|
72
hahastudio 2021-04-26 13:12:34 +08:00
说起来,这么写和直接随机数字的区别是什么?
怎么直觉上这种会更容易被碰撞 |
73
fareware 2021-04-26 13:36:33 +08:00
这个设计的问题有两个
1. 碰撞。这个还可以通过改代码来立即解决 2. 数据库。使用 b+ 做索引的关系型数据库的性能问题,这个最严重,后期想优化更是难受。 |
74
sss495088732 2021-04-26 13:40:26 +08:00
0.0 说实话这种生成唯一主键的是不是大家都用雪花算法....还没有遇到过性能问题
|
75
MinQ 2021-04-26 14:10:12 +08:00
@sss495088732 主要是好调好写,可以自己定制,最多依赖一个 zookeeper 或者 redis
|
76
Cloutain 2021-04-26 14:12:16 +08:00
无序主键对于数据库是个考验 哈哈哈
|
77
oolovexx 2021-04-26 14:15:58 +08:00
随机,可以的,牛批
|
78
3dwelcome 2021-04-26 14:16:17 +08:00
相同的主键没办法写入两次,数据库没冲突,是正常的。
楼主的代码应该只贴出了一小半,如果冲突,大概率会重新生成一次。这样速度也不慢。 |
79
JokeEnd 2021-04-26 14:37:01 +08:00
用雪花算法
|
80
TimPeake 2021-04-26 14:38:47 +08:00
我一个前端都知道弄个时间戳还能一定程度防止重复。。。。。
|
81
KouShuiYu 2021-04-26 15:35:29 +08:00 1
说的应该就是我🐶
```js function getRandomStr(len) { const dictionary = '0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*()_+~:;,./<>?'; const dictionaryLen = dictionary.length; let str = ''; for (let i = 0; i < len; i += 1) { str += dictionary[Math.floor(getRandom(dictionaryLen))]; } return str; } ``` |
82
xiaochong0302 2021-04-26 15:48:45 +08:00 1
我懒鬼订单号:$this->sn = date('YmdHis') . rand(1000, 9999);
没有大量用户高并发,这样又不是不能用,大不了后面再加一段随机数。 |
83
nanjoyoshino 2021-04-26 17:05:13 +08:00
这个可真的是太强了,点进来之前我完全没想到是这种方法
|
84
watzds 2021-04-26 17:06:03 +08:00
怎么把核心代码公布出来了! 😄
|
85
Wincer 2021-04-26 17:25:00 +08:00
第二天楼主因为公开核心代码被开除了
|
86
roudancongji 2021-04-26 18:04:45 +08:00
估计碰撞了就加个 retry,再来一遍
|
87
johnsona 2021-04-26 20:05:40 +08:00 via iPhone
@weizhen199 不然别人发明各种分布式 id 干嘛
|
88
johnsona 2021-04-26 20:06:12 +08:00 via iPhone
@roudancongji 好家伙 哈希碰撞策略被你学明白了
|
89
l1ve 2021-04-26 21:03:23 +08:00
if repeat {
retry() } print("get random successful") |
90
luwill 2021-04-26 22:06:00 +08:00
uuid-4 变种
|
91
opengps 2021-04-26 22:24:41 +08:00
别说的一无是处,这种自造逻辑有个天然优势就是自带防猜解特点
|
92
cabing 2021-04-26 22:37:16 +08:00
插入失败 retry 就行。设计的有点东西,一般人绝对想不到如此有趣的设计。
内网系统估计也没多少条数据。 |
93
hanxiV2EX 2021-04-26 22:38:47 +08:00 via Android
如果这个是用来生成用户 id,且用户量不大,比如内部的后台系统,那没啥大毛病,注册失败再重试一下,哈哈哈哈。
|
94
cogitoxin 2021-04-27 07:51:35 +08:00 via iPhone
叹为观止
|
95
ccppgo 2021-04-27 09:18:56 +08:00
@xiaochong0302 哈哈哈, 只要没有分库分表, 直接弄个唯一索引, 报错就重试
|
96
wangyzj 2021-04-27 09:54:11 +08:00
多大数量啊?
|
97
echoZero 2021-04-27 09:56:34 +08:00
跑就对了,不然你就会知道 mysql 主键不是自增时插入效率到底有多低。DBA 天天追着你进行优化
|
98
fanyingmao 2021-04-27 20:26:42 +08:00
又不是不能用,反正项目赚不赚钱和代码写得好坏关系不大。
|
99
linyinma 2021-04-28 09:29:34 +08:00
抛开业务谈代码都是耍流氓,存在必有其合理性
|
100
zhuweiyou 2021-04-28 10:15:17 +08:00
公司内部系统, 一共就老板和测试两个人会访问, 没毛病
|