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

高併發系統資料冪等性解決方案:7 大核心策略完整指南

     編輯:關於SqlServer

什麼是冪等性

冪等:N 次操作與 1 次操作結果相同。高併發系統中,網路重試、重複提交、訊息重發皆可能導致非冪等操作產生嚴重後果(如重複下單、重複扣款)。

7 大冪等解決方案

1. 查詢操作:天然冪等

SELECT 無副作用,天然滿足冪等。無需額外處理。

2. MVCC 樂觀鎖:更新帶條件

-- 版本號樂觀鎖
UPDATE Table_X SET Name = #Name#, Version = Version + 1 WHERE Version = #Version#;

-- 業務條件樂觀鎖(扣庫存)
UPDATE Table_X SET Qty = Qty - #SubQty# WHERE Qty - #SubQty# >= 0;

適用於更新操作,利用資料庫行級鎖與條件判斷保證冪等。

3. 獨立去重表:唯一索引防重

CREATE TABLE Biz_Dedup (
    Biz_Type VARCHAR(20),
    Biz_Key  VARCHAR(100),
    Created_At DATETIME DEFAULT GETDATE(),
    PRIMARY KEY (Biz_Type, Biz_Key)
);

插入業務資料前,先插入去重表。利用主鍵/唯一索引衝突攔截重複。適合多業務類型、去重邏輯統一場景。

4. 分散式鎖:跨服務協調

使用 Redis (Redisson)、ZooKeeper、etcd 實現分散式鎖:

RLock lock = redisson.getLock("biz:order:" + orderId);
lock.lock();
try {
    // 業務邏輯
} finally {
    lock.unlock();
}

適用於分散式系統、無法確定唯一業務鍵場景。注意鎖超時、續約、可用性設計。

5. 刪除操作:冪等語義設計

DELETE FROM Table WHERE Id = #Id#;  -- 多次執行結果相同
-- 或軟刪除
UPDATE Table SET Deleted = 1 WHERE Id = #Id# AND Deleted = 0;

刪除天然冪等(結果態相同),軟刪除需加條件避免重複更新觸發器。

6. 插入唯一索引:業務主鍵約束

CREATE UNIQUE INDEX UX_Order_User_Date ON Orders (UserId, OrderDate, ProductId);

資料庫層面強制唯一。API 層面可增加客戶端生成 UUID,伺服端以 UUID 去重:

// 客戶端生成
String idempotencyKey = UUID.randomUUID().toString();
// 伺服端驗證
if (redis.setnx("idem:" + idempotencyKey, "1", 24, TimeUnit.HOURS)) {
    // 執行業務
}

7. 狀態機冪等:狀態流向控制

訂單狀態:建立 → 付款 → 發貨 → 完成

UPDATE Orders SET Status = 'PAID' 
WHERE OrderId = #Id# AND Status = 'CREATED';  -- 僅允許 CREATED → PAID

非預期狀態轉換(如 PAID → CREATED)直接拒絕,保證狀態流向單向性與冪等。

方案選擇指引

場景推薦方案備註
單機更新MVCC 樂觀鎖簡單高效
多業務類型去重獨立去重表統一管理
分散式系統插入分散式鎖 + 唯一索引雙重保險
API 重複提交客戶端 UUID + Redis 去重應用層攔截
工作流狀態流轉狀態機條件更新業務語義保護

總結

冪等設計是高併發系統穩定性基石。資料庫約束為底線,應用層邏輯為防線,分散式協調為補強。根據業務場景組合使用,避免單點失效。

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