Go 基于雪花算法的分布式ID生成器
全局唯一性:不能出現(xiàn)有重復的 ID 標識,這是基本要求。
遞增性:確保生成的 ID 對于用戶或業(yè)務是遞增的。
高可用性:確保任何時候都能生成正確的D。
高性能性:在高并發(fā)的環(huán)境下依然表現(xiàn)良好。
不僅僅是用于用戶 ID ,實際互聯(lián)網(wǎng)中有很多場景需要能夠生成類似MySQL自增 ID 這樣不斷增大,同時又不會重復的 ID 。以支持業(yè)務中的高并發(fā)場景。
比較典型的場景有:電商促銷時短時間內(nèi)會有大量的訂單誦入到系統(tǒng),比如每秒10W+; 明星出軌時微博短時間內(nèi)會產(chǎn)生大量的相關(guān)微博轉(zhuǎn)發(fā)和評論消息。在這些業(yè)務場景下將數(shù)據(jù)插入數(shù)據(jù)庫之前,我們需要給這些訂單和消息先分配一個唯一ID,然后再保存到數(shù)據(jù)庫中。對這個id的要求是希望其中能帶有一些時間信息,這樣即使我們后端的系統(tǒng)對消息進行了分庫分表,也能夠以時間順序?qū)@些消息進行排序。
雪花算法
snowflake算法介紹雪花算法,它是Twitter開源的由64位整數(shù)組成分布式ID,性能較高,并且在單機上遞增。
第一位占用1bt,其值始終是0,沒有實際作用。
時間戳占用41bt,單位為毫秒,總共可以容納約69年的時間。當然,我們的時間毫秒計數(shù)不會真的從1970年開始記,那樣我們的系統(tǒng)跑到2039/9/7 23:47:35就不能用了,所以這里的時間戳只是相對于某個時間的增量,比如我們的系統(tǒng)上線是2022-05-01,那么我們完全可以把這個timestamp當作是從2022-05-01 00:00:00.000的偏移量。
工作機器 id 占用 10bit,其中高位5bit是數(shù)據(jù)中心D,低位5bit是工作節(jié)點ID,最多可以容納1024個節(jié)點。
序列號占用12bt,用來記錄同毫秒內(nèi)產(chǎn)生的不同d。每個節(jié)點每毫秒0開始不斷累加,最多可以累加到4095,同一毫秒一共可以產(chǎn)生4096個1D。 SnowFlake算法在同一毫秒內(nèi)最多可以生成多少個全局唯一ID呢? 同一毫秒的1D數(shù)量=1024X4096=4194304I
snowflake 的 Go 實現(xiàn)bwmarrin/snowflakebwmarrin/snowflake: A simple to use Go (golang) package to generate or parse Twitter snowflake IDs (github.com)
bwmarrin/snowflake 是一個輕量化的snowflake的Go實現(xiàn)。
實現(xiàn)示例:
package?mainimport?(???"fmt"???"time"???"github.com/bwmarrin/snowflake")var?node?*snowflake.Nodefunc?Init(startTime?string,?machineID?int64)?(err?error)?{???var?st?time.Time???st,?err?=?time.Parse("2006-01-02",?startTime)???if?err?!=?nil?{??????return???}???snowflake.Epoch?=?st.UnixNano()?/?1000000???node,?err?=?snowflake.NewNode(machineID)???return}func?GenID()?int64?{???return?node.Generate().Int64()}func?main()?{???if?err?:=?Init("2022-05-03",?1);?err?!=?nil?{??????fmt.Printf("init?failed,?err:%v",?err)??????return???}???id?:=?GenID()???fmt.Println(id)}sony/sonyflake
sony/sonyflake: A distributed unique ID generator inspired by Twitter's Snowflake (github.com)
sonyflake,是Sony公司的一個開源項目,基本思路和snowflake:差不多,不過位分配上稍有不同:
這里的時間只用了39個bit,但時間的單位變成了10ms,所以理論上比41位表示的時間還要久(174年)。 Sequence ID和之前的定義一致,Machine ID其實就是節(jié)點id。sonyflake庫有以下配置參數(shù):
type?Settings?struct?{????StartTime?time.Time????MachineID?func()?(uint16,?error)????CheckMachineID?func(uint16)?bool}簡單的實例:
package?mainimport?(???"fmt"???"time"???"github.com/sony/sonyflake")var?(???sonyFlake?????*sonyflake.Sonyflake?//?類似于node???sonyMachineID?uint16)func?getMachineID()?(uint16,?error)?{???return?sonyMachineID,?nil}func?Init(startTime?string,?machineID?uint16)?(err?error)?{???sonyMachineID?=?machineID???var?st?time.Time???st,?err?=?time.Parse("2006-01-02",?startTime)???if?err?!=?nil?{??????return?err???}???settings?:=?sonyflake.Settings{??????StartTime:?st,??????MachineID:?getMachineID,???}???sonyFlake?=?sonyflake.NewSonyflake(settings)???return}//?GenID?生成idfunc?GenID()?(id?uint64,?err?error)?{???if?err?!=?nil?{??????fmt.Errorf("sonyflake?init?failed,?err:%v",?err)??????return???}???id,?err?=?sonyFlake.NextID()???return}func?main()?{???if?err?:=?Init("2022-05-03",?1);?err?!=?nil?{??????fmt.Printf("Init?failed,?err:%v
",?err)??????return???}???id,?_?:=?GenID()???fmt.Println(id)}
相關(guān)評說:
安塞縣旋轉(zhuǎn): ______ 必須自行實現(xiàn) 并且要支持分布式 各個node之間的session自行同步 你是指不能使用session基于容器的的存儲方式呢,還是所容器實現(xiàn)的session完全不能用?容器實現(xiàn)的session完全不能用 問題補充:myali88 寫道引用容器實現(xiàn)的session完全不...
安塞縣旋轉(zhuǎn): ______ 作為主鍵,UUID長度過長,主鍵索引KeyLength長度過大,而影響能夠基于內(nèi)存的索引記錄數(shù)量,進而影響基于內(nèi)存的索引命中率,而基于硬盤進行索引查詢性能很差.嚴重影響數(shù)據(jù)庫服務器整體的性能表現(xiàn). 建議,如果考慮分布式,可以仿造MongoDB建立索引,能有效實現(xiàn)服務器同步,KeyLength也很小.如果使用UUID進行數(shù)據(jù)同步管理,需要對UUID字符串進行Djb的Hash算法,然后對Int/Long類型的哈希數(shù)值進行索引.第一次檢索,通過UUIDHashCode將結(jié)果集范圍縮小,再使用UUID定位具體數(shù)據(jù).這樣性能能高很多.使用Int類型的ID作為主鍵.UUID不作為主鍵,而僅作為數(shù)據(jù)同步的標記字段被使用.
安塞縣旋轉(zhuǎn): ______ 當 SET XACT_ABORT 為 ON 時,如果執(zhí)行 Transact-SQL 語句產(chǎn)生運行時錯誤,則整個事務將終止并回滾.當 SET XACT_ABORT 為 OFF 時,有時只回滾產(chǎn)生錯誤的 Transact-SQL 語句,而事務將繼續(xù)進行處理.如果錯誤很嚴重,那么即使 ...
安塞縣旋轉(zhuǎn): ______ 參照我的整理貼 --遠程連接操作 /****************************************************************************************************************************************************** --Tab表: ID 自增列 Name ----------- --------- 1 a 2 b 3 c --存儲過程: create proc P ...
安塞縣旋轉(zhuǎn): ______ 1. 把用戶ID,用可逆加密的方式,存儲于Cookie中.當用戶登陸成功時,ID經(jīng)過加密存儲.用戶第一次訪問A頁面,通過解密ID,如果解密成功,然后調(diào)用SOA(或者其他分布式服務實現(xiàn),可以達到隨意擴展,而不用更改調(diào)用端),獲取用戶信...
安塞縣旋轉(zhuǎn): ______ 云存儲系統(tǒng)具有良好的可擴展性、容錯性,以及內(nèi)部實現(xiàn)對用戶透明等特性,這一切都離不開分布式文件系統(tǒng)的支撐.現(xiàn)有的云存儲分布式文件系統(tǒng)包括GFS、HDFS、Lustre、FastDFS、PVFS、GPFS、PFS...
安塞縣旋轉(zhuǎn): ______ 詳細和你說一下星型模型和雪花模型 星型模式 vs 雪花模型多維數(shù)據(jù)建模以直觀的方式組織數(shù)據(jù),并支持高性能的數(shù)據(jù)訪問.每一個多維數(shù)據(jù)模型由多個多維數(shù)據(jù)模式表示,每一個多維數(shù)據(jù)模式都是由一個事實表和一組維表組成的.多維模型最...
安塞縣旋轉(zhuǎn): ______ 慢的原因是你在對List的循環(huán)中使用了List的get函數(shù).典型的"Shlemiel噴涂算法",所以越跑越慢啊.List里是一個鏈表,get方法會從頭一個個地數(shù),越到后面,數(shù)的時間就越長.所以會...
安塞縣旋轉(zhuǎn): ______ 自動化專業(yè) 概述: 自動化專業(yè)主要研究的是自動控制的原理和方法,自動化單元技... 自動控制理論、運籌學、信號與系統(tǒng)分析、計算機軟件技術(shù)應用、算法語言及程序設(shè)計...
安塞縣旋轉(zhuǎn): ______ spark最大優(yōu)勢在于是基于內(nèi)存的分布式計算框架,在計算速度方面可甩hadoop好幾條街.天生就適合于多迭代的業(yè)務場景,在機器學習算法上能夠充分體現(xiàn).另外,spark還支持準實時流式框架spark streaming,分布式查詢spark SQL、圖計算...