精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一次 Redis 事務使用不當引發的生產事故

數據庫 Redis
現象:每天早上客服人員在后臺創建客服事件時,都會創建失敗。當我們重啟這個微服務后,后臺就可以正常創建了客服事件了。到第二天早上又會創建失敗,又得重啟這個微服務才行。

你好,我是悟空。

本文主要內容如下:

圖片

一、前言

最近項目的生產環境遇到一個奇怪的問題:

現象:每天早上客服人員在后臺創建客服事件時,都會創建失敗。當我們重啟這個微服務后,后臺就可以正常創建了客服事件了。到第二天早上又會創建失敗,又得重啟這個微服務才行。

初步排查:創建一個客服事件時,會用到 Redis 的遞增操作來生成一個唯一的分布式 ID 作為事件 id。代碼如下所示:

return redisTemplate.opsForValue().increment("count", 1);

而恰巧每天早上這個遞增操作都會返回 null,進而導致后面的一系列邏輯出錯,保存客服事件失敗。當重啟微服務后,這個遞增操作又正常了。

那么排查的方向就是 Redis 的操作為什么會返回 null 了,以及為什么重啟就又恢復正常了。

二、排查

根據上面的信息,我們先來看看 Redis 的自增操作在什么情況下會返回 null。

2.1 推測一

根據重啟后就恢復正常,我們推測晚上執行了大量的 job,大量 Redis 連接未釋放,當早上再來執行 Redis 操作時,執行失敗。重啟后,連接自動釋放了。

但是其他有使用到 Redis 的業務功能又是正常的,所以推測一的方向有問題,排除。

2.2 推測二

可能是 Redis 事務造成的問題。這個推測的依據是根據下面的代碼來排查的。

直接看 redisTemplate? 遞增的方法 increment,如下所示:

圖片

官方注釋已經說明什么情況下會返回 null:

  • 當在 pipeline(管道)中使用這個 increment 方法時會返回 null。
  • 當在 transaction(事務)中使用這個 increment 方法時會返回 null。

事務提供了一種將多個命令打包,然后一次性、有序地執行機制.

多個命令會被入列到事務隊列中,然后按先進先出(FIFO)的順序執行。

事務在執行過程中不會被中斷,當事務隊列中的所有命令都被執行完畢之后,事務才會結束。(內容來自 Redis 設計與實現)

繼續看代碼,發現在操作 Redis 的 ServiceImpl 實現類的上面添加了一個 @Transactional 注解,推測是不是這個注解影響了 Redis 的操作結果。

2.3 驗證推測二

如下面的表格所示,第二行中沒有添加 Spring 的事務注解 @Transactional?時,執行 Redis 的遞增命令肯定是正常的,而接下來要驗證的是表格中的第一行:加了 @Transactional 是否對 Redis 的命令有影響。

圖片

為了驗證上面的推論,我寫了一個 Demo 程序。

Controller 類,定義了一個 API,用來模擬前端發起的請求:

圖片

Service 實現類,定義了一個方法,用來遞增 Redis 中的 count 鍵,每次遞增 1,然后返回命令執行后的結果。而且這個 Service 方法加了@Transactional 注解。

圖片

Postman 測試下,發現每發一次請求,count 都會遞增 1,并沒有返回 null。

圖片

然后到 Redis 中查看數據,count 的值也是遞增后的值 38,也不是 null。

圖片

通過這個實驗說明在 @Transactional 注解的方法里面執行 Redis 的操作并不會返回 null,結論我記錄到了表格中。

圖片

所以說上面的推論不成立(加了 @Transactional 注解并不影響),到這里線索似乎斷了。

2.4 推測三

然后跟當時做這塊功能的開發人員說明了情況,告訴他可能是 Redis 事務造成的,然后問有沒有其他同學在凌晨執行過 Redis 事務相關的 Job。

他說最近有同事加過 Redis 的事務功能,在凌晨執行 Job 的時候用到事務。我將這位同事加的代碼簡化后如下所示:

圖片

下面是針對這段代碼的解釋,簡單來說就是開啟事務,將 Redis 命令順序放到一個隊列中,然后最后一起執行,且保證原子性。

setEnableTransactionSupport表示是否開啟事務支持,默認不開啟。

圖片

難道開啟了 Redis 事務,還能影響 Spring 事務中的 Redis 操作?

2.5 驗證推測三

如下表,序號 3 和 序號 4 的場景都是開啟了 Redis 的事務支持,兩個場景的區別是是否加了 @Transactional 注解。

圖片

為了驗證上面的場景,我們來做個實驗:

  • 先開啟 Redis 事務支持,然后執行 Redis 的事務命令 multi  和 exec 。
  • 驗證場景 3:在 @Transactional 注解的方法中執行 Redis 的遞增操作。
  • 驗證場景 4:在非 @Transactional 注解的方法中執行 Redis 的遞增操作

2.5.1 執行 Redis 事務

首先就用 Redis 的 multi 和 exec 命令來設置兩個 key 的值。

圖片

如下圖所示,設置成功了。

圖片

2.5.2 @Transactional 中執行 Redis 命令

接下來在標注有 @Transactional 注解的方法中執行 Redis 的遞增操作。

圖片

多次執行這個命令返回的結果都是 null,這不就正好重現了!

圖片

再來看 Redis 中 count 的值,發現每執行一次 API 請求調用,都會遞增 1,所以雖然命令返回的是 null,但最后 Redis 中存放的還是遞增后的結果。

圖片

圖片

接下來我們驗證下場景 4,先執行 Redis 事務操作,然后在不添加 @Transactional 注解的方法中執行 Redis 遞增操作。

圖片

用 Postman 調用這個接口后,正常返回自增后的結果,并不是返回 null。說明在非 @Transactional 中執行 Redis 操作并沒有受到 Redis 事務的影響。

圖片

四個場景的結論如下所示,只有第三個場景下,Redis 的遞增操作才會返回 null。

圖片

問題原因找到了,說明 RedisTemplete 開啟了 Redis 事務支持后,在 @Transactional 中執行的 Redis 命令也會被認為是在 Redis 事務中執行的,要執行的遞增命令會被放到隊列中,不會立即返回執行后的結果,返回的是一個 null,需要等待事務提交時,隊列中的命令才會順序執行,最后 Redis 數據庫的鍵值才會遞增。

三、源碼解析

那我們就看下為什么開啟了 Redis 事務支持,效果就不一樣了。

找到 Redis 執行命令的核心方法, execute 方法。

圖片

然后一步一步點進去看,關鍵代碼就是 211 行到 216 行,有一個邏輯判斷,當開啟了 Redis 事務支持后,就會去綁定一個連接(bindConnection?),否則就去獲取新的 Redis 連接(getConnection?)。這里我們是開啟了的,所以再到 bindConnection方法中查看如何綁定連接的。

圖片

接著往下看,關鍵代碼如下所示,當開啟了 Redis 事務支持,且添加了 @Transactional 注解時,就會執行 Redis 的 mutil 命令。

關鍵代碼:conn.multi();

圖片

Redis Multi 命令用于標記一個事務塊的開始,事務塊內的多條命令會按照先后順序被放進一個隊列當中,最后由 EXEC 命令原子性(atomic)地執行。

真相大白,開啟 Redis 事務支持 + @Transactional 注解后,最后其實是標記了一個 Redis 事務塊,后續的操作命令是在這個事務塊中執行的。

比如下面的的遞增命令并不會返回遞增后的結果,而是返回 null。

stringRedisTemplate.opsForValue().increment("count", 1);

而我們的生產環境重啟服務后,開啟的 Redis 事務支持又被重置為默認值了,所以后續的 Redis 遞增操作都能正常執行。

四、修復方案

目前想到了兩種解決方案:

方案一:每次 Redis 的事務操作完成后,關閉 Redis 事務支持,然后再執行 @Transactional 中的 Redis 命令。(有弊端)

方案二:創建兩個 StringRedisTemplate,一個專門用來執行 Redis 事務,一個用來執行普通的 Redis 命令。

4.1 方案一

方案一的寫法如下,先開啟事務支持,事務執行之后,再關閉事務支持。

圖片

但是這種寫法有個弊端,如果在執行 Redis 事務期間,在 @Transactional 注解的方法里面執行 Redis 命令,則還是會造成返回結果為 null。

圖片

4.2 方案二

弄兩個 RedisTemplate Bean,一個是用來執行 Redis 事務的,一個是用來執行普通 Redis 命令的(不支持事務)。不同的地方引入不同的 Bean 就可以了。

先創建一個 RedisConfig 文件,自動裝配兩個 Bean。一個 Bean 名為 stringRedisTemplate? 代表不支持事務的,執行命令后立即返回實際的執行結果。另外一個 Bean 名為 stringRedisTemplateTransaction,代表開啟 Redis 事務支持的。

代碼如下所示:

圖片

接下來在測試的 Service 類中注入兩個不同的 StringRedisTemplate 實例,代碼如下所示:

圖片

Redis 事務的操作改寫成這樣,且不需要手動開啟 Redis 事務支持了。用到的 StringRedisTemplate 是支持事務的那個實例。

圖片

在 Spring 的 @Tranactional 中執行的 Redis 命令如下所示,用到的 StringRedisTemplate 是不支持事務的那個實例。

圖片

然后還是按照上面場景 3 的測試步驟,先執行 testRedisMutil 方法,再執行 testTransactionAnnotations 方法。

驗證結果:Redis 遞增操作正常返回 count 的值,修復完成。

另外關于 Redis 事務使用還有一個坑,就是 Redis 連接未釋放,導致獲取不到連接了,這是下一個話題了~

參考資料:https://blog.csdn.net/qq_34021712/article/details/79606551

責任編輯:武曉燕 來源: 悟空聊架構
相關推薦

2024-06-28 10:01:04

2020-11-16 12:35:25

線程池Java代碼

2025-07-28 06:38:07

2025-07-16 07:20:00

開發代碼并發

2019-10-10 15:40:17

redisbug數據庫

2021-06-10 06:59:34

Redis應用API

2024-09-05 08:07:55

2021-05-20 10:02:50

系統Redis技巧

2021-09-11 19:00:54

Intro元素MemoryCache

2020-10-22 07:09:19

TCP網絡協議

2019-01-16 09:20:42

架構設計JVM FullGC宕機事故

2009-12-17 14:53:52

VS2008程序

2021-08-26 14:26:25

Java代碼集合

2024-02-04 08:26:38

線程池參數內存

2017-11-09 09:06:29

流量暴增優化

2021-07-11 09:34:45

ArrayListLinkedList

2022-11-16 08:00:00

雪花算法原理

2022-06-21 11:24:05

多線程運維

2020-12-09 08:59:59

MongoDB復合索事故

2021-11-01 17:29:02

Windows系統Fork
點贊
收藏

51CTO技術棧公眾號

欧美激情成人在线视频| 欧美午夜影院一区| 蜜桃视频日韩| 在线观看免费视频一区| 伊人久久大香线蕉精品组织观看| 日韩一区二区三区在线视频| 亚洲人成无码网站久久99热国产| 黄色av网址在线免费观看| 蜜桃91丨九色丨蝌蚪91桃色| 欧美高清不卡在线| 日韩不卡av在线| 91国内精品白嫩初高生| 欧美中文字幕久久| 日韩亚洲欧美视频| 麻豆影院在线观看| 91女厕偷拍女厕偷拍高清| 成人激情综合网| 在线视频一区二区三区四区| 伊人青青综合网| 中文字幕av日韩| 午夜剧场免费看| 99久热在线精品视频观看| 日韩欧美亚洲成人| 国产91视频一区| 日本高清中文字幕在线| 久久日韩精品一区二区五区| 鬼打鬼之黄金道士1992林正英| 中文字幕免费视频观看| 亚洲最黄网站| 欧美国产日韩一区| 天天鲁一鲁摸一摸爽一爽| 国产一区网站| 日韩电影免费在线观看中文字幕| xxx中文字幕| 国产经典一区| 色综合久久久久综合| 日本十八禁视频无遮挡| 永久免费网站在线| 亚洲欧洲av另类| 性高潮久久久久久久久| 欧美在线观看在线观看| 99久久亚洲一区二区三区青草| 动漫一区二区在线| 国产成人三级一区二区在线观看一 | 色综合中文字幕| 欧美不卡在线播放| 国产欧洲在线| 亚洲电影在线免费观看| av在线免费观看国产| 成人日韩欧美| 亚洲乱码精品一二三四区日韩在线| 午夜精品短视频| lutube成人福利在线观看| 久久精品一区二区三区av| 久久涩涩网站| 欧美zzoo| 国产人伦精品一区二区| 日韩av影视| 99re热久久这里只有精品34| 中文字幕不卡在线播放| 一区二区三区视频| 国产美女在线观看| 亚洲资源在线观看| 日韩欧美国产综合在线| 老色鬼在线视频| 好吊成人免视频| 日本美女高潮视频| 麻豆久久久久| 日韩欧美一区二区三区在线| 亚洲少妇一区二区| 天堂99x99es久久精品免费| 亚洲欧洲国产一区| 999精品在线视频| 欧美国产91| 91精品91久久久久久| 高清乱码免费看污| 蜜桃视频一区二区三区在线观看| 成人福利视频网| 国产www视频| 97精品国产97久久久久久久久久久久 | 人人妻人人澡人人爽欧美一区双| av电影院在线看| 色天天综合久久久久综合片| 亚洲第一狼人区| 66精品视频在线观看| 精品视频在线播放免| 俄罗斯毛片基地| 欧美日韩国产精品一区二区亚洲| 久久久久久亚洲精品中文字幕 | 欧美自拍偷拍一区| 亚洲综合123| 亚洲成aⅴ人片久久青草影院| 中文字幕不卡在线视频极品| 黄色一级视频免费观看| 性色一区二区三区| 亚洲一区二区三区久久| 日韩电影免费| 亚洲美女视频一区| 男女无套免费视频网站动漫| 日韩一区网站| 在线观看国产精品91| 精国产品一区二区三区a片| 国产精品一二| 99久久免费国| 川上优的av在线一区二区| 亚洲精品va在线观看| 欧美日韩一区二区在线免费观看| 国产亚洲精aa在线看| 亚洲欧美中文字幕| 久久久久亚洲av片无码下载蜜桃| 日本女人一区二区三区| 国内一区二区在线视频观看| 蜜桃视频在线观看免费视频网站www| 婷婷一区二区三区| 免费高清视频在线观看| 欧美日韩第一| 欧美性视频精品| 亚洲国产视频一区二区三区| 中文天堂在线一区| 黑森林福利视频导航| www国产精品| 久久久999精品视频| 无码人妻丰满熟妇区bbbbxxxx| 国产91在线看| 一级黄色片播放| 国模私拍国内精品国内av| 亚洲精品久久久久中文字幕欢迎你| av激情在线观看| 久久国产精品99精品国产| 欧美亚洲免费高清在线观看 | 国产在线精品成人一区二区三区| 四虎影视在线观看2413| 亚洲亚洲人成综合网络| www.51色.com| 91精品国产视频| 成人黄色免费在线观看| h视频在线免费| 色老汉一区二区三区| 欧美精品黑人猛交高潮| 国产亚洲精品bv在线观看| 国产精品久久九九| 日本高清在线观看视频| 日韩欧美高清一区| 青青草精品在线视频| 国产剧情一区二区三区| 九一免费在线观看| 中文字幕一区日韩精品| 欧美激情在线观看视频| 性做久久久久久久久久| 亚洲最新视频在线播放| 欧美成人精品一区二区综合免费| 欧美激情1区2区3区| 99在线影院| av3级在线| 日韩精品久久久久久福利| 国产污污视频在线观看| 2023国产一二三区日本精品2022| 国产欧美在线一区| 国产99精品一区| 国产乱肥老妇国产一区二| 日本在线免费| 欧美大片在线观看一区| 日韩和一区二区| 久久精品一二三| 中文字幕日韩有码| 欧美亚洲免费高清在线观看 | 国产欧美一区二区三区在线| 麻豆最新免费在线视频| 欧美一级欧美三级| 久久久久久久久久久久久久久久久 | 欧美性受xxxx黒人xyx性爽| 女同性一区二区三区人了人一| 亚洲free嫩bbb| а√在线中文网新版地址在线| 亚洲精品日韩久久久| 在线免费看av片| 一区二区三区四区av| 无套内谢大学处破女www小说| 老司机午夜精品视频| 一本一本久久a久久精品综合妖精| 24小时成人在线视频| 久久久久亚洲精品| 国产一级片在线| 日韩一区二区电影网| 毛片基地在线观看| 17c精品麻豆一区二区免费| 四虎精品一区二区| 日韩 欧美一区二区三区| 无码人妻精品一区二区三区99v| 嫩草国产精品入口| 国产日韩欧美影视| 免费一二一二在线视频| 日韩一区二区久久久| 午夜18视频在线观看| 69久久夜色精品国产69蝌蚪网| 国产一级理论片| 亚洲国产成人自拍| 2一3sex性hd| 看片的网站亚洲| 国产在线精品91| 天天综合亚洲| 欧美一区免费视频| 999国产精品一区| 国产美女久久久| 国产精品电影| 精品中文字幕视频| www亚洲人| 日韩av一区在线观看| 国产丝袜视频在线观看| 色呦呦国产精品| 日本五十路女优| 亚洲嫩草精品久久| 草草影院第一页| av网站一区二区三区| 91aaa精品| 麻豆精品久久久| 国产偷人视频免费| 国产精品vip| 免费久久久久久| 日本精品黄色| 欧美一区二区三区在线免费观看| 麻豆一区一区三区四区| 99久久精品久久久久久ai换脸| 亚洲二区av| 国产精品一二三视频| 美女福利一区二区三区| 91国产精品电影| 僵尸再翻生在线观看| 久久人人爽人人爽人人片av高请 | 国产精品国产三级国产专播精品人| 欧美v亚洲v| 久久91亚洲人成电影网站| 婷婷在线视频观看| 中文字幕免费国产精品| 国产日韩精品在线看| 亚洲视频在线免费观看| 涩爱av在线播放一区二区| 亚洲国产精品久久久久久| 亚洲av无码乱码在线观看性色| 欧美一级片在线看| 99久久久国产精品无码免费| 6080国产精品一区二区| 999久久久久久| 日韩一区二区三区高清免费看看| 91中文字幕在线播放| 欧美精品777| 国产a级免费视频| 精品国免费一区二区三区| 成人毛片视频免费看| 精品国产一区二区三区忘忧草| 成人h动漫精品一区二区无码 | sese一区| 日韩在线观看网站| 亚洲小说区图片区都市| 欧美肥婆姓交大片| 国产蜜臀在线| 4388成人网| 欧美日韩在线精品一区二区三区激情综合 | 欧美精品一区二区三区在线四季| 日韩欧美国产大片| 日本免费一区二区三区| av亚洲在线观看| 熟女视频一区二区三区| 国产综合网站| 日本福利视频在线| 免费看日韩精品| 午夜激情影院在线观看| 成人美女视频在线看| 一区二区三区少妇| 欧美极品aⅴ影院| 九九九在线视频| 欧美日韩精品在线| 中文字幕一区二区免费| 欧美浪妇xxxx高跟鞋交| 精品人妻一区二区三区蜜桃| 亚洲第一免费网站| 川上优的av在线一区二区| 欧美美最猛性xxxxxx| 伊人网在线播放| 成人网欧美在线视频| 乱亲女h秽乱长久久久| 色一情一乱一伦一区二区三区丨 | 777精品视频| 成人高清一区| 国产精品一区二区三区在线 | 免费欧美一级视频| 三级精品在线观看| 美女被爆操网站| 久久精品日韩一区二区三区| 91日韩中文字幕| 日本高清免费不卡视频| 亚洲av无码国产综合专区| 亚洲欧美三级伦理| 色呦呦在线看| 国产精品亚洲欧美导航| 玖玖玖免费嫩草在线影院一区| 日本精品二区| 激情久久久久久| 爱豆国产剧免费观看大全剧苏畅| 成人av网站免费观看| 99热在线观看精品| 日韩欧美成人网| 亚洲国产综合网| 深夜福利一区二区| 美女福利一区二区三区| 成人欧美一区二区三区黑人免费| 激情婷婷综合| 成人免费观看cn| 国产精品自在在线| 色婷婷国产精品免| 大桥未久av一区二区三区| 精品人妻无码一区二区色欲产成人 | 图片区偷拍区小说区| 欧美国产欧美综合| 综合激情网五月| 亚洲成人免费在线视频| 久久77777| 国产免费一区二区三区在线能观看| 欧美18免费视频| youjizz.com在线观看| 精品亚洲国内自在自线福利| 亚洲欧洲久久久| 动漫精品一区二区| 日本韩国在线观看| 欧美俄罗斯性视频| 日韩欧美中文字幕一区二区三区| 亚洲一区二区四区| 青青草精品视频| jizz中文字幕| 91黄色在线观看| 免费在线视频你懂得| 91高清视频免费| 欧美综合精品| ww国产内射精品后入国产| 成人一区二区三区中文字幕| 九九精品在线观看视频| 日韩欧美123| 免费电影网站在线视频观看福利| 1卡2卡3卡精品视频| 亚洲成人免费| 人妻精油按摩bd高清中文字幕| 亚洲男女毛片无遮挡| 国产麻豆免费观看| 久久综合伊人77777尤物| 国产精品毛片aⅴ一区二区三区| 黄瓜视频免费观看在线观看www| 激情综合色综合久久综合| 99热这里只有精品4| 欧美日本国产一区| 18av在线播放| 国产不卡一区二区在线观看| 激情久久婷婷| 国产又黄又粗又猛又爽的视频| 欧美日韩色婷婷| 国产精品视频二区三区| 国产精品视频久久久| 久久亚洲专区| 在线观看免费看片| 亚洲综合色网站| 国产精品国产高清国产| 欧美又大又粗又长| 精品国产a一区二区三区v免费| 亚洲激情在线观看视频| 国产精品美日韩| 国内精品国产成人国产三级| 欧美极品少妇xxxxx| 久久久久影视| 992kp快乐看片永久免费网址| 国产精品久久久久精k8| www.色播.com| 57pao成人永久免费视频| 精品成人影院| 天堂av手机在线| 黑人巨大精品欧美一区二区免费| 久久米奇亚洲| 亚洲aaa激情| 在线综合亚洲| 五月天免费网站| 日韩一区二区免费视频| 亚洲精品**中文毛片| 一区二区三区四区久久| 成人少妇影院yyyy| 啪啪小视频网站| 欧美日韩不卡合集视频| 亚洲精品国产动漫| 亚洲男人天堂2021| 欧美日韩一区免费| av网址在线播放| 久久伦理网站| 国产精品一区二区不卡| 天堂а√在线中文在线新版 | 青青草在线观看视频| 亚洲男人第一网站| 视频免费一区二区| 男女污污的视频| 亚洲6080在线| 美女隐私在线观看| 欧美综合77777色婷婷| 国产精品99久久久久| 成年人晚上看的视频|