怎样生成唯一的ID?

作者: 捉虫大师 | 来源:发表于2015-04-24 20:13 被阅读7306次

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

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%的系统已经能满足了,因为网站的量根本没有那么大。
第二种方法是用队列来处理,虽然牛刀杀鸡,但也算是个方法。

讲这么多大概讲完了今天想到的东西,最近有点感触就是,遇到的东西多思考你将可能发现更多的好玩的东西。

相关文章

  • 怎样生成唯一的ID?

    打开我的简书首页,在地址栏上可以看到这样的地址 http://www.jianshu.com/users/066a...

  • 生成全局唯一id的几种方式

    生成全局唯一id的几种方式: 1、uuid生成全球唯一id,生成方式简单粗暴,本地生成,没有网络开销,效率高;缺点...

  • 生成唯一id

    1.API >=9:通过“Build.SERIAL”这个属性来保证ID的独一无二。 api<9

  • nsq源码(7) nsqd messageID

    messageID 消息唯一标识 GenerateID()返回ID NewGUID()生成ID

  • 生成分布式序列ID

    生成分布式序列ID 介绍 在很多分布式系统中,需要生成唯一的id。如在分库分表的情况下,给某个逻辑表生成唯一id。...

  • 随手小工具函数

    js 随机生成唯一值(ID)

  • js如何生成唯一标识符(类似uuid)

    1. JavaScript唯一ID生成器Nano ID NanoID: 一个极小的,安全的ID生成器Source:...

  • 设计分布式唯一id生成

    1. 生成全局唯一id 什么时候需要生成全局唯一id db不帮你自动生成的时候。比如: db做了分库分表,没帮你自...

  • Redis-全局唯一ID

    零、本文纲要 一、全局唯一ID 二、Redis生成全局唯一ID1、snowflake算法全局唯一ID策略2、Red...

  • 全局唯一ID

    生成全局唯一ID 通过MySQL的自增主键,作为唯一id; 通过内存中变量AtomicLong的自增来得到唯一id...

网友评论

    本文标题:怎样生成唯一的ID?

    本文链接:https://www.haomeiwen.com/subject/ccupfttx.html