數據庫 ID 生成方案:號段模式

還可以使用號段的方式來獲取自增 ID,號段可以理解成批量獲取。比如從數據庫獲取 ID 時,就可以批量獲取多個 ID 並緩存在本地,提升效率。

比如每次從數據庫獲取 ID 時,就獲取一個號段,如 (1,1000],這個範圍表示1000個 ID,業務應用在請求提供 ID 時,只需要在本地從1開始自增並返回,而不需要每次都取請求數據庫,一直到本地自增到1000時,也就是當前號段已經用完了,纔去數據庫重新獲取下一號段。

對數據庫表進行改動如下:

CREATE TABLE Test (
  id int(10) NOT NULL,
  current_max_id bigint(20) NOT NULL COMMENT '當前最大Id',
  increment_step int(10) NOT NULL COMMENT '號段的長度',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

這個數據表是用來記錄自增步長,以及當前自增 ID 的最大值(也就是當前已被申請號段的最後那個值),而自增邏輯就移動到業務裏頭去實現,所以數據庫不需要這部分邏輯。

這種方案不再強依賴數據庫,就算數據庫不可用,那麼系統也能繼續支撐一段時間,但如果系統重啓,就會丟失一段 ID,導致 ID 空洞。

爲提高可用性,需要做一個集羣,業務在請求集羣獲取 ID 時,會隨機的選擇某個節點進行獲取,對每個節點來說,數據庫連接的是同個數據庫,那麼就可能會產生多個節點同時請求數據庫獲取號段,這時就可以利用樂觀鎖來進行控制,比如在數據庫表中增加一個 version 字段,在獲取號段時使用如下 SQL:

update Test set current_max_id = #{newMaxId}, version = version+1 where version = #{version}

以上 newMaxId 是根據 oldMaxId + 步長 算出來的,只要上面的 update 更新成功,也就表示號段獲取成功。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章