IM消息ID技術(shù)專題(七):深度解密vivo的自研分布式ID服務(wù)(魯班) 僅登錄用戶可見

本文由vivo互聯(lián)網(wǎng)技術(shù)An Peng分享,本文收錄時(shí)有內(nèi)容修訂和重新排版。
1、引言
本文通過對(duì)分布式ID的3種應(yīng)用場(chǎng)景、實(shí)現(xiàn)難點(diǎn)以及9種分布式ID的實(shí)現(xiàn)方式進(jìn)行介紹,并對(duì)結(jié)合vivo業(yè)務(wù)場(chǎng)景特性下自研的魯班分布式ID服務(wù)從系統(tǒng)架構(gòu)、ID生成規(guī)則與部分實(shí)現(xiàn)源碼進(jìn)行分享,希望為本文的閱讀者在分布式ID的方案選型或技術(shù)自研提供參考。

?技術(shù)交流:
- 移動(dòng)端IM開發(fā)入門文章:《新手入門一篇就夠:從零開發(fā)移動(dòng)端IM》
- 開源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK(備用地址點(diǎn)此)
(本文已同步發(fā)布于:http://www.52im.net/thread-4378-1-1.html)
2、專題目錄
本文是“IM消息ID技術(shù)專題”系列文章的第?7?篇,專題總目錄如下:
《IM消息ID技術(shù)專題(一):微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)》
《IM消息ID技術(shù)專題(二):微信的海量IM聊天消息序列號(hào)生成實(shí)踐(容災(zāi)方案篇)》
《IM消息ID技術(shù)專題(三):解密融云IM產(chǎn)品的聊天消息ID生成策略》
《IM消息ID技術(shù)專題(四):深度解密美團(tuán)的分布式ID生成算法》
《IM消息ID技術(shù)專題(五):開源分布式ID生成器UidGenerator的技術(shù)實(shí)現(xiàn)》
《IM消息ID技術(shù)專題(六):深度解密滴滴的高性能ID生成器(Tinyid)》
《IM消息ID技術(shù)專題(七):深度解密vivo的自研分布式ID服務(wù)(魯班)》(* 本文)
vivo技術(shù)團(tuán)隊(duì)分享的其它文章:
《vivo的Electron技術(shù)棧選型、全方位實(shí)踐總結(jié)》
《vivo直播系統(tǒng)中IM消息模塊的架構(gòu)實(shí)踐》
3、分布式ID的應(yīng)用場(chǎng)景
3.1概述
隨著系統(tǒng)的業(yè)務(wù)場(chǎng)景復(fù)雜化、架構(gòu)方案的優(yōu)化演進(jìn),我們?cè)诳朔栴}的過程中,也總會(huì)延伸出新的技術(shù)訴求。分布式ID也是誕生于這樣的IT發(fā)展過程中。
在不同的關(guān)聯(lián)模塊內(nèi),我們需要一個(gè)全局唯一的ID來讓模塊既能并行地解耦運(yùn)轉(zhuǎn),也能輕松地進(jìn)行整合處理。
以下,首先讓我們一起回顧這些典型的分布式ID場(chǎng)景。
3.2系統(tǒng)分庫分表
隨著系統(tǒng)的持續(xù)運(yùn)作,常規(guī)的單庫單表在支撐更高規(guī)模的數(shù)量級(jí)時(shí),無論是在性能或穩(wěn)定性上都已經(jīng)難以為繼,需要我們對(duì)目標(biāo)邏輯數(shù)據(jù)表進(jìn)行合理的物理拆分。
這些同一業(yè)務(wù)表數(shù)據(jù)的拆分,需要有一套完整的 ID生成方案來保證拆分后的各物理表中同一業(yè)務(wù)ID不相沖突,并能在后續(xù)的合并分析中可以方便快捷地計(jì)算。
以公司的營(yíng)銷系統(tǒng)的訂單為例:當(dāng)前不但以分銷與零售的目標(biāo)組織區(qū)別來進(jìn)行分庫存儲(chǔ),來實(shí)現(xiàn)多租戶的數(shù)據(jù)隔離,并且會(huì)以訂單的業(yè)務(wù)屬性(訂貨單、退貨單、調(diào)拔單等等)來進(jìn)一步分拆訂單數(shù)據(jù)。
具體是:
1)在訂單創(chuàng)建的時(shí)候,根據(jù)這些規(guī)則去構(gòu)造全局唯一ID,創(chuàng)建訂單單據(jù)并保存在對(duì)應(yīng)的數(shù)據(jù)庫中;
2)在通過訂單號(hào)查詢時(shí),通過ID的規(guī)則,快速路由到對(duì)應(yīng)的庫表中查詢;
3)在BI數(shù)倉的統(tǒng)計(jì)業(yè)務(wù)里,又需要匯總這些訂單數(shù)據(jù)進(jìn)行報(bào)表分析。
3.3系統(tǒng)多活部署
無論是面對(duì)著全球化的各國(guó)數(shù)據(jù)合規(guī)訴求,還是針對(duì)容災(zāi)高可用的架構(gòu)設(shè)計(jì),我們都會(huì)對(duì)同一套系統(tǒng)進(jìn)行多活部署。
多活部署架構(gòu)的各單元化服務(wù),存儲(chǔ)的單據(jù)(如訂單/出入庫單/支付單等)均帶有部署區(qū)域?qū)傩缘腎D結(jié)構(gòu)去構(gòu)成全局唯一ID。
創(chuàng)建單據(jù)并保存在對(duì)應(yīng)單元的數(shù)據(jù)庫中,在前端根據(jù)單據(jù)號(hào)查詢的場(chǎng)景,通過ID的規(guī)則,可快速路由到對(duì)應(yīng)的單元區(qū)域進(jìn)行查詢。
對(duì)應(yīng)多活部署架構(gòu)的中心化服務(wù),同步各單元的單據(jù)數(shù)據(jù)時(shí),單據(jù)的ID是全局唯一,避免了匯聚數(shù)據(jù)時(shí)的ID沖突。
在公司的系統(tǒng)部署中,公共領(lǐng)域的 BPM 、待辦、營(yíng)銷領(lǐng)域的系統(tǒng)都大范圍地實(shí)施多活部署。
3.4鏈路跟蹤技術(shù)
在微服務(wù)架構(gòu)流行的大背景下,此類微服務(wù)的應(yīng)用對(duì)比單體應(yīng)用的調(diào)用鏈路會(huì)更長(zhǎng)、更復(fù)雜,對(duì)問題的排查帶來了挑戰(zhàn)。
應(yīng)對(duì)該場(chǎng)景的解決方案,是會(huì)在流量入口處產(chǎn)生全局唯一的TraceID,并在各微服務(wù)之間進(jìn)行透?jìng)?,進(jìn)行流量染色與關(guān)聯(lián),后續(xù)通過該全局唯一的TraceID,可快速地查詢與關(guān)聯(lián)全鏈路的調(diào)用關(guān)系與狀態(tài),快速定位根因問題。
在公司的各式各樣的監(jiān)控系統(tǒng)、灰度管理平臺(tái)、跨進(jìn)程鏈路日志中,都會(huì)伴隨著這么一個(gè)技術(shù)組件進(jìn)行支撐服務(wù)。
4、分布式ID的核心難點(diǎn)
分布式ID的技術(shù)難點(diǎn)比較,這里我簡(jiǎn)單總結(jié)了一下。
最核心的技術(shù)難點(diǎn)主要是:
1)唯一性:?保持生成的ID全局唯一,在任何情況下也不會(huì)出現(xiàn)重復(fù)的值(如防止時(shí)間回拔,時(shí)鐘周期問題);
2)高性能:?ID的需求場(chǎng)景多,中心化生成組件后,需要高并發(fā)處理,以接近 0ms的響應(yīng)大規(guī)模并發(fā)執(zhí)行;
3)高可用:?作為ID的生產(chǎn)源頭,需要100%可用,當(dāng)接入的業(yè)務(wù)系統(tǒng)多的時(shí)候,很難調(diào)整出各方都可接受的停機(jī)發(fā)布窗口,只能接受無損發(fā)布;
4)易接入:?作為邏輯上簡(jiǎn)單的分布式ID要推廣使用,必須強(qiáng)調(diào)開箱即用,容易上手;
5)規(guī)律性:?不同業(yè)務(wù)場(chǎng)景生成的ID有其特征,例如有固定的前后綴,固定的位數(shù),這些都需要配置化管理。
5、分布式ID的常見方案
常用系統(tǒng)設(shè)計(jì)中主要有下圖9種ID生成的方式:

以下是詳細(xì)表格說明之:

上面這些ID算法里,最知名是Twitter的雪花算法(Snowflake)。
Snowflake的核心思想就是:使用一個(gè) 64 bit 的 long 型的數(shù)字作為全局唯一 ID。
這 64 個(gè) bit 中,其中 1 個(gè) bit 是不用的,然后用其中的 41 bit 作為毫秒數(shù),用 10 bit 作為工作機(jī)器 ID,12 bit 作為序列號(hào)。
SnowFlake的ID構(gòu)成:

▲ 圖片引用自《深度解密美團(tuán)的分布式ID生成算法 - 美團(tuán)為什么不直接用Snowflake算法?》
SnowFlake的ID樣本:

▲ 圖片引用自《深度解密美團(tuán)的分布式ID生成算法 - 美團(tuán)為什么不直接用Snowflake算法?》
6、自研分布式ID服務(wù)(魯班)的方案
我們的系統(tǒng)跨越了公共、生產(chǎn)制造、營(yíng)銷、供應(yīng)鏈、財(cái)經(jīng)等多個(gè)領(lǐng)域。
我們?cè)诜植际絀D訴求下還有如下特點(diǎn):
1)在業(yè)務(wù)場(chǎng)景上除了常規(guī)的Long類型ID,也需要支持“String類型”、“MixId類型”(后詳述)等多種類型的ID生成,每一種類型也需要支持不同的長(zhǎng)度的ID;
2)在ID的構(gòu)成規(guī)則上需要涵蓋如操作類型、區(qū)域、代理等業(yè)務(wù)屬性的標(biāo)識(shí);需要集中式的配置管理;
3)在一些特定的業(yè)務(wù)上,基于安全的考慮,還需要在尾部加上隨機(jī)數(shù)來保證ID不能被輕易猜測(cè)。
綜合參考了業(yè)界優(yōu)秀的開源組件與常用方案均不能滿足,為了統(tǒng)一管理這類基礎(chǔ)技術(shù)組件的訴求,我們選擇基于公司業(yè)務(wù)場(chǎng)景自研一套分布式ID服務(wù):魯班分布式ID服務(wù)。
7、分布式ID服務(wù)魯班的整體架構(gòu)
魯班的整體架構(gòu)如下圖所示:

魯班的架構(gòu)說明:

8、魯班支持多種類型的ID規(guī)則
目前魯班分布式ID服務(wù)共提供"Long類型"、“String類型”、“MixId類型”等三種主要類型的ID,相關(guān)ID構(gòu)成規(guī)則與說明如下。
8.1Long類型
1)構(gòu)成規(guī)則:
靜態(tài)結(jié)構(gòu)由以下三部分?jǐn)?shù)據(jù)組成,組成部分共19位。如下所示。
* 固定部分(4位),由FixPart+ServerPart組成:
1)FixPart(4位):由大區(qū)zone 1位/代理 agent 1位/項(xiàng)目 project 1位/應(yīng)用 app 1位,組成的4位數(shù)字編碼;
2)ServerPart(4位):用于定義產(chǎn)生全局ID的服務(wù)器標(biāo)識(shí)位,服務(wù)節(jié)點(diǎn)部署時(shí)動(dòng)態(tài)分配。
* 動(dòng)態(tài)部分DynPart(13位):?System.currentTimeMillis()?- 固定配置時(shí)間的TimeMillis?(可滿足使用100年)。
* 自增部分SelfIncreasePart(2位):用于在全局ID的客戶端SDK內(nèi)部自增部分,由客戶端SDK控制,業(yè)務(wù)接入方無感知。共 2位組成。
2)降級(jí)機(jī)制:
主要自增部分在服務(wù)器獲取初始值后,由客戶端SDK維護(hù),直到自增99后再次訪問服務(wù)端獲取下一輪新的ID以減少服務(wù)端交互頻率,提升性能,服務(wù)端獲取失敗后拋出異常,接入業(yè)務(wù)側(cè)需介入進(jìn)行處理。
3)樣例說明:

8.2String類型
1)構(gòu)成規(guī)則:
靜態(tài)結(jié)構(gòu)由以下五部分?jǐn)?shù)據(jù)組成,組成部分共25~27位。
* 固定部分操作位op+FixPart(9~11位):
1)操作位op(2~4位):2~4位由業(yè)務(wù)方傳入的業(yè)務(wù)類型標(biāo)識(shí)字符;
2)FixPart(7位):業(yè)務(wù)接入時(shí)申請(qǐng)獲取,由大區(qū)zone 1位,代理 agent 2位,項(xiàng)目 project 2位,應(yīng)用 app 2位組成。
* 服務(wù)器標(biāo)識(shí)部分 ServerPart(1位):?用于定義產(chǎn)生全局ID的服務(wù)器標(biāo)識(shí)位,服務(wù)節(jié)點(diǎn)部署時(shí)動(dòng)態(tài)分配A~Z編碼。
* 動(dòng)態(tài)部分DynPart(9位):System.currentTimeMillis()?- 固定配置時(shí)間的TimeMillis?,再轉(zhuǎn)換為32進(jìn)制字符串(可滿足使用100年)。
* 自增部分SelfIncreasePart(3位):用于在全局ID的客戶端SDK內(nèi)部自增部分,由客戶端SDK控制,業(yè)務(wù)接入方無感知。
* 隨機(jī)部分secureRandomPart(3位):用于在全局ID的客戶端SDK的隨機(jī)部分,由SecureRandom隨機(jī)生成3位0-9,A-Z字母數(shù)字組合的安全隨機(jī)數(shù),業(yè)務(wù)接入方無感知。
2)降級(jí)機(jī)制:
主要自增部分由客戶端SDK內(nèi)部維護(hù),一般情況下只使用001–999 共999個(gè)全局ID。也就是每向服務(wù)器請(qǐng)求一次,都在客戶端內(nèi)可以自動(dòng)維護(hù)999個(gè)唯一的全局ID。
特殊情況下在訪問服務(wù)器連接出問題的時(shí)候,可以使用帶字符的自增來做服務(wù)器降級(jí)處理,使用產(chǎn)生00A, 00B... 0A0, 0A1,0A2....ZZZ. 共有36 * 36 * 36 - 1000 (999純數(shù)字,000不用)= 45656個(gè)降級(jí)使用的全局ID。
3)樣例說明:

8.3MixId類型
1)構(gòu)成規(guī)則:
靜態(tài)結(jié)構(gòu)由以下三部分?jǐn)?shù)據(jù)組成,組成部分共17位。
* 固定部分FixPart(4~6位):
1)操作位op(2~4位):2~4位由業(yè)務(wù)方傳入的業(yè)務(wù)類型標(biāo)識(shí)字符;
2)FixPart(2位):業(yè)務(wù)接入時(shí)申請(qǐng)獲取由代理 agent 2位組成。
* 動(dòng)態(tài)部分DynPart(6位):?生成ID的時(shí)間,年(2位)月(2位)日(2位)。
* 自增部分SelfIncreasePart(7位):用于在全局ID的客戶端SDK內(nèi)部自增部分,由客戶端SDK控制,業(yè)務(wù)接入方無感知。
2)降級(jí)機(jī)制:
無,每次ID產(chǎn)生均需到服務(wù)端請(qǐng)求獲取,服務(wù)端獲取失敗后拋出異常,接入業(yè)務(wù)側(cè)需介入進(jìn)行處理。
3)樣例說明:

9、魯班的業(yè)務(wù)自定義ID規(guī)則實(shí)現(xiàn)
魯班分布式ID服務(wù)內(nèi)置“Long類型”,“String類型”,“MixId類型”等三種長(zhǎng)度與規(guī)則固定的ID生成算法。除以上三種類型的ID生成算法外,業(yè)務(wù)側(cè)往往有自定義ID長(zhǎng)度與規(guī)則的場(chǎng)景訴求。
在魯班分布式ID服務(wù)內(nèi)置ID生成算法未能滿足業(yè)務(wù)場(chǎng)景時(shí),為了能在該場(chǎng)景快速支持業(yè)務(wù),魯班分布式ID服務(wù)提供了業(yè)務(wù)自定義接口并通過SPI機(jī)制在服務(wù)運(yùn)行時(shí)動(dòng)態(tài)加載,以實(shí)現(xiàn)業(yè)務(wù)自定義ID生成算法場(chǎng)景的支持。
相關(guān)能力的實(shí)現(xiàn)設(shè)計(jì)與接入流程如下。
1)ID的構(gòu)成部分主要分FixPart、DynPart、SelfIncreasePart三個(gè)部分。
2)魯班分布式ID服務(wù)的客戶端SDK提供?LuBanGlobalIDClient的接口與getGlobalId(...)/setFixPart(...)/setDynPart(...)/setSelfIncreasePart(...)等四個(gè)接口方法。
3)業(yè)務(wù)側(cè)實(shí)現(xiàn)LuBanGlobalIDClient接口內(nèi)的4個(gè)方法,通過SPI機(jī)制在業(yè)務(wù)側(cè)服務(wù)進(jìn)行加載,并向外暴露出HTTP或DUBBO協(xié)議的接口。
4)用戶在魯班分布式ID服務(wù)管理后臺(tái)對(duì)自定義ID生成算法的類型名稱與服務(wù)地址信息進(jìn)行配置,并關(guān)聯(lián)需要使用的AK接入信息。
5)業(yè)務(wù)側(cè)使用時(shí)調(diào)用客戶端SDK提供的LuBanGlobalIDClient的接口與getGlobalId方法,并傳入ID生成算法類型與IdRequest入?yún)?duì)象,魯班分布式ID服務(wù)接收請(qǐng)求后,動(dòng)態(tài)識(shí)別與路由到對(duì)應(yīng)ID生產(chǎn)算法的實(shí)現(xiàn)服務(wù),并構(gòu)建對(duì)象的ID返回給客戶端,完成整個(gè)ID生成與獲取的過程。
10、魯班保證ID生成不重復(fù)的方案
眾所周之,如何保證ID服務(wù)生成的ID不碰撞、不重復(fù),是最基本的要求之一。
我們是這樣做的:

11、魯班的無狀態(tài)無損管理
服務(wù)部署的環(huán)境在虛擬機(jī)上,ip是固定,常規(guī)的做法是在配置表里配置ip與機(jī)器碼的綁定關(guān)系(這樣在服務(wù)擴(kuò)縮容的時(shí)候就需要人為介入操作,存在一定的遺漏配置風(fēng)險(xiǎn),也帶來了一定的運(yùn)維成本)。
但在容器的部署場(chǎng)景,因?yàn)槊看尾渴饡r(shí)IP均是動(dòng)態(tài)變化的,以前通過配置表里ip與機(jī)器碼的映射關(guān)系的配置實(shí)現(xiàn)方式顯然不能滿足運(yùn)行在容器場(chǎng)景的訴求,故在服務(wù)端設(shè)計(jì)了通過心跳上報(bào)實(shí)現(xiàn)機(jī)器碼動(dòng)態(tài)分配的機(jī)制,實(shí)現(xiàn)服務(wù)端節(jié)點(diǎn)ip與機(jī)器碼動(dòng)態(tài)分配、綁定的能力,達(dá)成部署自動(dòng)化與無損發(fā)布的目的。
相關(guān)流程如下:

需要注意的是:
服務(wù)端節(jié)點(diǎn)可能因?yàn)楫惓?非正常地退出,對(duì)于該場(chǎng)景,這里就需要有一個(gè)解綁的過程,當(dāng)前實(shí)現(xiàn)是通過公司平臺(tái)團(tuán)隊(duì)的分布式定時(shí)任務(wù)服務(wù),檢查持續(xù)5分鐘(可配置)沒有上報(bào)心跳的機(jī)器碼分配節(jié)點(diǎn)進(jìn)行數(shù)據(jù)庫綁定信息清理的邏輯,重置相關(guān)機(jī)器碼的位置供后續(xù)注冊(cè)綁定使用。
12、魯班的使用方接入SDK的設(shè)計(jì)
SDK設(shè)計(jì)主要以"接入快捷,使用簡(jiǎn)單"的原則進(jìn)行設(shè)計(jì)。
1)接入時(shí):
魯班分布式ID服務(wù)提供了spring-starter包,應(yīng)用只需再pom文件依賴該starter,在啟動(dòng)類里添加@EnableGlobalClient,并配置AK/SK等租戶參數(shù)即可完成接入。
同時(shí)魯班分布式ID服務(wù)提供Dubbo & Http的調(diào)用方式,通過在啟動(dòng)注解配置accessType為HTTP/DUBBO來確定,SDK自動(dòng)加載相關(guān)依賴。
2)使用時(shí):
根據(jù)"Long"、"String"、"MixId"等三種id類型分別提供GlobalIdLongClient、GlobalIdStringClient、GlobalIdMixIDClient等三個(gè)客戶端對(duì)象,并封裝了統(tǒng)一的入?yún)equestDTO對(duì)象,業(yè)務(wù)系統(tǒng)使用時(shí)只需構(gòu)建對(duì)應(yīng)Id類型的RequestDTO對(duì)象(支持鏈?zhǔn)綐?gòu)建),并調(diào)用對(duì)應(yīng)id類型的客戶端對(duì)象getGlobalID(GlobalBaseRequestDTO?globalBaseRequestDTO)方法,即可完成ID的構(gòu)建。
Long類型Id獲取代碼示例:
packagecom.vivo.it.demo.controller;
?
importcom.vivo.it.platform.luban.id.client.GlobalIdLongClient;
importcom.vivo.it.platform.luban.id.dto.GlobalLongIDRequestDTO;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.RequestMapping;
?
@RequestMapping("/globalId")
publicclassGlobalIdDemoController {
?
????@Autowired
????privateGlobalIdLongClient globalIdLongClient;
?
????@RequestMapping("/getLongId")
????publicString getLongId() {
????????GlobalLongIDRequestDTO globalLongIDRequestDTO = GlobalLongIDRequestDTO.Builder()
????????????????.setAgent("1") //代理,接入申請(qǐng)時(shí)確定
????????????????.setZone("0") //大區(qū),接入申請(qǐng)時(shí)確定
????????????????.setApp("8") //應(yīng)用,接入申請(qǐng)時(shí)確定
????????????????.setProject("7") //項(xiàng)目,接入申請(qǐng)時(shí)確定
????????????????.setIdNumber(2); //當(dāng)次返回的id數(shù)量,只對(duì)getGlobalIDQueue有效,對(duì)getGlobalID(...)無效
????????longlongId = globalIdLongClient.getGlobalID(globalLongIDRequestDTO);
????????returnString.valueOf(longId);
????}
}
13、魯班的關(guān)鍵運(yùn)行性能優(yōu)化場(chǎng)景
13.1內(nèi)存使用優(yōu)化
在項(xiàng)目上線初時(shí),經(jīng)常發(fā)生FGC,導(dǎo)致服務(wù)停頓,獲取ID超時(shí)。
經(jīng)過分析,魯班分布式ID服務(wù)的服務(wù)端主要為內(nèi)存敏感的應(yīng)用,當(dāng)高并發(fā)請(qǐng)求時(shí),過多對(duì)象進(jìn)入老年代從而觸發(fā)FGC。
經(jīng)過排查主要是JVM內(nèi)存參數(shù)上線時(shí)是使用默認(rèn)的,沒有經(jīng)過優(yōu)化配置,JVM初始化的內(nèi)存較少,高并發(fā)請(qǐng)求時(shí)JVM頻繁觸發(fā)內(nèi)存重分配,相關(guān)的對(duì)象也流程老年代導(dǎo)致最終頻繁發(fā)送FGC。
對(duì)于這個(gè)場(chǎng)景的優(yōu)化思路主要是要相關(guān)內(nèi)存對(duì)象在年輕代時(shí)就快速經(jīng)過YGC回收,盡量少的對(duì)象進(jìn)行老年代而引起FGC。
基于以上的思路主要做了以下的優(yōu)化:
1)增大JVM初始化內(nèi)存(-Xms,容器場(chǎng)景里為-XX:InitialRAMPercentage);
2)增大年輕代內(nèi)存(-Xmn);
3)優(yōu)化代碼,減少代碼里臨時(shí)對(duì)象的復(fù)制與創(chuàng)建。
13.2鎖顆粒度優(yōu)化
客戶端SDK再自增值使用完或一定時(shí)間后會(huì)向服務(wù)端請(qǐng)求新的id生成,這個(gè)時(shí)候需要保證該次請(qǐng)求在多線程并發(fā)時(shí)是只請(qǐng)求一次。
當(dāng)前設(shè)計(jì)是基于用戶申請(qǐng)ID的接入配置,組成為key,去獲取對(duì)應(yīng)key的對(duì)象鎖,以減少同步代碼塊鎖的粒度,避免不同接入配置去在并發(fā)去遠(yuǎn)程獲取新的id時(shí),鎖粒度過大,造成線程的阻塞,從而提升在高并發(fā)場(chǎng)景下的性能。
14、應(yīng)用現(xiàn)狀
當(dāng)前魯班分布式ID服務(wù)日均ID生成量?jī)|級(jí),平均RT在0~1ms內(nèi),單節(jié)點(diǎn)可支持 萬級(jí)QPS,已全面應(yīng)用在公司IT內(nèi)部營(yíng)銷訂單、支付單據(jù)、庫存單據(jù)、履約單據(jù)、資產(chǎn)管理編碼等多個(gè)領(lǐng)域的業(yè)務(wù)場(chǎng)景。
15、未來規(guī)劃
在可用性方面,當(dāng)前魯班分布式ID服務(wù)仍對(duì)Redis、Mysql等外部DB組件有一定的依賴(如應(yīng)用接入配置信息、MixId類型自增部分ID計(jì)數(shù)器),規(guī)劃在該依賴極端宕機(jī)的場(chǎng)景下,魯班分布式ID服務(wù)仍能有一些降級(jí)策略,為業(yè)務(wù)提供可用的服務(wù)。
同時(shí)基于業(yè)務(wù)場(chǎng)景的訴求,支持標(biāo)準(zhǔn)形式的雪花算法等ID類型。
16、參考資料
[1]?微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)
[2]?解密融云IM產(chǎn)品的聊天消息ID生成策略
[3]?深度解密美團(tuán)的分布式ID生成算法
[4]?開源分布式ID生成器UidGenerator的技術(shù)實(shí)現(xiàn)
[5]?深度解密滴滴的高性能ID生成器(Tinyid)
(本文已同步發(fā)布于:http://www.52im.net/thread-4378-1-1.html)