天天看點

Rabbit MQ 幂等性(處理消息重複消費問題的思路)1、什麼是幂等性2、消費端的幂等性保障3、業界主流的幂等性操作

Rabbit MQ 幂等性(處理消息重複消費問題的思路)

  • 1、什麼是幂等性
  • 2、消費端的幂等性保障
  • 3、業界主流的幂等性操作
    • 3.1、唯一ID + 指紋碼 機制
    • 3.2、利用 Redis 原子特性實作

1、什麼是幂等性

借助資料庫的樂觀鎖機制舉例:

我們在執行一條更新庫存操作的SQL語句時,在高并發的情況下,如何避免庫存 count  = 0了,還在減少的情況發生?

解決方案:加上版本号。
每次更新庫存前,先根據主鍵查詢 版本号
select count from t_rep where 主鍵 = **;
假設此時的版本号version = 1, 然後再根據版本号+主鍵作為條件去更新
update t_reps set count = count - 1,version = version +1 where version = 1 and 主鍵 = **.

這樣當多個人查詢到相同的版本号時,隻有一個人能修改庫存。
           

總結什麼是幂等性:

       可能你要對一件事進行一個操作,這個操作你可能要執行一百次或一千次,那麼我們最終操作的結果,這一百次一千次的結果都是相同的。

2、消費端的幂等性保障

舉例:在海量訂單産生的業務高峰期,如何避免消息的重複消費問題?

       在高并發的情況下,可能會有很多消息到達MQ,然後我們的消費端要監聽大量的消息。這個時候難免會遇到消息的重複投遞,或者網絡不穩定的原因導緻閃斷,進而導緻 Broker 重發消息,這個時候不去做幂等,就會出現重複消費的問題。
  • 消費端實作幂等性,就意味着我們的消息永遠不會消費多次,即使我們收到了多條一樣的消息。

3、業界主流的幂等性操作

3.1、唯一ID + 指紋碼 機制

  • 唯一ID + 指紋碼 機制,利用資料庫主鍵去重
  • select count(1) from t_order where id = 唯一ID + 指紋碼
  • 好處:實作簡單
  • 壞處:高并發下有資料庫寫入的性能瓶頸。
  • 解決方案:跟進ID進行分庫分表進行算法路由
       這裡的指紋碼可能是我們的一些業務規則,時間戳加上銀行傳回的唯一碼,這個指紋碼并不一定是我們系統生成的,而是一些外部的規則或者是我們内部的業務規則去拼接起來的。

指紋碼的目的就是為了保障這次操作是絕對唯一的。

具體的實作過程中,我們要保證 唯一ID + 指紋碼在資料庫中是唯一的 。在進行具體操作時,我們先通過 唯一ID + 指紋碼 去資料庫查詢,如果沒有資料我們就insert插入,如果有資料則證明已經被操作了,我們就不做任何操作。

3.2、利用 Redis 原子特性實作

  • 使用 Redis 進行幂等,需要考慮的問題。
  • 第一:我們是否要進行資料落庫,如果落庫的話,關鍵解決的問題是資料庫和緩存如何做到原子性?
  • 第二: 如果不進行落庫,那麼都存儲到緩存中,如何設定定時同步的政策?

.