关于唯一随机字符串的讨论

聪明的一休 2012-01-12 03:17:10
最近有个需求,按批次生成一定数量的18位唯一随机字符串(数字,大小写字母组成)。
因为考虑到效率,不可能生成一个去表里遍历是否存在,所以我每个批次生成6位批次号,再用rand生成12位随机字符串放在批次号后面组成18位字符串,当然这样虽然大大减少了重复的可能性,还是不能保证完全重复,存储过程还是需要事务去保证以防主键重复。

不知道各位有没有什么更优的方法解决此类问题?
...全文
395 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
biandongfeng 2012-02-02
  • 打赏
  • 举报
回复
前面用年月日时分秒,后面加上你所需要的串
聪明的一休 2012-01-20
  • 打赏
  • 举报
回复
第一个问题,的确是你没理解我的意思,1000个随机串我只对流水号做一个一次检查,后12位并没做检查。

第二个问题,是我理解错了,我以为是用mysql的md5函数,因为当初发起这个讨论只是找数据库层面的解决方案。

[Quote=引用 8 楼 jiahehao 的回复:]

第一个问题,如果你对这1000个随机串的后12位都做唯一性检查,当然能保证唯一,但是会损失时间。而我的默认前提是只管生成,不管校验。所以在此前提下,你的这个批次号 + 随机串 会提高重复性。

第二个问题,我想你对RSA加密算法还不太了解。它所达到的效果就是和:“如果你不能解决随机字符串的唯一性问题的话,后面再加密也是徒劳的。”这句话是相反的。我在前面说过,哪怕是相同的一个随机串,进去加密后,出来的密文也是绝对不一样的。
[/Quote]
聪明的一休 2012-01-20
  • 打赏
  • 举报
回复
这是一种比较好的实现方式,我试了50万条记录

[Quote=引用 7 楼 shine333 的回复:]

如果只考虑唯一及均匀分布的话,不考虑效率的话,
CONCAT(
LEFT(CONV(CRC32(RAND()), 16, 36), 6), -- 前6位为rand的crc32的前6位,以36进制表示(0-9,A=10,Z=36)
LEFT(CONV(CRC32(UUID()), 16, 36), 6), -- 中间6位,用UUID
L……
[/Quote]
jiahehao 2012-01-17
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 wfevgch 的回复:]
关于重复的可能性,你可能还没理解我的意思,比如我一个批次生成1000个随机串,我先生成一个批次号,可以在批次表里检查唯一性,这样我只要保证后面12位在1000个中的唯一性,而不需要保证在全表中的唯一性了。所以是大大减少了重复的可能性。

至于你说的加密算法,如果你不能解决随机字符串的唯一性问题的话,后面再加密也是徒劳的。我们主要需要解决唯一性问题。当然如果我们先用唯一时间戳再MD5加密的话,和……
[/Quote]

第一个问题,如果你对这1000个随机串的后12位都做唯一性检查,当然能保证唯一,但是会损失时间。而我的默认前提是只管生成,不管校验。所以在此前提下,你的这个批次号 + 随机串 会提高重复性。

第二个问题,我想你对RSA加密算法还不太了解。它所达到的效果就是和:“如果你不能解决随机字符串的唯一性问题的话,后面再加密也是徒劳的。”这句话是相反的。我在前面说过,哪怕是相同的一个随机串,进去加密后,出来的密文也是绝对不一样的。
shine333 2012-01-16
  • 打赏
  • 举报
回复
如果只考虑唯一及均匀分布的话,不考虑效率的话,
CONCAT(
LEFT(CONV(CRC32(RAND()), 16, 36), 6), -- 前6位为rand的crc32的前6位,以36进制表示(0-9,A=10,Z=36)
LEFT(CONV(CRC32(UUID()), 16, 36), 6), -- 中间6位,用UUID
LEFT(CONV(CRC32(SIN(RAND())), 16, 36), 6) -- 最后6位,用sin(rand())
)
或者其他类似的方法,注意CONV只能处理32bit,所以必须分段处理。
聪明的一休 2012-01-13
  • 打赏
  • 举报
回复
关于重复的可能性,你可能还没理解我的意思,比如我一个批次生成1000个随机串,我先生成一个批次号,可以在批次表里检查唯一性,这样我只要保证后面12位在1000个中的唯一性,而不需要保证在全表中的唯一性了。所以是大大减少了重复的可能性。

至于你说的加密算法,如果你不能解决随机字符串的唯一性问题的话,后面再加密也是徒劳的。我们主要需要解决唯一性问题。当然如果我们先用唯一时间戳再MD5加密的话,和UUID是一个问题,MD5生成出来是16位和32位。

[Quote=引用 4 楼 jiahehao 的回复:]

"所以我每个批次生成6位批次号,再用rand生成12位随机字符串放在批次号后面组成18位字符串,当然这样虽然大大减少了重复的可能性,"

你这种 批次号 + 12位随机串 的方式只是易于管理查验,并不能“大大减少了重复的可能性”,相反,是“大大提高了重复的可能性”,因为你会有相当多的数据前6位是相同的。

有个思路,你先只管生成18位随机字符串,然后找个加密算法过一遍,取生成的密文为正式……
[/Quote]
jiahehao 2012-01-13
  • 打赏
  • 举报
回复
"所以我每个批次生成6位批次号,再用rand生成12位随机字符串放在批次号后面组成18位字符串,当然这样虽然大大减少了重复的可能性,"

你这种 批次号 + 12位随机串 的方式只是易于管理查验,并不能“大大减少了重复的可能性”,相反,是“大大提高了重复的可能性”,因为你会有相当多的数据前6位是相同的。

有个思路,你先只管生成18位随机字符串,然后找个加密算法过一遍,取生成的密文为正式字符串。因为象RSA、MD5这类的现代加密算法都有个特点:同样的明文进去,出来的密文仍然不同。所以,就算你进去的字符串是一样的,出来的密文也肯定不一样。
iihero 2012-01-13
  • 打赏
  • 举报
回复
如果只是18位,取uuid的第9到26位,并加上是否重复键判断,总体效果也还算不错。重复的机率比较小。

ACMAIN_CHM 2012-01-12
  • 打赏
  • 举报
回复
直接找种算法,把 1,2,3,4 这样的序列转换成 18 位字符串。
聪明的一休 2012-01-12
  • 打赏
  • 举报
回复
要求是18位,你用uuid的话,截字符串的话就不能保证唯一了。

[Quote=引用 1 楼 rucypli 的回复:]

直接用uuid啊
mysql> select replace(uuid(),'-','');
+----------------------------------+
| replace(uuid(),'-','') |
+----------------------------------+
| 674a5c443cf211e1a2440019b9e04a91 |……
[/Quote]
rucypli 2012-01-12
  • 打赏
  • 举报
回复
直接用uuid啊
mysql> select replace(uuid(),'-','');
+----------------------------------+
| replace(uuid(),'-','') |
+----------------------------------+
| 674a5c443cf211e1a2440019b9e04a91 |
+----------------------------------+
1 row in set (0.00 sec)

56,938

社区成员

发帖
与我相关
我的任务
社区描述
MySQL相关内容讨论专区
社区管理员
  • MySQL
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧