開卷故意,好久沒寫博客了,近期工作也挺忙的。
死鎖距離我不遙遠。最終還是在高並發時被我碰到了。
DeadLock Found!
雖然編程風格中會盡量避免死鎖,可是還是被我碰上了。文章可能看不出來我在做什么事情。僅僅是記錄自己的一個排除死鎖的過程。
事情起源於兩個聯動的緩存+redis+異步數據庫讀寫操作。
事務中的這句出現死鎖:
DELETE FROM table WHERE FROM key = ‘helloworld’
當初的思考解除死鎖的思路例如以下:
1)分析死鎖模型,如果1,2 兩個線程,如果A,B兩個鎖,通俗的說 :
1持有A鎖。等待B鎖 -- 2 持有B鎖。等待A鎖
於是掐這了,就癱了。
2)繼續思考,要真這么簡單,也不好意思稱自己project師了,實際開發中都是碰到死鎖環。
什么意思呢?繼續如果
1持有A。等B,
2持有B,等C,
3持有C。等A
Anyway,讀者能夠自己如果還有4。5,6。7...
3)繼續思考,死鎖出現,第一步肯定是重審自己的代碼。這個時候一定要對使用的成熟的工具優先保持自信但要保留質疑的態度。怎么重審,記錄我的過程
a,我們說代碼越簡潔,越不easy出錯。所以,秉着DRY原則。也要消除反復的代碼,能復用就絕對不看着行數而自得。
b。重構過后。一定是要數據層,邏輯層分離。不要在數據層包括邏輯處理。不要在邏輯層去做數據層做的事情。(這個時候會發現,腦中有設計模式思想和沒有這個 概念的人是有非常大差別的)
c。回歸正題,我代碼中的死鎖出現是高並發環境,存在熱點區。在重構過代碼后,肯定要對熱點數據進行預處理,才進行異步寫入數據庫。
什么是熱點區?我自己亂 叫的一個名字,就是非常多時候。日志也好,外來數據也好,非常多時候會出現300ms以內出現100條99%相似度的數據。
d,繼續測試。發現死鎖依然,馬上建立新的緩存,推斷究竟哪里出了問題。發現,邏輯並沒有問題。
e,持着質疑工具的態度,檢索使用的工具,高並發發生在異步讀寫數據庫,那么既然邏輯沒有問題,讀寫中操作的數據就不會有問題。那就是數據庫這里的鎖機制出 了問題。
閱讀數據庫鎖機制文檔,發現了事務操作中的頁面鎖和記錄鎖出了問題。
f,問題來了。既然是多線程。高並發,就不可能不讓事務持有記錄鎖和頁面鎖。此時怎么辦?
解決的方法。放棄根據索引刪除,更新。改用主鍵進行刪除更新操作。
g,測試。正常。
整個過程。看了非常多文檔,當中,最實用的:
同一時候也會翻譯一篇看到的高並發的國外文章。