真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

ID生成策略——SnowFlake

一、遇到問題

創(chuàng)新互聯(lián)專注于企業(yè)營銷型網(wǎng)站、網(wǎng)站重做改版、平壩網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、H5開發(fā)成都做商城網(wǎng)站、集團公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為平壩等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。


某個項目采用了數(shù)據(jù)庫(MySQL)自增ID作為主要業(yè)務(wù)數(shù)據(jù)的主鍵。數(shù)據(jù)庫自增ID使用簡單,自動編號,速度快,而且是增量增長,按順序存放,對于檢索非常有利。


單庫環(huán)境下,數(shù)據(jù)庫自增ID問題不大。但在分布式環(huán)境或分庫分表環(huán)境下,數(shù)據(jù)庫自增ID逐漸暴露出一些問題。例如,分庫分表的情況下保證ID唯一變得困難;訂單號等業(yè)務(wù)數(shù)據(jù)如果用數(shù)據(jù)庫自增ID,競對很容易算出大概的業(yè)務(wù)量。


二、常見的ID生成策略


1、數(shù)據(jù)庫自增ID(前面提到了)


2、UUID

算法的核心思想是結(jié)合機器的網(wǎng)卡、當(dāng)?shù)貢r間、一個隨記數(shù)來生成UUID。

優(yōu)點:本地生成,生成簡單,性能好,沒有高可用風(fēng)險

缺點:長度過長,存儲冗余,且無序不可讀,查詢效率低


3、redis生成ID

Redis生成ID可以看做數(shù)據(jù)庫自增ID的升級版。Redis的所有命令操作都是單線程的,本身提供像 incr 和 increby 這樣的自增原子命令,所以能保證生成的 ID 肯定是唯一有序的。


優(yōu)點:不依賴于數(shù)據(jù)庫,靈活方便,且性能優(yōu)于數(shù)據(jù)庫;數(shù)字ID天然排序,對分頁或者需要排序的結(jié)果很有幫助。

缺點:如果系統(tǒng)中沒有Redis,還需要引入新的組件,增加系統(tǒng)復(fù)雜度;需要編碼和配置的工作量比較大。


考慮到單節(jié)點的性能瓶頸,可以使用 Redis 集群來獲取更高的吞吐量。假如一個集群中有5臺 Redis??梢猿跏蓟颗_ Redis 的值分別是1, 2, 3, 4, 5,然后步長都是 5。各個 Redis 生成的 ID 為

ID生成策略——SnowFlake

4、Twitter的snowflake算法。


三、snowflake算法


snowflake算法,采用64位二進制整數(shù)。二進制具體位數(shù)含義如下圖。

ID生成策略——SnowFlake

1位,不用。二進制中最高位為1的都是負數(shù),但是我們生成的id都使用正數(shù),所以這個最高位固定是0


41位,用來記錄時間戳(毫秒)。

如果只用來表示正整數(shù)(計算機中正數(shù)包含0),可以表示的數(shù)值范圍是:0 至 241?1,減1是因為可表示的數(shù)值范圍是從0開始算的,而不是1。

也就是說41位可以表示241?1個毫秒的值,轉(zhuǎn)化成單位年則是(241?1)/(1000?60?60?24?365)=69年


10位,用來記錄工作機器id。

可以部署在1024個節(jié)點,包括5位datacenterId和5位workerId


12位,序列號,用來記錄同毫秒內(nèi)產(chǎn)生的不同id。

12位(bit)可以表示的最大正整數(shù)是4095,即可以用0、1、2、3、....4095這4096個數(shù)字,來表示同一機器同一時間截(毫秒)內(nèi)產(chǎn)生的4096個ID序號

大多數(shù)人都知道這個算法,但Twitter 利用 zookeeper 還做了很多工程上的實現(xiàn),感興趣可以看https://github.com/twitter/snowflake

截取git上該工程的主要文件目錄, 

ID生成策略——SnowFlake

git工程README.md文件中有這么一段話

We have retired the initial release of Snowflake and working on open sourcing the next version based on Twitter-server, in a form that can run anywhere without requiring Twitter's own infrastructure services.


Twitter幾年前就停止了對這個項目的維護,新的版本也沒見著放出來。好在現(xiàn)有版本的核心算法已經(jīng)能夠滿足常規(guī)的需求。


當(dāng)然,snowflake有眾多優(yōu)點的同時也是有缺點的。


優(yōu)點:

毫秒數(shù)在高位,自增序列在低位,整個ID都是趨勢遞增的。

不依賴數(shù)據(jù)庫等第三方系統(tǒng),以服務(wù)的方式部署,穩(wěn)定性更高,生成ID的性能也是非常高的。

可以根據(jù)自身業(yè)務(wù)特性分配bit位,非常靈活。


缺點:

強依賴機器時鐘,如果機器上時鐘回撥,會導(dǎo)致發(fā)號重復(fù)或者服務(wù)會處于不可用狀態(tài)。

強依賴時鐘在有些情況下很致命,我個人就遇到過服務(wù)器剛重啟的短時間內(nèi)時間沒有同步,造成生成ID出問題的情況!


四、一些改進策略


1、美團Leaf比較完美的方案


美團Leaf比較好的解決了這些問題,參看《Leaf——來自美團點評的分布式ID生成系統(tǒng)》

美團Leaf的方案核心有兩點

(1)依靠zookeeper實現(xiàn)workerId的自動化租用

(2)通過算法解決了時鐘回撥問題

美團Leaf目前是開源軟件,可以在https://github.com/weizhenyi/leaf-snowflake下載


2、一個候選人不嚴謹?shù)杀竞艿偷膶崿F(xiàn)


我在面試中,一個候選人提出的方法也比較有意思(盡管這個方法不嚴謹)。

在redis中設(shè)置一個整數(shù)變量workerNum,初始值為0,snowflake id生成客戶端每次啟動時讀取redis中的變量,用workerNum%1024作為worker的值,然后把redis中的workerNum+1。

在idworker數(shù)量不多的情況下,這個方案一般不會出現(xiàn)workerId重復(fù)(因為隨著業(yè)務(wù)的迭代,一般情況下idworker過一段時間都會因為業(yè)務(wù)部署而重啟)。如果研發(fā)資源特別有限,又想使用snowflake可以考慮一下這個辦法。 

ID生成策略——SnowFlake

3、個人項目中hash分庫的解決辦法


實際使用中,有時候ID需要支持分庫分表,snowflake的默認實現(xiàn)對這塊支持得不夠。在業(yè)務(wù)量不大的情況下,snowflake生成的id序列號部分大多都是0,轉(zhuǎn)換為十進制會是偶數(shù)。用這個id通過取模hash分庫,顯然不平均。


萬一有這樣的需求怎么辦呢?可以考慮借助ID時間戳部分實現(xiàn)均勻分布

(1)分庫分表邏輯使用ID中時間戳部分做取模。這個方法需要把10進制ID轉(zhuǎn)成2進制,然后移位,再進行計算。比較麻煩

(2)生成ID的時候把序列號部分尾數(shù)用時間戳對應(yīng)的位置覆蓋。截段代碼,這段代碼的取值能保證ID除以128的余數(shù)均勻分布。 

ID生成策略——SnowFlake


當(dāng)前文章:ID生成策略——SnowFlake
分享鏈接:http://weahome.cn/article/pcdoch.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部