冪等性:構建穩健分布式系統的關鍵
為什么冪等性是關鍵?
在現代分布式系統中,可用性是關鍵因素,這意味著你需要構建重試機制和處理失敗及恢復的方法。這也意味著你可能會在系統中重復處理相同的操作,但如果你的應用程序不了解這一點,并將其視為一個全新的請求,它將產生不可預期的結果。如果是處理支付或管理電子商務訂單的應用程序,這會導致巨大的財務損失和不可挽回的損害。
那么,我們該怎么做才能保證多次執行操作的結果與僅執行一次的結果相同呢?
讓系統具備冪等性!!!
什么是冪等性?
冪等性是指一個系統或過程在多次執行相同操作時能夠產生相同結果的能力。冪等性保證了多次執行相同操作不會引入意外的副作用,從而防止了意外的重復處理或不期望的更改。例如,在重復檢查中,冪等系統確保重復請求不會導致重復處理,因此如果向系統發出重復請求,冪等系統要么忽略它,要么返回首次處理的狀態。
等一下,我有點困惑!!!重復檢查和冪等操作是一樣的嗎?
重復檢查 vs 冪等性
重復檢查旨在防止不必要的狀態更改,確保我們不會多次處理同一事件,而冪等性則允許我們再次處理相同的事件,但結果將是相同的。簡單來說,通過冪等性,我們可以在至少一次的消息傳遞系統中處理重復事件,確保多次處理相同事件仍然產生相同的效果。換句話說,冪等性是處理重復事件的最佳方式。
這聽起來不錯。但我們該如何實現它,可能會遇到什么挑戰呢?
冪等性實現策略
為了構建冪等性,最重要的任務是為每個請求找到或創建一個冪等鍵。我制定了一個簡單的算法策略,并添加了一些標準鍵來構建穩健的冪等性。
策略:
- 為每個請求找到一個唯一的關聯標識符,我們可以依賴它并存儲在數據存儲中,以便檢查每個傳入請求。
- 如果沒有唯一標識符,可以通過對有效負載進行哈希處理來創建校驗和,并將其用于冪等性。
- 如果有效負載包含UUID或時間戳(如創建時間戳),可能在每次重試時會改變,盡可能忽略這些字段并創建校驗和。如果無法忽略,請確保使用硬編碼值。
- 對于POST API,在請求頭中添加x-idempotency-key,并要求消費者提供一個唯一標識符和一個可選的過期時間。
- 在服務網格中,服務協作執行任務時,使用狀態變化模型和重復檢查來確保系統的冪等性。
- 定義冪等鍵的有效期,例如你的數據存儲將存儲該鍵的時間長度。
- 可以使用如下示例中展示的通用模型來創建復合冪等鍵:
public class IdempotentKey {
private String key; // 鍵
private long ttl; // 生存時間
private String result; // 響應
}
冪等鍵
可用于構建冪等鍵的標準鍵:
- UUID v4: 使用標準的java.util.UUID創建唯一標識符。
- 有效負載哈希: 創建請求有效負載的哈希(摘要)作為冪等鍵,保證相同有效負載的請求生成相同的鍵。?鍵元素: 在冪等鍵中包含用戶ID、交易詳情和時間戳等唯一參數,創建精確識別的復合鍵。
- 令牌: 發放并要求客戶端在請求中包含令牌,作為冪等鍵和安全措施。
- 時間戳: 使用時間戳或組合時間戳作為時間基冪等鍵,確保操作在定義的時間窗口內是冪等的。
冪等模型
冪等性如何實現,以及如何處理不同場景?下面是我開發的冪等性的shell級實現。
- 客戶端將有效負載“p12345”發送到接收服務進行處理。客戶端可以選擇在請求頭中發送x-idempotency-key,作為處理的冪等鍵。如果客戶端未發送冪等鍵頭,則我們可以通過對有效負載進行哈希處理創建一個,并將鍵存儲在Mapper中。(如果訂單ID尚未生成,系統將為每個新請求生成一個)。
- 接收服務將執行重復檢查,查看訂單是否已存在系統中;如果是,它將返回訂單的當前狀態;如果不是,它將持久化訂單及其當前狀態—RCVD。
- 接下來,接收服務可以進行必要的驗證并進行支付。如果成功,則加載訂單的當前狀態(因為它可能已經是PAID狀態),如果狀態是RCVD,則處理支付并更新狀態為—PAID。如果接收服務由于網絡故障或其他原因重試支付現有訂單,我們的狀態模型將救場,重試將被拒絕,因為訂單已經是PAID狀態。
- 成功支付后,接收服務將訂單發送進行履行。如果訂單狀態是PAID,訂單將被履行并達到最終狀態—FULFILLED。如果此處發生重試,狀態模型將救場。
- 注意,如果接收服務或支付服務有多個實例(pods)運行,確保在更新狀態時擁有集群鎖。
- 另一個要點是,為了加快冪等性的處理,可以使用緩存層存儲映射信息,但在我的案例中,主數據存儲足以處理高負載(避免過早優化)。
這是冪等性的一個演示用例。對于生產環境,你需要考慮你的用例,以及如何將該模型應用于實際場景。
結論
冪等性對于構建大規模、數據完整性不受影響的彈性分布式系統至關重要。冪等性的重試策略是分布式事務的一個優秀替代方案,后者更復雜且隨著擴展更難以管理。