雪花算法
常見生成方式
UUID
- 標(biāo)準(zhǔn)型式包含 32 個(gè) 16 進(jìn)制數(shù)字,以連字號(hào)分為五段,形式為 8-4-4-4-12 的 36 個(gè)字符
- 性能非常高,本地生成,沒有網(wǎng)絡(luò)消耗
- UUID.randomUUID().toString()
為什么無序的 UUID 會(huì)導(dǎo)致入庫性能變差
- 分布式 ID 一般會(huì)作為主鍵,MySQL推薦主鍵盡量越短越好,所以不是很推薦。同時(shí)UUID生成為無序的,不能生成遞增有序的數(shù)字
- 由于 MYSQL 的索引通過 B+ 樹實(shí)現(xiàn)的,每一次新的 UUID 數(shù)據(jù)的插入,為了查詢的優(yōu)化都會(huì)對(duì)索引底層的 B+ 樹進(jìn)行修改,因?yàn)?UUID 無序所以每一次插入都會(huì)對(duì)主鍵的 B+ 樹進(jìn)行很大的修改,可能會(huì)導(dǎo)致一些中間節(jié)點(diǎn)產(chǎn)生分裂,也會(huì)創(chuàng)造很多不飽和節(jié)點(diǎn),降低了數(shù)據(jù)庫插入的性能
數(shù)據(jù)庫主鍵自增
- 自增 ID 機(jī)制的主要原理是:數(shù)據(jù)庫自增 ID 和 MySQL 數(shù)據(jù)庫的replace into 實(shí)現(xiàn)
- replace into 的含義是 插入一條記錄,如果表中唯一索引的值遇到?jīng)_突,則替換老數(shù)據(jù)
缺點(diǎn)
- 系統(tǒng)水平拓展比較困難,需要定義步長和初始值來實(shí)現(xiàn),配置麻煩,利用率低
- 數(shù)據(jù)庫壓力大,每次獲取 ID都得讀寫一次數(shù)據(jù)庫,非常影響性能,不符合分布式 ID 里面的低延遲和高 QPS 要求
基于 Redis 生成全局 ID
- 與 MySQL 類似,好處是可以獲取更高的吞吐量,同時(shí)也需要設(shè)置步長和增長,key一定要設(shè)置有效期
雪花算法
- 官網(wǎng)
- Twitter 的分布式自增 ID 算法 snowflake
- 集群高并發(fā)情況下保證分布式唯一全局 ID 生成,生成的 ID 能過按照時(shí)間有序生成,結(jié)果是一個(gè) 64 bit 大小的整數(shù),為一個(gè) Long 性;分布式系統(tǒng)內(nèi)不會(huì)產(chǎn)生 ID 碰撞(由 datacenter 和 workerID 區(qū)分)并且效率較高
- 41 bit 用來記錄時(shí)間戳,毫秒級(jí);12 bit 用來記錄同毫秒內(nèi)產(chǎn)生的不同 ID
- 10 bit 工作進(jìn)程位,用來記錄工作機(jī)器ID, 一般分為 5 datacenter 和 5 workerID
分布式全局 ID 要求
- 全局唯一
- 趨勢(shì)遞增
- 單調(diào)遞增
- 信息安全
- 含時(shí)間戳
優(yōu)勢(shì)與劣勢(shì)
- 毫秒數(shù)在高位,自增序列在低位,整個(gè) ID 都是趨勢(shì)遞增的
- 不依賴數(shù)據(jù)庫等第三方系統(tǒng),以服務(wù)的方式部署,穩(wěn)定性、生成 ID 的性能高
- 可以根據(jù)自身業(yè)務(wù)特性分配 bit 位,相對(duì)靈活
- 依賴機(jī)器時(shí)鐘,如果機(jī)器時(shí)鐘回?fù)軙?huì)導(dǎo)致重復(fù) ID 生成
拓展
- 百度開源的分布式唯一 ID 生成器 UidGenerator
- 美團(tuán)點(diǎn)評(píng)分布式 ID 生成系統(tǒng) Leaf
hshuo的面試之路 文章被收錄于專欄
作者目標(biāo)是找到一份Java后端方向的工作 此專欄用來記錄從Bilibili、書本、其他優(yōu)質(zhì)博客上面學(xué)習(xí)的內(nèi)容 用于鞏固、總結(jié)內(nèi)容 主要包含Docker、Dubbo、Java基礎(chǔ)、JUC、Maven、MySQL、Redis、SpringBoot、SpringCloud、數(shù)據(jù)結(jié)構(gòu)、雜文、算法、計(jì)算機(jī)網(wǎng)絡(luò)、操作系統(tǒng)、設(shè)計(jì)模式等相關(guān)內(nèi)容