摘要:出于以上兩個(gè)原因,我們需要自己的發(fā)號(hào)器來產(chǎn)生。與此同時(shí),為了保證執(zhí)行,具有原子性,我們使用來進(jìn)行實(shí)現(xiàn)。由于能力和水平有限,難免會(huì)有紕漏,希望及時(shí)指出。參考文章分布式生成器實(shí)現(xiàn)上實(shí)現(xiàn)原理
1、為什么要實(shí)現(xiàn)發(fā)號(hào)器
很多地方我們都需要一個(gè)全局唯一的編號(hào),也就是uuid。舉一個(gè)常見的場(chǎng)景,電商系統(tǒng)產(chǎn)生訂單的時(shí)候,需要有一個(gè)對(duì)應(yīng)的訂單編號(hào)。在composer上我們也可以看到有很多可以產(chǎn)生uuid的優(yōu)秀組件。那么,為什么我們還要自己實(shí)現(xiàn)發(fā)號(hào)器,來產(chǎn)生uuid呢?想了一下,主要有兩個(gè)原因吧:
1、我希望uuid是可反解的,通過反解uuid可以得出和我業(yè)務(wù)相關(guān)的數(shù)據(jù)。而我看到的composer關(guān)于uuid的相關(guān)組件,生成的都是一串指定格式的字符串,我很難將它同具體的業(yè)務(wù)關(guān)聯(lián)起來。
2、我希望通過uuid是可以隨著并放量進(jìn)行調(diào)整的。比如說原有支持1秒鐘可以產(chǎn)生1000個(gè)uuid,但隨著業(yè)務(wù)規(guī)模增長,我希望變成可以支持1秒鐘產(chǎn)生一萬個(gè)。而且,最好改下配置就可以了。
出于以上兩個(gè)原因,我們需要自己的發(fā)號(hào)器來產(chǎn)生uuid。那么,下一個(gè)問題是,我們應(yīng)該如何實(shí)現(xiàn)發(fā)號(hào)器,實(shí)現(xiàn)發(fā)號(hào)器的原理又是什么呢?
2、snowFlake算法關(guān)于發(fā)號(hào)器的實(shí)現(xiàn)原理,可能大家都聽過鼎鼎大名的snowflake算法 -- 雪花算法,Twitter的分布式自增Id算法。國內(nèi)的新浪微博也有自己實(shí)現(xiàn)的發(fā)號(hào)器算法,具體實(shí)現(xiàn)細(xì)節(jié)雖有不同,但是原理相通,明白其中一個(gè)即可。這里我們主要介紹snowflake。
關(guān)于snowflaw的介紹,已經(jīng)有很多文章進(jìn)行介紹,而且寫的也很不錯(cuò),我沒有必要在重寫一遍,拿來粘貼即可,出于對(duì)作者的尊重,我會(huì)將原文鏈接添加到參考鏈接中。
推特的分布式自增ID算法,使用long (8 × 8 = 64 byte)來保存uuid。其中1bit留給固定符號(hào)位0,41bit留給毫秒時(shí)間戳,10bit給MachineID,也就是機(jī)器要預(yù)先配置,剩下12位留Sequence(可支持1毫秒內(nèi)4096個(gè)請(qǐng)求)。
也許有的人會(huì)問如果超過了1毫秒4096個(gè)請(qǐng)求怎么辦?一般的做法是,讓它等上1毫秒,促使41bit的時(shí)間戳變化。
這里我們將MachineId進(jìn)行了拆分,5byte留給機(jī)器(最多可以支持32機(jī)器),5byte留給了業(yè)務(wù)號(hào)(最多可支持32種業(yè)務(wù))
這里的時(shí)間戳保存的是當(dāng)前時(shí)間與固定過去時(shí)間得一個(gè)差值,不是當(dāng)前時(shí)間。這樣的好處是能使用更長時(shí)間,而且不受年份限制,只取決于從什么時(shí)候開始用的,2^41 / 1000360024*365=69年。
如果保存的是當(dāng)前時(shí)間戳,最多只能使用到2039年。2^41=2199023255552=2039/9/7 23:47:35
理論上單機(jī)速度:2^12*1000 = 4 096 000/s
通過對(duì)snowflake的初步了解,發(fā)現(xiàn),其實(shí)發(fā)號(hào)器也是建立在時(shí)間戳基礎(chǔ)之上的,因?yàn)闀r(shí)間是天然的唯一元素。但是,如何在單位時(shí)間內(nèi),比如說一秒鐘或者一毫秒之內(nèi),保證Sequence持續(xù)遞增才是發(fā)號(hào)器實(shí)現(xiàn)的關(guān)鍵。
這里我們實(shí)現(xiàn)的方式比較簡單,直接使用redis的incr進(jìn)行計(jì)數(shù),對(duì)應(yīng)的key就是毫秒時(shí)間戳。出于redis內(nèi)存回收的考慮,我們需要將每一個(gè)key設(shè)置過期時(shí)間。如果key是秒級(jí)別的時(shí)間戳,那么過期時(shí)間就是1秒 + 網(wǎng)絡(luò)延遲;如果key毫秒級(jí)別的時(shí)間戳,那么過期時(shí)間就是1毫秒 + 網(wǎng)絡(luò)延遲。
與此同時(shí),為了保證執(zhí)行incr,expire(pexpire)具有原子性,我們使用lua來進(jìn)行實(shí)現(xiàn)。
好了,實(shí)現(xiàn)的思路大致如此。由于能力和水平有限,難免會(huì)有紕漏,希望及時(shí)指出。
4、參考文章分布式ID生成器PHP+Swoole實(shí)現(xiàn)(上) - 實(shí)現(xiàn)原理
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/31404.html
摘要:接著上一篇實(shí)現(xiàn)一個(gè)簡單的發(fā)號(hào)器原理篇,本篇講一下發(fā)號(hào)器的具體實(shí)現(xiàn)。統(tǒng)計(jì)最后一列的總數(shù)量和去重后的數(shù)量是否一致即可。 接著上一篇 php + redis + lua 實(shí)現(xiàn)一個(gè)簡單的發(fā)號(hào)器(1)-- 原理篇,本篇講一下發(fā)號(hào)器的具體實(shí)現(xiàn)。 1、基礎(chǔ)知識(shí) 發(fā)號(hào)器的實(shí)現(xiàn)主要用到了下面的一些知識(shí)點(diǎn): 1. php中的位運(yùn)算的操作和求值 2. 計(jì)算機(jī)原碼、補(bǔ)碼、反碼的基本概念 3. redis中l(wèi)u...
摘要:為什么需要發(fā)號(hào)器在分布式系統(tǒng)中,經(jīng)常需要對(duì)大量的數(shù)據(jù)消息請(qǐng)求等進(jìn)行唯一標(biāo)識(shí),例如對(duì)于分布式系統(tǒng),服務(wù)間相互調(diào)用需要唯一標(biāo)識(shí),調(diào)用鏈路分析,日志追蹤的時(shí)候需要使用這個(gè)唯一標(biāo)識(shí)。 原文鏈接:何曉東 博客 文章起源于 康神交流群的 panda大佬和boss li關(guān)于發(fā)號(hào)器的一些交流,特此感謝讓我們學(xué)到了新知識(shí)。 為什么需要發(fā)號(hào)器 在分布式系統(tǒng)中,經(jīng)常需要對(duì)大量的數(shù)據(jù)、消息、http 請(qǐng)求等進(jìn)...
摘要:舉個(gè)例子,第一個(gè)進(jìn)來的鏈接發(fā)號(hào)器發(fā)號(hào),對(duì)應(yīng)的短鏈接為,第二個(gè)進(jìn)來的鏈接發(fā)號(hào)器發(fā)號(hào),對(duì)應(yīng)的短鏈接為,以此類推。這樣一來會(huì)導(dǎo)致一條長鏈接對(duì)應(yīng)多條短鏈接的情況出現(xiàn),不僅浪費(fèi)存儲(chǔ)空間,又浪費(fèi)發(fā)號(hào)器資源。 1. 什么是短鏈接 顧名思義,短鏈接即是長度較短的網(wǎng)址。通過短鏈接技術(shù),我們可以將長度較長的鏈接壓縮成較短的鏈接。并通過跳轉(zhuǎn)的方式,將用戶請(qǐng)求由短鏈接重定向到長鏈接上去。短鏈接主要用在諸如微博...
閱讀 2183·2023-04-25 17:23
閱讀 2994·2021-11-17 09:33
閱讀 2591·2021-08-21 14:09
閱讀 3746·2019-08-30 15:56
閱讀 2659·2019-08-30 15:54
閱讀 1673·2019-08-30 15:53
閱讀 2193·2019-08-29 13:53
閱讀 1207·2019-08-29 12:31