首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 全局 ID 生成方案深度解析:CAS、分布式鎖、Redis 混合、Flicker 方案對比

     編輯:MySQL 資料庫相關知識

前言

業務增長驅動分庫分表,Sharding Key 必須全局唯一。本文從 DBA 視角,深度剖析四大主流全局 ID 生成方案:CAS 模式、分布式鎖、Redis+DB 混合模式、Flicker 方案,對比優劣與適用場景。

方案一:CAS 模式(比較並交換思想)

核心邏輯

  1. 從 sequence 表讀取當前最大 ID(gid)
  2. 內存中 +1 得到新 ID
  3. 執行條件更新:UPDATE sequence SET gid = 新ID WHERE name = 'xxx' AND gid < 新ID
  4. 若影響行數為 0,說明有並發搶佔,重試

表結構

CREATE TABLE `SEQUENCE` (
  `name` VARCHAR(30) NOT NULL COMMENT '分表表名',
  `gid` BIGINT(20) NOT NULL COMMENT '最大全局ID',
  PRIMARY KEY (`name`)
) ENGINE=InnoDB;

Java 實現片段

public long nextIdDb(String name) {
  SequenceDao dao = SequenceDao.getInstance();
  int threshold = 100;
  for (int i = 0; i < threshold; i++) {
    long lastId = dao.getSeqId(name);
    long id = lastId + 1;
    if (dao.setSeqId(name, id)) return id;
  }
  throw new RuntimeException("ID生成失敗");
}

優缺點

  • ✅ 無額外中間件依賴、實現簡單
  • ✅ 樂觀鎖無阻塞、高併發表現尚可
  • ❌ 高併發下重試開銷大、DB 成瓶頸
  • ❌ 單點風險(需主從或雙主)

方案二:分布式鎖(Redis/Memcached)

核心邏輯

  1. 用 SETNX (Redis) 或 add (Memcached) 嘗試獲取鎖
  2. 獲取成功 → INCR 生成 ID → 寫回 DB → 釋放鎖
  3. 獲取失敗 → 自旋等待 → 重試
  4. Redis 宕機時降級到 DB CAS 模式

Redis 實現關鍵代碼

public long nextIdRedis(String name) {
  // 嘗試獲取鎖
  while (true) {
    if (redis.setnx("sequence_" + name + "_flag", timestamp)) break;
    if (超時或重試上限) break;
  }
  // 生成 ID
  long id = redis.incr("sequence_" + name);
  if (id == 1 || id == false) { // 首次或失效,從 DB 回載
    long lastId = dao.getSeqId(name);
    redis.set("sequence_" + name, lastId);
    id = redis.incr("sequence_" + name);
  }
  dao.setSeqId(name, id); // 持久化到 DB
  redis.del("sequence_" + name + "_flag"); // 釋放鎖
  return id;
}

優缺點

  • ✅ 性能極高(內存操作)、支援高併發
  • ❌ 引入 Redis 依賴、運維複雜度上升
  • ❌ 鎖超時、網路分區可能導致重複 ID 或死鎖

方案三:Redis + DB 混合模式(生產推薦)

public long nextId(String name) {
  try {
    return nextIdRedis(name);
  } catch (Exception e) {
    log.warn("Redis不可用,降級DB模式", e);
    return nextIdDb(name);
  }
}

結合兩者優點:平時走 Redis 高性能,故障自動降級 DB 保可用。

方案四:Flicker 方案(MySQL 自增 + 雙主奇偶)

架構

  • 專用 Ticket 資料庫,表結構同方案一
  • 兩台 MySQL:auto_increment_increment=2,offset=1/2 產生奇/偶 ID
  • 客戶端輪詢獲取

優缺點

  • ✅ 充分利用原生自增、ID 有序、極高可靠
  • ❌ 佔用兩獨立 MySQL 實例、成本高
  • ❌ ID 非連續(間隔 2)、跨機房延遲敏感

方案對比總結表

維度CAS/DB分布式鎖Redis+DB混合Flicker雙主
性能中高高高
可用性依賴DB架構依賴Redis集群高(自動降級)極高(雙主)
實現複雜度低中中高中
ID有序性有序有序有序有序(間隔)
運維成本低中中高高
推薦場景中小併發、簡單架構高併發、有Redis核心業務、追求高可用頂級核心、資源充足

選型建議

  • 初創/中小系統:CAS + DB 最簡單、無額外依賴
  • 有 Redis 基礎設施:Redis + DB 混合 性價比最高
  • 核心交易/訂單系統:Flicker 雙主 或 Snowflake/Leaf 等成熟框架
  • 避坑指南:嚴禁使用 UUID 作為主鍵(無序、占空間大、索引效能差)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved