一、什麼是冪等性
可以參考資料庫樂觀鎖機制,比如執行一條更新庫存的 SQL 語句,在併發場景,為了效能和資料可靠性,會在更新時加上查詢時的版本,並且更新這個版本資訊。可能你要對一個事情進行操作,這個操作可能會執行成百上千次,但是操作結果都是相同的,這就是冪等性。
二、消費端的冪等性保障
在海量訂單生成的業務高峰期,生產端有可能就會重複發生了訊息,這時候消費端就要實現冪等性,這就意味著我們的訊息永遠不會被消費多次,即使我們收到了一樣的訊息。
業界主流的冪等性有兩種操作:
1.唯一 ID + 指紋碼 機制,利用資料庫主鍵去重
2.利用redis的原子性去實現
複製程式碼
三、唯一 ID + 指紋碼 機制
大家肯定懂唯一 ID 的,就不多說了,為什麼需要指紋碼呢?這是為了應對使用者在一瞬間的頻繁操作,這個指紋碼可能是我們的一些規則或者時間戳加別的服務給到的唯一資訊碼,它並不一定是我們系統生成的,基本都是由我們的業務規則拼接而來,但是一定要保證唯一性,然後就利用查詢語句進行判斷這個id是否存在資料庫中。
好處就是實現簡單,就一個拼接,然後查詢判斷是否重複。
壞處就是在高併發時,如果是單個資料庫就會有寫入效能瓶頸
解決方案 :根據 ID 進行分庫分表,對 id 進行演算法路由,落到一個具體的資料庫,然後當這個 id 第二次來又會落到這個資料庫,這時候就像我單庫時的查重一樣了。利用演算法路由把單庫的冪等變成多庫的冪等,分攤資料流量壓力,提高效能。
四、利用 redis 的原子性去實現
相信大家都知道 redis 的原子性操作,我這裡就不需要過多介紹了。
使用 redis 的原子性去實現需要考慮兩個點
一是 是否 要進行資料落庫,如果落庫的話,關鍵解決的問題是資料庫和快取如何做到原子性? 資料庫與快取進行同步肯定要進行寫操作,到底先寫 redis 還是先寫資料庫,這是個問題,涉及到快取更新與淘汰的問題
二是如果不落庫,那麼都儲存到快取中,如何設定定時同步的策略? 不入庫的話,可以使用雙重快取等策略,保障一個訊息副本,具體同步可以使用類似 databus 這種同步工具。