唯一主鍵方案之數據庫維護區間分配

我們介紹一種基於數據庫維護自增 ID 區間,結合內存分配的策略,這也是淘寶的 TDDL 等數據庫中間件使用的主鍵生成策略。

使用這種方式首先在數據庫中創建 sequence 表,其中的每一行,用於記錄某個業務主鍵當前已經被佔用的 ID 區間的最大值。sequence 表的主要字段是 name 和 value,其中 name 是當前業務序列的名稱,value 存儲已經分配出去的 ID 最大值。

CREATE TABLE `sequence_global` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Id',
  `app_name` varchar(64) NOT NULL COMMENT 'sequence name',
  `app_value` bigint(32) NOT NULL COMMENT 'sequence current value',
   `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間',
   PRIMARY KEY (`id`),
  UNIQUE KEY `unique_name` (`app_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

接下來插入一條行記錄,當需要獲取主鍵時,每臺服務器主機從數據表中取對應的 ID 區間緩存在本地,同時更新 sequence 表中的 value 最大值記錄。

現在我們新建一條記錄,比如設置一條 order 更新的規則,插入一行記錄如下:

INSERT INTO sequence_global(app_name,app_value,create_time,update_time) values('test',200,now(),now());

當服務器在獲取主鍵增長區段時,首先訪問對應數據庫的 sequence 表,更新對應的記錄,佔用一個對應的區間。比如我們這裏設置步長爲 200,原先的 value 值爲 1000,更新後的 value 就變爲了 1200。

取到對應的 ID 區間後,在服務器內部進行分配,涉及的併發問題可以依賴樂觀鎖等機制解決。

有了對應的 ID 增長區間,在本地就可以使用 AtomicInteger 等方式進行 ID 分配。

不同的機器在相同時間內分配出去的 ID 可能不同,這種方式生成的唯一 ID,不保證嚴格的時間序遞增,但是可以保證整體的趨勢遞增,在實際生產中有比較多的應用。

爲了防止單點故障,sequence 表所在的數據庫,通常會配置多個從庫,實現高可用。

參考代碼實現:https://github.com/JMCuixy/dubbo-demo/tree/master/sequence

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