分表後無法依賴單表自增 ID,需全局唯一 ID 生成策略。本文對比資料庫自增表、Redis 原子計數器、隊列預分配三大方案,分析高併發性能、可用性、業務靈活度,助您選型落地。
分表將數據分散至多張表,各表自增 ID 獨立 → 全局 ID 衝突。MySQL 無 Sequence 物件,需自行實現全局 ID 生成器。
CREATE TABLE create_id (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE=MyISAM; -- MyISAM 表鎖效能較 InnoDB 穩定
PHP 獲取 ID:
function get_AI_ID() {
$this->db->query("INSERT INTO create_id (id) VALUES ('')");
return $this->db->insert_id();
}
innodb_autoinc_lock_mode 控制鎖行為
結論:低併發可用,高併發成為瓶頸。
function get_next_autoincrement($timeout = 60) {
// 分布式鎖防止並發初始化
if (!acquire_lock("serial:lock", $timeout)) return 0;
$id = $redis->incr("serial");
if ($id > 1) { release_lock(); return $id; }
// 首次初始化:從 DB 讀取最大 ID
$maxId = $db->query("SELECT MAX(id) FROM user_posts")->fetchColumn();
$id = $maxId + 1;
$redis->set("serial", $id);
release_lock();
return $id;
}
優點:極高吞吐、原子操作、支援集群。缺點:引入外部依賴、需處理持久化一致性。
class IDGenerator {
private $redis;
public function __construct() { $this->redis = new Redis(); $this->redis->connect('127.0.0.1', 6379); }
// 批量注入 ID 池
public function refill_pool($ids) {
foreach ($ids as $id) $this->redis->lPush('id_pool', $id);
}
// 獲取 ID
public function next_id() { return $this->redis->lPop('id_pool'); }
}
// 初始化:生成 20 個不重複隨機 ID
$ids = [];
while (count($ids) < 20) {
$n = rand(1000, 4000);
if (!in_array($n, $ids)) $ids[] = $n;
}
$gen = new IDGenerator();
$gen->refill_pool($ids);
優點:可預分配「靚號」、支援業務語義 ID、削峰填谷。缺點:需監控池水位、自動補充邏輯複雜。
| 場景 | 推薦方案 | 核心理由 |
|---|---|---|
| 中小併發、簡單架構 | 資料庫自增表 (InnoDB mode=2) | 零依賴、ACID 保證 |
| 高併發、微服務 | Redis 原子計數器 / Snowflake 演算法 | 水平擴展、毫秒級吞吐 |
| 業務需語義 ID (靚號、分段) | 隊列預分配 | 靈活控制 ID 分佈 |
64-bit 長整數:1bit 符號 | 41bit 時間戳 | 10bit 機器碼 | 12bit 序列號,單機每秒 409 萬 ID,無中心協調,適合大規模分布式系統。
根據業務規模與架構演進,選擇最適合的全局 ID 策略。