12位纯数字兑换码的生成算法,如何尽可能保证不重复?
在只有PHP和mysql的环境下,做一个简单的发券、核销程序。其中券的兑换码必须为12位数字,数据量不会超过千万。如何生成不重复且乱序的券码?
最糟糕的方案是纯随机,然后到表里查一遍是否重复,重复则重新生成;不重复则插入
一个自认为好点的方案是用户id加一位随机数加截取时间戳后x位
例如用户ID为123,则是3位,加随机数4位。此时剩余8位则截取时间戳后8位补上。重复概率应该就很低了
在尽可能不遍历表的情况下,还有更难以重复的生成算法吗?求不吝赐教
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果是按照用户ID和时间戳等生成md5摘要的方式的话,可以用base_convert将哈希后的md5值转为10进制,不过这样转出来的结果值长度肯定就不止12位了,还需要用字符串截取函数截取一下,但原本几十位的十进制数只截取12位那么唯一性就无法保证了,可能还不如直接截取ID加时间戳,看你的描述应该是在用户请求的时候才生成码,那么一个用户同一秒不能生成多张的情况下组合部分时间戳和用户ID还是没问题的。
考虑用户的ID和时间进行消息摘要算法,比如最简单内置的MD5或者SHA1,然后对于结果进行一定的压缩或者提取,转化成12位的
我感觉你的想法挺好啊,还可以还原进行验证兑换码的合法性。
消息摘要算法太混沌了,压缩到12位后效果和随机没有区别,多了还是会碰撞。
楼主的做法(id + 时间戳 + 随机数)基本能满足不碰撞的要求了,问题在于乱序。
可以仿效线性同余生成伪随机数的方法,找个大素数a和常数b,把id + 时间戳 + 随机数生成的数字输入函数
f(x) = a * x + b (mod 1,000,000,000,000)
里,只要a足够大(数量级跟1,000,000,000,000相近)就很随机了。而且由于a是素数,f是可逆的,这也保证了只要输入不重复,输出也不会重复。另外建议拼接数字时把随机数放在高位,这样运算后输出的差别更大。