PHP+mysql+redis 一次性生成大量随机数,咋保证重复率低、快速存储

生成的时候做过去重了,插入时为何还有重复?把重复率控制在较低的水平,唯一索引引起的插入失败,不会影响整体性能。

■网友
Redis的集合(set)本来就可以保证唯一,也就是sadd无法插入一个已经存在的元素到集合里去.
至于MySQL,为了避免插入重复的值违反唯一约束导致出错,可以在INSERT中使用ON DUPLICATE KEY UPDATE.
假设有一个表test(自增id, 唯一name):
INSERT INTO test(name) VALUES(\u0026#39;foo\u0026#39;), (\u0026#39;bar\u0026#39;) ON DUPLICATE KEY UPDATE name = VALUES(name);
■网友
时间戳,以秒为单位是 10 位数,取毫秒,就是 13 位数。
随便丢一个7位数的随机数拼起来,满足每天十万个的需求还是很简单的,重复的可能性无限为0。

至于要求尽量不连续,这个方法就太多了:
把7位随机数放在开头把13位数调换一下顺序把7位随机数按照特定的规律分散插到13位中间去(可能稍微增加一点计算资源)
避免重复的思路其实很简单,就是尽可能引入多个变量。比如 UUID,其由多个部分组成,分别是 日期时间,时钟序列,机器识别号。单一变量容易重复,多个变量同时相等的概率就低多了。
我这个想法有两个变量:毫秒 + 随机数。两次取到相同的毫秒数,对单进程执行的PHP实例来说已经是很难了;不仅要取到相同毫秒数,还要刚好生成两个相同的7位数的随机数,在你的场景下就几乎不可能。





■网友
10万条记录,程序处理应该很快的。插入数据库的话会时间久一点。单线程插入在低配的云服务器大概一秒几百条(保守的话安200条估算);多线程插入的话可以用尽数据库的性能,每秒可以插入几千条(低配的服务器可以安2000或3000条每秒)。以上可以估算性能。如果直接在数据库里处理的话,那就更快了,先生成带自增字段的10万条记录(这个时间略长一点点,但是有些办法可以去到很快),然后update应该只要几秒就够了。去重的话方法很多。其它答案提到的自增加随机数实现起来非常简单又保证唯一。
■网友
前十位用唯一自增ID,后十位随机生成,组合起来20位

■网友
mysql可以为表生成大量的随机数:
1)产生0到10000间的随机数
  SELECT RAND()*10000;
  对应产生相应的整数
  SELECTFLOOR(RAND()*10000)
2)使用md5()产生32位随机字符串
  SELECTMD5(RAND()*10000)
  3)产生500-1000间的整形
  SELECTFLOOR(500+RAND()*(1000-500))


延伸:mysql随机取记录基本思路:随机排序。
select * from numbers order by rand() limit 1这行命令就可以从表中随机选择一条记录。如何是随机选择多条,如下
select * from numbers order by rand() limit 10

对随机数的介绍:https://medium.freecodecamp.org/a-brief-history-of-random-numbers-9498737f5b6c

■网友
服务器标识+时间戳+随机数,还可以满足你以后扩容了,不同服务器要编码统一的需要。

■网友
尽量不连续的话,可以考虑将年月日时分秒毫秒取出来进行自由组合,比如yyyy在20中的前四位组合排布类似,yyyymmdd hhmmss sss 已经17位了,剩下三位进行随机生成,只要确保这三位不一样,就可以了,一个简单比较就可以,不用从库中取数据(确保时间正确)

■网友
10万个20位数字的字符串而已,哪有那么多。
php一个20位字符串差不多是48个字节。算下来10万个也就4.6m左右的内存占用。你在内存中做去重不就好了,还要啥redis啊。


推荐阅读