數據庫自增ID機制原理介紹
在分佈式裡面,數據庫的自增ID機制的主要原理是:數據庫自增ID和mysql數據庫的replaceinto()函數實現的。這裡的replace數據庫自增ID和mysql數據庫的replaceinto()函數實現的。這裡的replace into跟insert功能類似,不同點在於:replace into首先嚐試插入數據列表中,如果發現表中已經有此行數據(根據主鍵或唯一索引判斷)則先刪除,再插入。否則直接插入新數據。
單機mysql數據庫的自增id實現如下所示 :
首先表結構如下所示
create table t_test( id bigint(20)unsignednotnull auto_increment PRIMARY KEY, stub char(1)notnulldefault'', 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,那是非常影響性能的)
關鍵字: 屬性值 自增 auto-increment-increment