首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

高併發下 MySQL 計數器設計:從單行鎖到隨機分桶優化方案

     編輯:MySQL 綜合教學

高併發下 MySQL 計數器設計:從單行鎖到隨機分桶優化方案

文章點擊數、商品瀏覽量等計數場景在高併發下若直接更新同一行,會產生嚴重的行鎖爭用,導致效能瓶頸。本文演進式介紹三種設計方案,並給出 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;

效能權衡

  • 寫入效能:分桶越多,鎖衝突越低,吞吐越高。
  • 讀取成本:需掃描多行聚合,桶數過大查詢變慢。
  • 建議:小流量 3-5 桶足矣,大流量可擴至 100 桶;亦可結合 Redis 預聚合定期落庫。

總結

「空間換時間」是高併發計數器的核心思想。隨機分桶將單點寫入壓力分散,犧牲少量讀取效能與開發複雜度,換取寫入吞吐量的線性擴展。實際專案需根據 QPS、一致性要求找到平衡點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved