開卷故意,好久沒寫部落格了,近期工作也挺忙的。
死鎖距離我不遙遠。最終還是在高併發時被我碰到了。
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,測試。正常。
整個過程。看了非常多文件,當中,最實用的:
p=844
文章寫完。認為自己寫的挺扯的。好久沒寫文章了。出來冒個泡泡,表示自己還在。
興許腦袋清醒的時候要做乙個高併發的專題,也算對自己這一段工作的總結。
同一時候也會翻譯一篇看到的高併發的國外文章。
this is my word.
記錄一次碰到的併發安全問題
還未進行生產測試,若存在問題請指出。兩個執行緒a,b。共享乙個arraylist。執行緒a接收資料,add到arraylist,根據列表中的記錄條數決定是否傳送到中間儲存件。執行緒b定時執行傳送。arraylistbuffer private final static int count 100 a...
記錄一次排查極光推送SDK死鎖問題
線上服務穩定了好幾個月,這兩天抽風,總是有mysql資料行被鎖,update會報錯 lock wait timeout exceeded try restarting transaction 導致系統無法使用,害得我得一直在後台給使用者解鎖 通過mysql的kill命令 o 極光sdk版本 接入sd...
高併發下怎樣生成唯一的訂單號?
如果沒有併發,訂單號只在乙個執行緒內產生,那麼由於程式是順序執行的,不同訂單的生成時間一定不同,因此用時間就可以區分各個訂單。如果存在併發,且訂單號是由乙個程序中的多個執行緒產生的,那麼只要把執行緒id新增到序列號中就可以保證訂單號唯一。如果存在併發,且訂單號是由同一臺主機中的多個程序產生的,那麼只...