首頁 > 軟體

在redis中防止訊息丟失的機制

2023-02-08 22:02:46

如何在redis中防止訊息丟失

前言

在專案中,由於網路問題,我們很難保證生產者傳送的訊息能100%到達訊息佇列伺服器,也就是說有訊息丟失的可能性,因 此,生產者就必須具有訊息丟失檢測和重發機制,也就是我們常說的訊息佇列的事物機制。

不能把可靠性的保證全部交給TCP,TCP只保證了傳輸層的可靠傳輸,但是無法保證與應用層的互動是否出錯 TCP無法給應用層任何反饋,因此必須在應用層處理差錯

同步的事務——停止等待

所謂停止等待協定就是沒傳送完一組資料後,等待對方確認並且收到確認後,再傳送下一組資料。

同步的事務——連續ARQ

類似於TCP的滑動視窗模型

非同步的事務——回撥機制

生產者在傳送訊息的時候,註冊一個回撥函數,這樣生產者便不用停下來等待確認了,而是可以一直持續傳送訊息,當訊息到達訊息佇列伺服器的時候,伺服器便會呼叫生產者註冊的回撥函數,告知生產者訊息傳送成功了還是失敗了,進而做進一步的處理,從而提高了並行量。

訊息的冪等處理

由於網路原因,生產者可能會重複傳送訊息,因此消費者方必須做訊息的冪等處理,常用的解決方案有:

  • 查詢操作:查詢一次和查詢多次,在資料不變的情況下,查詢結果是一樣的。select是天然的冪等操作;
  • 刪除操作:刪除操作也是冪等的,刪除一次和多次刪除都是把資料刪除。(注意可能返回結果不一樣,刪除的資料不存在,返回0,刪除的資料多條,返回結果多個) ;
  • 唯一索引,防止新增髒資料。比如:支付寶的資金賬戶,支付寶也有使用者賬戶,每個使用者只能有一個資金賬戶,怎麼防止給使用者建立資金賬戶多個,那麼給資金賬戶表中的使用者ID加唯一索引,所以一個使用者新增成功 一個資金賬戶記錄。要點:唯一索引或唯一組合索引來防止新增資料存在髒資料(當表存在唯一索引,並行 時新增報錯時,再查詢一次就可以了,資料應該已經存在了,返回結果即可);
  • token機制,防止頁面重複提交。業務要求: 頁面的資料只能被點選提交一次;發生原因: 由於重複點選或 者網路重發,或者nginx重發等情況會導致資料被重複提交;解決辦法: 叢集環境採用token加redis(redis單 執行緒的,處理需要排隊);單JVM環境:採用token加redis或token加jvm記憶體。處理流程:1. 資料提交前要向 服務的申請token,token放到redis或jvm記憶體,token有效時間;2. 提交後後臺校驗token,同時刪除 token,生成新的token返回。token特點:要申請,一次有效性,可以限流。注意:redis要用刪除操作來判 斷token,刪除成功代表token校驗通過,如果用select+delete來校驗token,存在並行問題,不建議使用;
  • 悲觀鎖——獲取資料的時候加鎖獲取。select * from table_xxx where id=‘xxx’ for update; 注意:id欄位一 定是主鍵或者唯一索引,不然是鎖表,會死人的悲觀鎖使用時一般伴隨事務一起使用,資料鎖定時間可能會 很長,根據實際情況選用;
  • 樂觀鎖——樂觀鎖只是在更新資料那一刻鎖表,其他時間不鎖表,所以相對於悲觀鎖,效率更高。樂觀鎖的 實現方式多種多樣可以通過version或者其他狀態條件:1. 通過版本號實現update table_xxx set name=#name#,version=version+1 where version=#version#如下圖(來自網上);2. 通過條件限制 update table_xxx set avai_amount=avai_amount-#subAmount# where avai_amount-#subAmount# >= 0要求: quality-#subQuality# >= ,這個情景適合不用版本號,只更新是做資料安全校驗,適合庫存模型,扣份額和 回滾份額,效能更高;
  • 分散式鎖——還是拿插入資料的例子,如果是分佈是系統,構建全域性唯一索引比較困難,例如唯一性的欄位沒法 確定,這時候可以引入分散式鎖,通過第三方的系統(redis或zookeeper),在業務系統插入資料或者更新資料,獲 取分散式鎖,然後做操作,之後釋放鎖,這樣其實是把多執行緒並行的鎖的思路,引入多多個系統,也就是分散式系 統中得解決思路。要點:某個長流程處理過程要求不能並行執行,可以在流程執行之前根據某個標誌(使用者ID+字尾 等)獲取分散式鎖,其他流程執行時獲取鎖就會失敗,也就是同一時間該流程只能有一個能執行成功,執行完成 後,釋放分散式鎖(分散式鎖要第三方系統提供);
  • select + insert——並行不高的後臺系統,或者一些任務JOB,為了支援冪等,支援重複執行,簡單的處理方法 是,先查詢下一些關鍵資料,判斷是否已經執行過,在進行業務處理,就可以了。注意:核心高並行流程不要用這 種方法;

到此這篇關於如何在redis中防止訊息丟失的文章就介紹到這了,更多相關redis防止訊息丟失內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com