死鎖檢測(cè)與解除:從原理到工程實(shí)踐的系統(tǒng)性解決方案
1. 項(xiàng)目概述從“卡死”到“疏通”的系統(tǒng)工程在后臺(tái)系統(tǒng)開發(fā)或者數(shù)據(jù)庫運(yùn)維的日常里最讓人頭疼的瞬間之一莫過于系統(tǒng)突然“卡住”不動(dòng)了。前端的請(qǐng)求轉(zhuǎn)著圈圈后端的日志停滯不前CPU和內(nèi)存占用看起來卻不高。這時(shí)候有經(jīng)驗(yàn)的工程師腦子里第一個(gè)蹦出來的詞很可能就是“死鎖”。這玩意兒不像內(nèi)存泄漏那樣緩慢侵蝕也不像CPU跑滿那樣聲勢(shì)浩大它更像是一場(chǎng)悄無聲息的交通癱瘓幾個(gè)關(guān)鍵線程或事務(wù)互相握住了對(duì)方需要的“鑰匙”卻又在等待對(duì)方先松手結(jié)果就是大家集體“擺爛”誰也動(dòng)不了。今天要聊的“死鎖的處理策略——檢測(cè)和解除”就是一套應(yīng)對(duì)這種系統(tǒng)性癱瘓的“應(yīng)急救援方案”。它不追求百分百的預(yù)防那屬于“避免”和“預(yù)防”策略的范疇而是承認(rèn)死鎖可能發(fā)生并建立一套機(jī)制來及時(shí)發(fā)現(xiàn)它然后安全地“拆除”它讓系統(tǒng)恢復(fù)暢通。無論是Java多線程程序里的鎖順序問題還是MySQL數(shù)據(jù)庫中并發(fā)的UPDATE語句甚至是操作系統(tǒng)內(nèi)核的資源爭(zhēng)奪死鎖檢測(cè)與解除都是保障系統(tǒng)最終可用性的關(guān)鍵安全網(wǎng)。這篇文章我們就深入這套“事后諸葛亮”但至關(guān)重要的策略拆解其核心原理、主流實(shí)現(xiàn)方案以及你在實(shí)操中一定會(huì)遇到的坑。2. 死鎖檢測(cè)的核心原理與算法實(shí)現(xiàn)死鎖檢測(cè)的本質(zhì)是在系統(tǒng)運(yùn)行的某一時(shí)刻拍一張“快照”然后分析這張快照里是否存在循環(huán)等待的條件。這個(gè)條件就是著名的“死鎖四個(gè)必要條件”互斥、持有并等待、不可剝奪、循環(huán)等待。檢測(cè)算法主要就是針對(duì)“循環(huán)等待”這個(gè)條件進(jìn)行建模和探查。2.1 資源分配圖與等待圖模型最直觀的模型是資源分配圖。在這個(gè)有向圖中有兩種節(jié)點(diǎn)進(jìn)程或線程節(jié)點(diǎn)和資源節(jié)點(diǎn)。從進(jìn)程指向資源的邊表示進(jìn)程請(qǐng)求該資源但尚未獲得從資源指向進(jìn)程的邊表示該資源已分配給該進(jìn)程。當(dāng)圖中出現(xiàn)一個(gè)閉合的環(huán)路時(shí)死鎖就發(fā)生了。然而在實(shí)際的系統(tǒng)實(shí)現(xiàn)中特別是數(shù)據(jù)庫管理系統(tǒng)這種資源類型繁多的場(chǎng)景維護(hù)完整的資源分配圖開銷較大。因此更常用的是一種簡(jiǎn)化模型等待圖。等待圖只關(guān)注進(jìn)程或事務(wù)節(jié)點(diǎn)。如果進(jìn)程A正在等待一個(gè)被進(jìn)程B占用的資源那么就畫一條從A指向B的邊。這樣問題就簡(jiǎn)化為在等待圖中是否存在環(huán)一旦檢測(cè)到環(huán)就意味著環(huán)上的所有進(jìn)程都陷入了死鎖。注意等待圖模型隱含了一個(gè)假設(shè)即一個(gè)資源同一時(shí)間只能被一個(gè)進(jìn)程占用互斥。這對(duì)于鎖這類資源是成立的但對(duì)于一些可共享的資源如信號(hào)量初始值大于1則需要更復(fù)雜的模型或轉(zhuǎn)換。2.2 基于深度優(yōu)先搜索的環(huán)檢測(cè)算法對(duì)于等待圖的環(huán)檢測(cè)最直接的算法是深度優(yōu)先搜索。系統(tǒng)需要維護(hù)一個(gè)全局的等待關(guān)系表。檢測(cè)器會(huì)定期比如每隔幾秒或根據(jù)特定條件如某個(gè)事務(wù)等待超時(shí)被觸發(fā)執(zhí)行以下步驟構(gòu)建等待圖遍歷當(dāng)前的鎖信息或等待隊(duì)列構(gòu)建出以事務(wù)為節(jié)點(diǎn)的有向圖。初始化為所有節(jié)點(diǎn)標(biāo)記“未訪問”。深度遍歷從任意一個(gè)“未訪問”的節(jié)點(diǎn)開始DFS。在DFS過程中需要維護(hù)一個(gè)“當(dāng)前路徑”的?;蛘咄ㄟ^顏色標(biāo)記法白色-未訪問灰色-訪問中黑色-已訪問完成。發(fā)現(xiàn)環(huán)在遍歷節(jié)點(diǎn)N時(shí)如果發(fā)現(xiàn)它的某個(gè)后繼節(jié)點(diǎn)M的狀態(tài)是“灰色”即正在當(dāng)前DFS路徑上那么就找到了一個(gè)從M到...到N再到M的環(huán)。環(huán)上的所有節(jié)點(diǎn)事務(wù)即為死鎖參與者。選擇犧牲者一旦檢測(cè)到環(huán)就需要選擇一個(gè)或多個(gè)“犧牲者”進(jìn)行回滾以打破死鎖。選擇策略我們會(huì)在解除策略部分詳細(xì)討論。一個(gè)簡(jiǎn)單的DFS檢測(cè)偽代碼示例顏色標(biāo)記法def detect_deadlock(wait_for_graph): # 顏色狀態(tài)0白色(未訪問), 1灰色(訪問中), 2黑色(已結(jié)束) color {node: 0 for node in wait_for_graph} deadlock_victims [] def dfs(node, path): if color[node] 1: # 找到環(huán) # 從當(dāng)前路徑path中找到環(huán)的起始位置 cycle_start_index path.index(node) cycle path[cycle_start_index:] deadlock_victims.extend(cycle) return True if color[node] 2: return False color[node] 1 path.append(node) for neighbor in wait_for_graph.get(node, []): if dfs(neighbor, path): # 如果已經(jīng)找到環(huán)可以提前結(jié)束本輪DFS但可能還有其他獨(dú)立環(huán) pass path.pop() color[node] 2 return False for node in wait_for_graph: if color[node] 0: dfs(node, []) return list(set(deadlock_victims)) # 去重2.3 數(shù)據(jù)庫中的死鎖檢測(cè)以InnoDB為例以MySQL的InnoDB存儲(chǔ)引擎為例它的死鎖檢測(cè)機(jī)制非常經(jīng)典。InnoDB使用一個(gè)等待圖來追蹤事務(wù)間的鎖等待關(guān)系。檢測(cè)算法做了高度優(yōu)化主動(dòng)檢測(cè)當(dāng)一個(gè)事務(wù)嘗試獲取鎖需要等待時(shí)InnoDB會(huì)立即觸發(fā)一次死鎖檢測(cè)而不是等待定時(shí)器。這能更快地發(fā)現(xiàn)死鎖。深度限制為了防止檢測(cè)算法本身消耗過多資源特別是在高并發(fā)下等待圖可能非常復(fù)雜InnoDB設(shè)置了檢測(cè)深度限制。如果搜索的深度超過了限制例如200步就認(rèn)為死鎖檢測(cè)成本過高會(huì)視為發(fā)生了死鎖并選擇回滾當(dāng)前請(qǐng)求鎖的事務(wù)。代價(jià)評(píng)估InnoDB在選擇犧牲者時(shí)會(huì)評(píng)估回滾哪個(gè)事務(wù)的“代價(jià)”更小。通常修改了更少數(shù)據(jù)行的事務(wù)會(huì)被優(yōu)先選為犧牲者。實(shí)操心得在數(shù)據(jù)庫運(yùn)維中SHOW ENGINE INNODB STATUS命令的輸出里的LATEST DETECTED DEADLOCK部分是分析死鎖現(xiàn)場(chǎng)的第一手資料。它會(huì)清晰地畫出等待關(guān)系并告訴你最終哪個(gè)事務(wù)被回滾了。定期檢查這個(gè)信息是定位和優(yōu)化應(yīng)用中潛在死鎖問題的關(guān)鍵。3. 死鎖解除的策略與抉擇檢測(cè)到死鎖只是第一步如何安全地解除它讓系統(tǒng)恢復(fù)同時(shí)盡量減少損失才是策略的核心。解除死鎖的本質(zhì)就是打破四個(gè)必要條件中的至少一個(gè)。在檢測(cè)并定位到死鎖環(huán)之后我們通常通過“剝奪資源”來打破“不可剝奪”或“持有并等待”條件具體操作就是回滾一個(gè)或多個(gè)事務(wù)。3.1 選擇犧牲者的權(quán)衡藝術(shù)選擇回滾哪個(gè)事務(wù)犧牲者是一個(gè)需要權(quán)衡的決策。常見的策略包括最小代價(jià)優(yōu)先這是最常用的策略。評(píng)估回滾各個(gè)死鎖事務(wù)所需的“代價(jià)”選擇代價(jià)最小的那個(gè)。代價(jià)的衡量標(biāo)準(zhǔn)可以是已執(zhí)行的計(jì)算時(shí)間回滾一個(gè)已經(jīng)運(yùn)行了10分鐘的事務(wù)比回滾一個(gè)剛運(yùn)行1秒的事務(wù)損失更大。已修改的數(shù)據(jù)量回滾一個(gè)修改了10000行的事務(wù)比回滾一個(gè)只修改了1行的事務(wù)更“重”。InnoDB主要采用此標(biāo)準(zhǔn)。事務(wù)的“年齡”通常更年輕的事務(wù)作為犧牲者影響更小。涉及的數(shù)據(jù)重要性較難量化某些關(guān)鍵數(shù)據(jù)的事務(wù)優(yōu)先級(jí)可能更高。最近啟動(dòng)的事務(wù)優(yōu)先基于“年輕事務(wù)持有鎖較少回滾代價(jià)低”的假設(shè)。涉及資源最少的事務(wù)優(yōu)先打破最小的環(huán)影響面最小。優(yōu)先級(jí)策略為事務(wù)設(shè)置人工優(yōu)先級(jí)總是回滾低優(yōu)先級(jí)的事務(wù)。這需要應(yīng)用層配合。實(shí)現(xiàn)上系統(tǒng)會(huì)維護(hù)事務(wù)的元數(shù)據(jù)開始時(shí)間、已修改頁面的列表等。當(dāng)需要選擇時(shí)遍歷死鎖環(huán)中的所有事務(wù)根據(jù)上述策略計(jì)算一個(gè)“代價(jià)分”選出分?jǐn)?shù)最低的作為犧牲者。3.2 回滾操作全部回滾與部分回滾選定犧牲者后就需要執(zhí)行回滾。全部回滾這是最簡(jiǎn)單粗暴的方式直接終止?fàn)奚呤聞?wù)并回滾其開始以來的所有操作。這對(duì)于短事務(wù)或讀寫事務(wù)是合適的。數(shù)據(jù)庫通過Undo Log可以高效地完成此操作。部分回滾也稱為“回退到安全點(diǎn)”。在某些復(fù)雜的場(chǎng)景或應(yīng)用邏輯中我們可能希望只回滾到死鎖發(fā)生前的某個(gè)點(diǎn)而不是事務(wù)起點(diǎn)。這需要事務(wù)系統(tǒng)支持保存點(diǎn)的機(jī)制。犧牲者回滾到最后一個(gè)保存點(diǎn)釋放其持有的部分鎖從而打破死鎖然后事務(wù)有可能被重新啟動(dòng)。這種方式對(duì)應(yīng)用更友好但實(shí)現(xiàn)復(fù)雜。重要提示無論采用哪種回滾都必須確保原子性和持久性。回滾操作本身必須是一個(gè)原子操作并且回滾后的狀態(tài)必須被持久化。同時(shí)系統(tǒng)需要向客戶端返回明確的錯(cuò)誤信息如MySQL的ERROR 1213 (40001): Deadlock found when trying to get lock以便應(yīng)用程序能夠進(jìn)行重試或其他處理。3.3 解除策略的副作用與應(yīng)對(duì)死鎖解除并非沒有代價(jià)性能損耗頻繁的死鎖檢測(cè)和回滾會(huì)消耗CPU和IO資源。如果系統(tǒng)死鎖過于頻繁檢測(cè)和解除的開銷本身就會(huì)成為性能瓶頸。業(yè)務(wù)邏輯中斷被回滾的事務(wù)意味著業(yè)務(wù)操作失敗前端用戶可能會(huì)看到操作失敗提示需要重試。這影響用戶體驗(yàn)?;铈i風(fēng)險(xiǎn)在極端情況下可能發(fā)生“活鎖”。即兩個(gè)或多個(gè)事務(wù)不斷被選為犧牲者并回滾然后又立即重試再次陷入死鎖如此循環(huán)導(dǎo)致事務(wù)永遠(yuǎn)無法完成。這通常需要引入隨機(jī)延遲重試機(jī)制來避免。我的踩坑記錄在一次高并發(fā)的庫存扣減場(chǎng)景中我們?cè)龅介g歇性的死鎖。采用默認(rèn)的最小修改行數(shù)策略回滾后發(fā)現(xiàn)總是后來啟動(dòng)的、只扣減1件庫存的“小事務(wù)”被回滾。這導(dǎo)致這些用戶的購買請(qǐng)求失敗率異常高。后來我們調(diào)整了策略結(jié)合事務(wù)年齡和修改行數(shù)并在應(yīng)用層為重試邏輯增加了指數(shù)退避算法才平穩(wěn)度過了促銷高峰。這說明默認(rèn)策略不一定最優(yōu)需要結(jié)合業(yè)務(wù)特點(diǎn)進(jìn)行考量。4. 檢測(cè)與解除的工程化實(shí)踐理論上的算法和策略最終要落地到具體的系統(tǒng)中。不同的系統(tǒng)操作系統(tǒng)、數(shù)據(jù)庫、分布式中間件有其獨(dú)特的實(shí)現(xiàn)方式和優(yōu)化技巧。4.1 檢測(cè)頻率與觸發(fā)機(jī)制定時(shí) vs 事件驅(qū)動(dòng)什么時(shí)候運(yùn)行死鎖檢測(cè)算法這是一個(gè)權(quán)衡開銷和及時(shí)性的問題。定時(shí)檢測(cè)系統(tǒng)設(shè)置一個(gè)固定的時(shí)間間隔如每5秒、每1分鐘啟動(dòng)檢測(cè)。優(yōu)點(diǎn)是實(shí)現(xiàn)簡(jiǎn)單可以將檢測(cè)開銷平均分?jǐn)傞_。缺點(diǎn)是死鎖發(fā)生后最長(zhǎng)需要等待一個(gè)檢測(cè)周期才能被發(fā)現(xiàn)響應(yīng)不及時(shí)。事件驅(qū)動(dòng)檢測(cè)當(dāng)新的“等待邊”產(chǎn)生時(shí)即一個(gè)事務(wù)/進(jìn)程因申請(qǐng)資源而阻塞時(shí)立即觸發(fā)檢測(cè)。這能保證死鎖幾乎被即時(shí)發(fā)現(xiàn)如上文提到的InnoDB。缺點(diǎn)是在高并發(fā)下頻繁的阻塞可能導(dǎo)致檢測(cè)被頻繁觸發(fā)開銷集中可能影響系統(tǒng)吞吐量?;旌喜呗哉壑械霓k法。采用事件驅(qū)動(dòng)但對(duì)檢測(cè)頻率設(shè)置一個(gè)下限如每秒最多觸發(fā)N次或者當(dāng)系統(tǒng)負(fù)載較低時(shí)采用事件驅(qū)動(dòng)負(fù)載高時(shí)切換為周期較長(zhǎng)的定時(shí)檢測(cè)。實(shí)操建議對(duì)于在線交易處理系統(tǒng)推薦使用事件驅(qū)動(dòng)或高頻率的定時(shí)檢測(cè)以快速響應(yīng)死鎖減少用戶等待時(shí)間。對(duì)于后臺(tái)批處理系統(tǒng)可以采用較低頻率的定時(shí)檢測(cè)以節(jié)省資源。4.2 分布式系統(tǒng)死鎖檢測(cè)的挑戰(zhàn)在單機(jī)系統(tǒng)中等待圖信息是集中的檢測(cè)相對(duì)直接。但在分布式系統(tǒng)中資源和進(jìn)程分散在不同的節(jié)點(diǎn)上構(gòu)建全局的等待圖變得異常困難。主流的分布式死鎖檢測(cè)方法有集中式檢測(cè)指定一個(gè)節(jié)點(diǎn)作為協(xié)調(diào)者。所有其他節(jié)點(diǎn)定期或在等待事件發(fā)生時(shí)向協(xié)調(diào)者發(fā)送本地等待信息。協(xié)調(diào)者匯總成全局圖進(jìn)行檢測(cè)。問題在于協(xié)調(diào)者單點(diǎn)故障和通信開銷。分布式檢測(cè)沒有中心節(jié)點(diǎn)。每個(gè)節(jié)點(diǎn)運(yùn)行自己的檢測(cè)算法并通過在進(jìn)程間傳遞“探針”消息來發(fā)現(xiàn)環(huán)路。例如 Chandy-Misra-Haas 算法。這種方式容錯(cuò)性好但算法復(fù)雜消息數(shù)量可能較多?;谌挚煺盏臋z測(cè)利用分布式快照算法如Chandy-Lamport算法獲取系統(tǒng)在某一時(shí)刻的一致性全局狀態(tài)然后在這個(gè)快照上運(yùn)行檢測(cè)算法。這更適用于事后分析而非實(shí)時(shí)解除。由于分布式死鎖檢測(cè)的復(fù)雜性和性能開銷許多現(xiàn)代分布式數(shù)據(jù)系統(tǒng)如Google Spanner、CockroachDB采用了不同的思路盡可能避免死鎖而不是檢測(cè)它。例如通過全局唯一、單調(diào)遞增的時(shí)間戳來規(guī)定所有事務(wù)的鎖獲取順序悲觀鎖或者使用樂觀并發(fā)控制在提交時(shí)再檢測(cè)沖突并讓沖突的事務(wù)中止這從本質(zhì)上避免了持有并等待形成的環(huán)。4.3 工具與監(jiān)控讓死鎖可視化對(duì)于開發(fā)和運(yùn)維人員不能只依賴系統(tǒng)自動(dòng)解除死鎖更需要主動(dòng)發(fā)現(xiàn)和根除死鎖的根源。這就需要監(jiān)控工具。數(shù)據(jù)庫層面MySQL InnoDB如前所述使用SHOW ENGINE INNODB STATUS\G。更進(jìn)階的可以開啟innodb_print_all_deadlocks配置將所有死鎖信息打印到錯(cuò)誤日志中便于集中收集分析。PostgreSQL查看pg_stat_activity視圖結(jié)合pg_locks視圖來分析鎖等待。日志中也會(huì)記錄死鎖信息。SQL Server使用 SQL Profiler 跟蹤Deadlock graph事件或查詢系統(tǒng)視圖sys.dm_tran_locks和sys.dm_os_waiting_tasks。應(yīng)用層面Java為例線程轉(zhuǎn)儲(chǔ)當(dāng)Java應(yīng)用疑似死鎖時(shí)使用jstack pid命令或kill -3 pid獲取線程轉(zhuǎn)儲(chǔ)。在轉(zhuǎn)儲(chǔ)文件末尾JVM通常會(huì)明確提示Found one Java-level deadlock:并列出死鎖線程的詳細(xì)堆棧信息。VisualVM, JProfiler 等工具這些圖形化工具可以連接至運(yùn)行的JVM直接檢測(cè)并展示死鎖線程。監(jiān)控告警將數(shù)據(jù)庫的死鎖計(jì)數(shù)器如Innodb_deadlocks或應(yīng)用日志中的死鎖錯(cuò)誤關(guān)鍵字納入監(jiān)控系統(tǒng)如 Prometheus Grafana, ELK并設(shè)置告警閾值。當(dāng)死鎖頻率超過一定范圍時(shí)及時(shí)通知研發(fā)人員介入排查。5. 從解除到預(yù)防根除死鎖的治本之策雖然檢測(cè)與解除是重要的安全網(wǎng)但一個(gè)健康的系統(tǒng)應(yīng)該追求的是盡可能少地觸發(fā)這個(gè)安全網(wǎng)。因此在理解了如何“救火”之后我們必須思考如何“防火”。5.1 通過設(shè)計(jì)模式避免死鎖在應(yīng)用代碼層面遵循一些成熟的設(shè)計(jì)模式可以極大降低死鎖概率固定順序獲取鎖這是避免死鎖最經(jīng)典、最有效的方法。如果系統(tǒng)中所有線程都按照一個(gè)全局約定的、固定的順序去申請(qǐng)鎖例如總是先鎖表A再鎖表B最后鎖表C那么循環(huán)等待的條件就不可能成立。這需要在對(duì)業(yè)務(wù)和數(shù)據(jù)進(jìn)行全局梳理的基礎(chǔ)上進(jìn)行設(shè)計(jì)。鎖超時(shí)機(jī)制不給鎖設(shè)置無限的等待時(shí)間。使用tryLock(long timeout, TimeUnit unit)這樣的方法在獲取鎖失敗一段時(shí)間后主動(dòng)放棄并回滾已做的工作或進(jìn)行重試。這打破了“持有并等待”條件因?yàn)榈却皇菬o限的但可能帶來活鎖問題需要配合隨機(jī)退避的重試策略。使用更高級(jí)的并發(fā)工具在Java中可以多使用java.util.concurrent包下的高級(jí)工具如ConcurrentHashMap、CopyOnWriteArrayList、Semaphore、CountDownLatch等。它們內(nèi)部實(shí)現(xiàn)了更高效的并發(fā)控制很多時(shí)候可以替代顯式的鎖減少死鎖風(fēng)險(xiǎn)??s小鎖的粒度與范圍盡量使用行級(jí)鎖而非表級(jí)鎖鎖住盡可能少的數(shù)據(jù)和盡可能短的時(shí)間。在事務(wù)中將最可能產(chǎn)生沖突的操作往后放盡快提交事務(wù)釋放鎖。5.2 數(shù)據(jù)庫事務(wù)設(shè)計(jì)最佳實(shí)踐數(shù)據(jù)庫是死鎖的重災(zāi)區(qū)良好的事務(wù)設(shè)計(jì)至關(guān)重要保持事務(wù)短小精悍事務(wù)執(zhí)行時(shí)間越長(zhǎng)持有鎖的時(shí)間就越長(zhǎng)與其他事務(wù)沖突的概率就越大。避免在事務(wù)中進(jìn)行遠(yuǎn)程調(diào)用、復(fù)雜的計(jì)算或人機(jī)交互。以一致的順序訪問數(shù)據(jù)這和“固定順序獲取鎖”同理。如果多個(gè)事務(wù)都需要更新用戶表和訂單表約定好都先更新用戶表再更新訂單表。合理使用索引UPDATE或DELETE語句的WHERE條件如果沒有合適的索引可能會(huì)升級(jí)為表鎖或鎖住大量不必要的行極易引發(fā)死鎖。確保高頻更新語句能用上索引??紤]使用樂觀鎖對(duì)于沖突不那么頻繁的場(chǎng)景可以使用版本號(hào)或時(shí)間戳的樂觀鎖機(jī)制。先讀取數(shù)據(jù)并記錄版本更新時(shí)檢查版本是否變化。這避免了在整個(gè)事務(wù)期間持有悲觀鎖從源頭減少了死鎖可能。謹(jǐn)慎使用SELECT ... FOR UPDATE明確你真的需要這條語句來鎖定讀取的行。不必要的悲觀鎖是死鎖的溫床。5.3 壓力測(cè)試與混沌工程在系統(tǒng)上線前或進(jìn)行重大變更后進(jìn)行有針對(duì)性的壓力測(cè)試是發(fā)現(xiàn)潛在死鎖問題的有效手段。模擬高并發(fā)場(chǎng)景使用JMeter、LoadRunner等工具模擬遠(yuǎn)高于日常峰值的并發(fā)用戶執(zhí)行那些涉及核心資源更新的業(yè)務(wù)流。關(guān)注長(zhǎng)尾延遲在壓力測(cè)試中不僅要看平均響應(yīng)時(shí)間和吞吐量更要關(guān)注P99、P99999分位、99.9分位的延遲。死鎖往往會(huì)導(dǎo)致少量請(qǐng)求的響應(yīng)時(shí)間異常飆升。引入混沌工程思想在測(cè)試環(huán)境甚至預(yù)發(fā)布環(huán)境可以故意制造一些“混亂”比如隨機(jī)延遲某個(gè)數(shù)據(jù)庫操作的響應(yīng)、隨機(jī)殺死某個(gè)服務(wù)實(shí)例觀察系統(tǒng)在異常情況下的行為看死鎖檢測(cè)與解除機(jī)制是否能正確工作。死鎖的處理從被動(dòng)的檢測(cè)解除到主動(dòng)的預(yù)防避免是一個(gè)系統(tǒng)工程。它要求開發(fā)者不僅了解底層的算法和機(jī)制更要具備良好的架構(gòu)設(shè)計(jì)意識(shí)和嚴(yán)謹(jǐn)?shù)木幊塘?xí)慣。把系統(tǒng)想象成一個(gè)復(fù)雜的交通網(wǎng)絡(luò)死鎖檢測(cè)與解除就是那套應(yīng)急清障和事故快處流程而良好的編碼規(guī)范和架構(gòu)設(shè)計(jì)則是科學(xué)的道路規(guī)劃、清晰的交通標(biāo)志和司機(jī)線程的守法意識(shí)。兩者結(jié)合才能保障系統(tǒng)這座“城市”的長(zhǎng)期暢通與穩(wěn)定。

相關(guān)新聞

videoJS播放m3u8視頻流:從原理到實(shí)戰(zhàn)的完整解決方案

videoJS播放m3u8視頻流:從原理到實(shí)戰(zhàn)的完整解決方案

1. 項(xiàng)目緣起:當(dāng)videoJS遇上m3u8,一個(gè)看似簡(jiǎn)單卻暗藏玄機(jī)的任務(wù) 最近在做一個(gè)內(nèi)部培訓(xùn)系統(tǒng)的后臺(tái),需要嵌入一些技術(shù)分享視頻。視頻團(tuán)隊(duì)給過來的源文件,清一色都是 .m3u8 格式的。對(duì)于前端來說,這不算什么新鮮事&#…

2026/8/1 15:11:43 閱讀更多
從TOP30榜單看眼科藥品零售趨勢(shì):一份基于規(guī)模及增速雙高數(shù)據(jù)的市場(chǎng)結(jié)構(gòu)分析

從TOP30榜單看眼科藥品零售趨勢(shì):一份基于規(guī)模及增速雙高數(shù)據(jù)的市場(chǎng)結(jié)構(gòu)分析

由中康開思發(fā)布的2026Q1全國(guó)零售藥店眼科類藥品規(guī)模&增速雙高TOP30榜單顯示,玻璃酸鈉滴眼液以5億銷售額穩(wěn)居一季度規(guī)模首位,作為干眼癥一線用藥的市場(chǎng)地位持續(xù)鞏固;左氧氟沙星滴眼液銷售額突破1億元,同比增長(zhǎng)31%,展…

2026/8/1 15:11:43 閱讀更多
ABAP開發(fā)中SY-INDEX與SY-TABIX的核心區(qū)別與應(yīng)用場(chǎng)景詳解

ABAP開發(fā)中SY-INDEX與SY-TABIX的核心區(qū)別與應(yīng)用場(chǎng)景詳解

1. 項(xiàng)目概述:從兩個(gè)“循環(huán)計(jì)數(shù)器”說起 在ABAP開發(fā)的世界里, SY-INDEX 和 SY-TABIX 是兩個(gè)幾乎每天都會(huì)打交道的系統(tǒng)變量。乍一看,它們都像是循環(huán)里的計(jì)數(shù)器,很多新手,甚至一些有幾年經(jīng)驗(yàn)的開發(fā)者,都曾…

2026/8/1 15:11:43 閱讀更多
CMake與Visual Studio的使用

CMake與Visual Studio的使用

前言:對(duì)于一些cmake編譯的項(xiàng)目,對(duì)于Windows環(huán)境下,我一般先安裝一個(gè)cmake gui(官網(wǎng)有)。開發(fā)環(huán)境:cmake gui:cmake 3.22VS:2019第一步設(shè)置源碼目錄:選擇你的項(xiàng)目根目錄&a…

2026/8/1 16:21:45 閱讀更多
數(shù)字孿生行業(yè)動(dòng)態(tài):飛渡科技、51視界、漂視網(wǎng)絡(luò)引領(lǐng)新賽道

數(shù)字孿生行業(yè)動(dòng)態(tài):飛渡科技、51視界、漂視網(wǎng)絡(luò)引領(lǐng)新賽道

數(shù)字孿生行業(yè)動(dòng)態(tài):飛渡科技、51視界、漂視網(wǎng)絡(luò)引領(lǐng)新賽道 引言 數(shù)字孿生技術(shù)作為工業(yè)4.0和智慧城市建設(shè)的核心引擎,正迎來前所未有的發(fā)展機(jī)遇。本文聚焦國(guó)內(nèi)數(shù)字孿生領(lǐng)域的領(lǐng)軍企業(yè)——飛渡科技、51視界、漂視網(wǎng)絡(luò)的最新動(dòng)態(tài),剖析行業(yè)發(fā)展風(fēng)向…

2026/8/1 16:21:45 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應(yīng)用材料(Applied Materials)公司生產(chǎn)的一款用于半導(dǎo)體設(shè)備的I/O信號(hào)分配電路板。該型號(hào)(0100-02186)的核心特點(diǎn)如下:專用于Endura等半導(dǎo)體工藝腔室。集成信號(hào)路由與分配功能。連接控制…

2026/8/1 0:09:33 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機(jī),適用于自動(dòng)化設(shè)備及通用機(jī)械驅(qū)動(dòng)。該型號(hào)(FFMN-32L-10-T0 40AX)的核心特點(diǎn)如下:三相交流異步電動(dòng)機(jī)。額定…

2026/8/1 0:09:33 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應(yīng)用材料(Applied Materials)公司生產(chǎn)的一款用于半導(dǎo)體設(shè)備的I/O信號(hào)分配電路板。該型號(hào)(0100-02186)的核心特點(diǎn)如下:專用于Endura等半導(dǎo)體工藝腔室。集成信號(hào)路由與分配功能。連接控制…

2026/8/1 0:09:33 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機(jī),適用于自動(dòng)化設(shè)備及通用機(jī)械驅(qū)動(dòng)。該型號(hào)(FFMN-32L-10-T0 40AX)的核心特點(diǎn)如下:三相交流異步電動(dòng)機(jī)。額定…

2026/8/1 0:09:33 閱讀更多