怎样生成唯一的ID?

打开我的简书首页,在地址栏上可以看到这样的地址

http://www.jianshu.com/users/066ab87a062b/latest_articles

作为一个web开发者应该知道这里的users后面的那串"066ab87a062b"必定是我的ID,这个ID肯定是唯一的。这就是今天要讨论的,怎样生成唯一的ID?

如果你是一个初级的web开发者,那么你可能不会去生成这种唯一的ID,因为有一个很简单的方法已经帮我们搞定了这个事情,那就是数据库。

比如我们往数据库的用户表中插入一个用户,数据库的自增键就会生成一个唯一的ID,当然这种ID是很简单的,就是从1开始自增,这样就不会重复。当然这里有很大的安全隐患,从链接上多观察一下,就能发现规律。如果简书现在的链接是这样的:

http://www.jianshu.com/users/19875/latest_articles

再多看看其他用户的简书首页地址,你发现也是一个数字,并且修改几个连续的数字大多数能查看到其他用户,那么现在我就可以从ID为1开始遍历,就可以知道简书有多少注册用户了。是不是算暴露了信息?当然黑客可以做的事情远远不止这些。

这个时候我们就得想一个比较复杂的生成唯一ID的想法。

一般来说,我们都会想到用当前系统时间来做这件事情,比如最简单的是unix时间戳,像这样

time();
//1429874998

一般情况下这样是行不通的,因为unix时间戳只是精确到秒,同一秒有两个人注册怎么办?

我记得我一开始实习那会用这个方法来生成唯一ID

time() . rand(1, 10000);
//142987499812

时间戳后面加一个随机数,这样把一秒钟分成10000份,重复的概率只有万分之一,对于一般的情况已经能够搞定了。

但是精明一点的人肯能会猜到你是在用10位的时间戳加一个随机数字,那怎么办?

第一反映自然是加密:

md5(time() . rand(1, 10000));
//141464D2619764441D30A285ED4478F5

不可逆的加密算法有很多,比如md5,sha1等,当然如果使用可逆的加密算法容易被看出来。这样加密一般很难破解了,如果你还觉得不够安全,可以在加密前后进行一系列字符串操作,比如反转。这样就非常难以破解了。当然也有问题,那就是ID变得很长很长。而且似乎也没有解决生成唯一ID的关键问题。

生成唯一ID的关键问题就是唯一,安全问题次之,不是说安全不重要,而是如果连生成唯一ID都解决不了,安全就没有什么可谈的了,系统本身就是不稳定不安全的。

上述的方法还是有一定的概率生成重复ID的,虽然只有万分之一,但如果刚好两个人在同一秒注册,刚好就生成了一样的呢?

php提供了一个生成唯一ID的函数:

uniqid();
//553a2f5bad51f

这个生成的ID就和简书的ID非常像了。

但是这个函数也不一定会生成唯一的ID,原因是uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID;基于微妙的意思就是如果并发数非常非常高的时候,在同一个毫秒里面有两个人注册,那么也是会生成唯一的ID。

正真做到不重复要怎么办?

一种方法是结合时间和数据库生成的ID,这两者结合起来就是唯一的了。
至于怎么结合可以根据自己的需求或者喜好。这样生成的ID只要不进行不可逆加密还可以按时间来排序。

还有一种方法是不借助数据库那个唯一ID,而是将注册流程改为严格的单线程,也就是每次只处理一个,那这样时间戳就是唯一的了,生成方法也就可以随意发挥了。当然了,一两秒的等待用户还是可以接受的。

怎么做到严格的单线程处理注册流程?

第一种简单的就是假设你已经控制好了系统是单线程处理的,我记得以前听过一个鸵鸟算法,像鸵鸟一样将头埋在沙子里面,什么也不做,假装看不到,有时候这何尝不是一种好的生活态度呢。ok,继续说,假设以微妙为单位,这对于90%的系统已经能满足了,因为网站的量根本没有那么大。
第二种方法是用队列来处理,虽然牛刀杀鸡,但也算是个方法。



作者:龟仙老人
链接:https://www.jianshu.com/p/f4464631b82a
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值