资讯专栏INFORMATION COLUMN

php + redis + lua 实现一个简单的发号器(1)-- 原理篇

rottengeek / 3431人阅读

摘要:出于以上两个原因,我们需要自己的发号器来产生。与此同时,为了保证执行,具有原子性,我们使用来进行实现。由于能力和水平有限,难免会有纰漏,希望及时指出。参考文章分布式生成器实现上实现原理

1、为什么要实现发号器

很多地方我们都需要一个全局唯一的编号,也就是uuid。举一个常见的场景,电商系统产生订单的时候,需要有一个对应的订单编号。在composer上我们也可以看到有很多可以产生uuid的优秀组件。那么,为什么我们还要自己实现发号器,来产生uuid呢?想了一下,主要有两个原因吧:

1、我希望uuid是可反解的,通过反解uuid可以得出和我业务相关的数据。而我看到的composer关于uuid的相关组件,生成的都是一串指定格式的字符串,我很难将它同具体的业务关联起来。

2、我希望通过uuid是可以随着并放量进行调整的。比如说原有支持1秒钟可以产生1000个uuid,但随着业务规模增长,我希望变成可以支持1秒钟产生一万个。而且,最好改下配置就可以了。

出于以上两个原因,我们需要自己的发号器来产生uuid。那么,下一个问题是,我们应该如何实现发号器,实现发号器的原理又是什么呢?

2、snowFlake算法

关于发号器的实现原理,可能大家都听过鼎鼎大名的snowflake算法 -- 雪花算法,Twitter的分布式自增Id算法。国内的新浪微博也有自己实现的发号器算法,具体实现细节虽有不同,但是原理相通,明白其中一个即可。这里我们主要介绍snowflake。

关于snowflaw的介绍,已经有很多文章进行介绍,而且写的也很不错,我没有必要在重写一遍,拿来粘贴即可,出于对作者的尊重,我会将原文链接添加到参考链接中。

推特的分布式自增ID算法,使用long (8 × 8 = 64 byte)来保存uuid。其中1bit留给固定符号位0,41bit留给毫秒时间戳,10bit给MachineID,也就是机器要预先配置,剩下12位留Sequence(可支持1毫秒内4096个请求)。

也许有的人会问如果超过了1毫秒4096个请求怎么办?一般的做法是,让它等上1毫秒,促使41bit的时间戳变化。

这里我们将MachineId进行了拆分,5byte留给机器(最多可以支持32机器),5byte留给了业务号(最多可支持32种业务)


这里的时间戳保存的是当前时间与固定过去时间得一个差值,不是当前时间。这样的好处是能使用更长时间,而且不受年份限制,只取决于从什么时候开始用的,2^41 / 1000360024*365=69年。

如果保存的是当前时间戳,最多只能使用到2039年。2^41=2199023255552=2039/9/7 23:47:35
理论上单机速度:2^12*1000 = 4 096 000/s

3、如何保证在单位时间内持续递增

通过对snowflake的初步了解,发现,其实发号器也是建立在时间戳基础之上的,因为时间是天然的唯一元素。但是,如何在单位时间内,比如说一秒钟或者一毫秒之内,保证Sequence持续递增才是发号器实现的关键。

这里我们实现的方式比较简单,直接使用redis的incr进行计数,对应的key就是毫秒时间戳。出于redis内存回收的考虑,我们需要将每一个key设置过期时间。如果key是秒级别的时间戳,那么过期时间就是1秒 + 网络延迟;如果key毫秒级别的时间戳,那么过期时间就是1毫秒 + 网络延迟。

与此同时,为了保证执行incr,expire(pexpire)具有原子性,我们使用lua来进行实现。

好了,实现的思路大致如此。由于能力和水平有限,难免会有纰漏,希望及时指出。

4、参考文章

分布式ID生成器PHP+Swoole实现(上) - 实现原理

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/31404.html

相关文章

  • php + redis + lua 实现一个简单的发号器(2)-- 实现

    摘要:接着上一篇实现一个简单的发号器原理篇,本篇讲一下发号器的具体实现。统计最后一列的总数量和去重后的数量是否一致即可。 接着上一篇 php + redis + lua 实现一个简单的发号器(1)-- 原理篇,本篇讲一下发号器的具体实现。 1、基础知识 发号器的实现主要用到了下面的一些知识点: 1. php中的位运算的操作和求值 2. 计算机原码、补码、反码的基本概念 3. redis中lu...

    iOS122 评论0 收藏0
  • 分布式系统全局发号器的几点思考

    摘要:为什么需要发号器在分布式系统中,经常需要对大量的数据消息请求等进行唯一标识,例如对于分布式系统,服务间相互调用需要唯一标识,调用链路分析,日志追踪的时候需要使用这个唯一标识。 原文链接:何晓东 博客 文章起源于 康神交流群的 panda大佬和boss li关于发号器的一些交流,特此感谢让我们学到了新知识。 为什么需要发号器 在分布式系统中,经常需要对大量的数据、消息、http 请求等进...

    dayday_up 评论0 收藏0
  • 短链接原理分析

    摘要:举个例子,第一个进来的链接发号器发号,对应的短链接为,第二个进来的链接发号器发号,对应的短链接为,以此类推。这样一来会导致一条长链接对应多条短链接的情况出现,不仅浪费存储空间,又浪费发号器资源。 1. 什么是短链接 顾名思义,短链接即是长度较短的网址。通过短链接技术,我们可以将长度较长的链接压缩成较短的链接。并通过跳转的方式,将用户请求由短链接重定向到长链接上去。短链接主要用在诸如微博...

    SexySix 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<