數據庫自增ID機制原理介紹
在分布式里面,數據庫的自增ID機制的主要原理是:數據庫自增ID和mysql數據庫的replace_into()函數實現的。這里的replace數據庫自增ID和mysql數據庫的replace_into()函數實現的。這里的replace into跟insert功能類似,不同點在於:replace into首先嘗試插入數據列表中,如果發現表中已經有此行數據(根據主鍵或唯一索引判斷)則先刪除,再插入。否則直接插入新數據。
單機mysql數據庫的自增id實現如下所示 :
首先表結構如下所示
create table t_test(
id bigint(20) unsigned not null auto_increment PRIMARY KEY,
stub char(1) not null default '',
unique key stub (stub)
)
然后我們插入的sql語句和查詢的語句如下所示
replace into t_test (stub) values('b');
select last_insert_id();
此時可以看到看到我們剛剛插入的id值是1
以上就是單機版mysql的自增id的實現過程,但是這里講的是分布式id,所以我們要分析一下數據庫的自增ID機制在分布式里面是怎么實現的。
分布式id在數據庫里面的實現過程:
既然是分布式id,那么最少要使用兩個數據庫,這里我們使用3台來講解,為了保證每一台數據庫里面的id自增的時候不會重復,那么我們就要給每一台數據庫設置auto-increment-increment和auto-increment-offset這兩個屬性值(auto-increment-increment表示每一台數據庫的起始id值,然后auto-increment-offset表示每一台數據庫每一次的增加數字),設置值如下所示
Server1:
auto-increment-increment = 1
auto-increment-offset = 3
Server2:
auto-increment-increment = 2
auto-increment-offset = 3
Server2:
auto-increment-increment = 3
auto-increment-offset = 3
那么如果我們有n台數據庫的話,那么上面的auto-increment-increment和auto-increment-offset這兩個屬性值應該怎么設計呢,我們給每一台數據庫設置初始值分別為1,2,3...N,然后每一台數據庫自增步長為機器的台數N,如下圖所示
數據庫自增ID是否適合做分布式ID:
那數據庫自增ID機制適合作分布式ID嗎?答案是不太適合,為什么呢,我總結了下面兩個原因:
1:系統水平擴展比較困難,比如定義好了步長和機器台數之后,如果要添加機器該怎么做?假設現在只有一台機器發號是1,2,3,4,5(步長是1),這個時候需要擴容機器一台。可以這樣做:把第二台機器的初始值設置得比第一台超過很多,比如14(主要這里設置14的前提是:在擴容期間第一台機器的ID不可能增加到14),同時設置步長為2,那么這台機器下發的號碼都是14以后的偶數。然后摘掉第一台,把ID值保留為奇數,比如7,然后修改第一台的步長為2。讓它符合我們定義的號段標准。擴容方案看起來復雜嗎?貌似還好,現在想象一下如果我們線上有100台機器,這個時候要擴容該怎么做?簡直是噩夢。所以系統水平擴展方案復雜難以實現。
2:數據庫壓力還是很大,每次獲取ID都得讀寫一次數據庫,非常影響性能,不符合分布式ID里面的延遲低和要高QPS的規則(在高並發下,如果都去數據庫里面獲取id,那是非常影響性能的)
看到這里的同學,覺得好的話就幫忙推薦下吧,Thanks♪(・ω・)ノ
其他分布式ID系列快捷鍵:
分布式ID系列(1)——為什么需要分布式ID以及分布式ID的業務需求
分布式ID系列(2)——UUID適合做分布式ID嗎
分布式ID系列(3)——數據庫自增ID機制適合做分布式ID嗎
分布式ID系列(4)——Redis集群實現的分布式ID適合做分布式ID嗎
分布式ID系列(5)——Twitter的雪法算法Snowflake適合做分布式ID嗎