php -1 是真值吗,真假唯一数,PHP唯一数,Java唯一数,Node唯一数

在真实的业务场景中生成唯一数是很常用的功能,也是面试必考题。最近面试一个PHP开发岗位,无意中聊到这个话题,然后顺着话题一直拓展。今天说下在面试中,面试官问这个问题想得到怎样的答案。

每种编程语言都提供了唯一数生成函数,但是都有条件限制,先看看网上都有哪些生成唯一数的方法。

一. 散列+时间+随机值

md5(time() . mt_rand(1,1000000));

time()函数获取当前时间戳,mt_rand(1,1000000)函数获取一个1到1000000的随机值,看着好像生成的数能唯一,但这行代码的问题其实非常多。

在代码中时间是很不靠谱的参数,如果用户1秒内发送了2个请求,那么time()字段毫无意义。

在代码中随机数其实并不随机,常见的随机数都需要有随机种子,而为了保证种子不被猜到,编程语言默认会使用当前系统时间作为种子。又变成了依赖时间的一个参数,所以这种方案不可取。

二. 微秒+进程编号

uniqid();

uniqid()函数可以得到一个基于微秒和进程编号的唯一ID。对于php-fpm来说,每个请求都独占一个进程,一个进程会串行的处理多个请求。所以通过进程编号+微秒时间看上去能生成唯一ID。但深究之后发现并不靠谱。

1秒等于100万微秒,现在问题会变成一个进程能在百万分之一秒内处理多个请求吗?答案是可以的,用当前最普通的CPU来说,单核心1秒就可以计算20亿次,1微秒可以计算2千次。从计算机调度的角度来说,2千次同时处理到一个进程的两个请求是完全可能的。所以又变成了依赖时间的一个参数,这种方案不可取。

你还能使用纳秒,皮秒等精度更高的时间参数,但以发展的远光看问题,未来CPU的算力会越来越快,依赖时间的唯一性会越来越差。无论怎么努力,只依靠编程语言自身得到唯一ID是非常困难的,也是我不推荐的。

三. 数据库

靠编程语言自己走不通,那就通过第三方工具,这种方案是靠谱的。但实现起来也有很多种方法。

LOCK TABLES id_maker;

//拿到id

select id from id_maker;

//加1更新

update id_maker set id=id+1;

UNLOCK id_maker;

这是我曾经见过的一种id_maker用法,这样每次得到的id都是唯一并且有序的。但问题就是需要锁表,性能不高,在高并发下会发生资源抢占导致数据库崩溃。

//id_maker表有自增id和内容data两个字段

insert into id_maker(data) values('');

select last_insert_id();

这种方式性能就高很多,insert语句不会锁表,自增id百分百保证唯一性且有序。唯一的问题是需要定期删除历史数据,对于大部分项目我都建议使用这种方式生成唯一ID。

除了MySQL还有MongoDB,Redis等其他数据库方案,方法大同小异。但是这个方案有局限性,当我们的业务发展到成千上万台服务器时通过一个数据库的一张表去生成ID会导致性能下降拖垮其他服务,还会形成单点依赖。

四. 微秒+服务器编号+计数器

这是twitter使用的一种方案,名字叫SnowFlake,这种方案的原理非常简单,所以很容易基于SnowFlake算法做扩展。比如PHP并不会常驻内存,计数器的实现就比较麻烦,但只要原理清楚了使用扩展或者数据库很容易实现。

这个方案的最大优点就是在庞大的集群中,每个服务靠自己就能算出全局的唯一ID。服务器编号和微秒能确定到具体服务器,计数器可以理解为只为当前服务器提供的id_maker,这样生成的唯一编号无懈可击。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值