文章點擊數、商品瀏覽量等計數場景在高併發下若直接更新同一行,會產生嚴重的行鎖爭用,導致效能瓶頸。本文演進式介紹三種設計方案,並給出 SQL 實作範例。
CREATE TABLE article (
article_id INT PRIMARY KEY,
article_view INT NOT NULL DEFAULT 0,
...
) ENGINE=InnoDB;
缺點:讀寫混雜,鎖衝突大,不利於分庫分表。
CREATE TABLE article_view (
article_id INT NOT NULL,
view INT NOT NULL DEFAULT 0,
PRIMARY KEY (article_id)
) ENGINE=InnoDB;
雖分離了熱點,但單行更新仍串行化,高併發下等待時間長。
將一個文章的計數拆分為多行(如 100 桶),寫入時隨機選一桶 UPDATE 或 INSERT,讀取時 SUM 聚合。
CREATE TABLE article_view (
article_id INT NOT NULL,
pond TINYINT NOT NULL COMMENT '分桶編號 1-100',
view INT NOT NULL DEFAULT 0,
PRIMARY KEY (article_id, pond)
) ENGINE=InnoDB;
寫入邏輯(利用 ON DUPLICATE KEY UPDATE):
INSERT INTO article_view (article_id, pond, view)
VALUES (123, FLOOR(RAND()*100)+1, 1)
ON DUPLICATE KEY UPDATE view = view + 1;
讀取總數:
SELECT SUM(view) FROM article_view WHERE article_id = 123;
「空間換時間」是高併發計數器的核心思想。隨機分桶將單點寫入壓力分散,犧牲少量讀取效能與開發複雜度,換取寫入吞吐量的線性擴展。實際專案需根據 QPS、一致性要求找到平衡點。