網站首頁 編程語言 正文
如何在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,為了支持冪等,支持重復執行,簡單的處理方法 是,先查詢下一些關鍵數據,判斷是否已經執行過,在進行業務處理,就可以了。注意:核心高并發流程不要用這 種方法;
原文鏈接:https://blog.csdn.net/weixin_44427181/article/details/128898438
相關推薦
- 2022-02-03 checkbox修改默認樣式
- 2022-06-01 C語言?詳解如何刪除有序數組中的重復項_C 語言
- 2023-01-26 Redis的數據復制過程詳解_Redis
- 2022-10-27 Python?標準庫?fileinput與文件迭代器_python
- 2022-11-05 ios開發?try-catch引起的野指針問題排查_IOS
- 2023-03-20 python如何在pygame中設置字體并顯示中文詳解_python
- 2023-02-25 從迷你todo?命令行入門Rust示例詳解_Rust語言
- 2022-06-18 C語言中main函數與命令行參數詳細講解_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支