《意外成為殘疾總監的心尖寵【完結】》第52頁 明燦彎起眼睛笑了下(1)

作者:溫水煮茶·4天前

明燦彎起眼睛笑了下,把空碗收進保溫袋裡,又把桌上的橘子皮收拾乾淨,拿溼巾把桌面擦了一遍,最後把水杯拿起來,重新接了半杯溫水遞過去。

“姐姐,我今天做哪個模組?昨天你讓我改的那幾個bug我都改的差不多了。”

“分散式鎖。”蘇執說,接過明燦遞來的水杯,但沒有喝,只是捧在手裡,指腹摩挲著杯壁,“昨天你做的那個定時任務,在多例項部署的情況下會重複執行。”

明燦眨了下眼睛,手裡還捏著半瓣橘子,頓住了。

她做的那個定時任務,是每天早上三點統計前一天的運營資料。在本地開發環境跑得好好的,但她心裡清楚,蘇執說的問題確實存在——如果生產環境部署了多個服務例項,每個例項都會在三點觸發同一個任務,重複寫入資料,輕則資料冗餘,重則邏輯錯亂。

“所以需要分散式鎖。”蘇執把水杯放到床頭櫃上,伸手去夠床頭櫃上的筆記本,明燦趕緊放下橘子,把電腦遞過去。

蘇執把筆記本放在自己面前的小桌板上,指尖在觸控板上點了幾下,開啟一個空白的編輯器,一邊敲一邊說:“方案有很多,資料庫悲觀鎖、Redis的setnx、Zookeeper的臨時順序節點,你用哪個?”

明燦湊過去看,蘇執的手指在鍵盤上敲得很快,一行一行的基礎程式碼出現在螢幕上,不是完整的實現,而是一個骨架——鎖的介面定義、加鎖解鎖的基本流程、異常處理的框架。

“Redis。”明燦說,語氣裡帶著一點不確定,“用setnx,配合lua指令碼保證原子性,設定過期時間避免死鎖。”

蘇執停下來,側過臉看了她一眼。那一眼很淡,但明燦覺得自己被從頭到腳審視了一遍,像面試時被技術總監盯著等回答的那種感覺,心跳不由自主地加快了幾拍。

“繼續。”蘇執說。

明燦深吸一口氣,開始說:“加鎖的時候用setnx,如果返回成功就拿到鎖,同時設定一個過期時間比如三十秒。如果返回失敗說明鎖被其他例項佔用,可以重試或者直接放棄。鎖的持有者需要在業務邏輯執行完之後釋放鎖,刪除對應的key。為了防止A執行緒的鎖被B執行緒釋放,value要用一個唯一標識,比如UUID或者執行緒ID,釋放的時候先get再判斷,匹配了才能del。”

她說完,怯生生看著蘇執。

蘇執沒有立刻表態,低下頭在鍵盤上又敲了幾行,然後把螢幕轉向明燦。

螢幕上是一個完整的Redis分散式鎖實現,用lua指令碼把判斷和刪除兩個操作合併成一個原子操作,避免了get和del之間的時間視窗。明燦一行一行地看,看到最後一行的時候,發現蘇執還在程式碼末尾加了一行註釋:// 考慮使用Redisson的RLock,自動續期機制更優雅。

明燦盯著那行註釋看了兩秒,然後抬頭看蘇執:“姐姐,你這是……在教我寫程式碼,還是在給我做程式碼審查?”

“都是。”蘇執的聲音很淡,但嘴角有一個極其細微的弧度,像是剋制過但沒完全剋制住,“你剛才說的方案裡,漏了一個關鍵問題。”

明燦愣了:“什麼?”

“鎖過期了但業務還沒執行完怎麼辦?”

明燦張了張嘴,又閉上了。

她確實漏了這個。

如果設定的過期時間是三十秒,但業務邏輯執行了四十秒,那麼鎖在第三十秒的時候就會自動釋放,另一個例項拿到鎖進來執行同樣的任務,等第一個例項執行完再釋放鎖的時候,釋放的是第二個例項的鎖。後果很嚴重——鎖的持有者被誤刪,第二個例項以為自己還有鎖,實際上鎖已經被別人幹掉了。

“所以需要鎖續期。”蘇執說,“拿到鎖之後啟動一個後臺執行緒,每隔一段時間檢查一下鎖是否還在,如果還在就延長過期時間。業務執行完再取消續期,釋放鎖。”

明燦聽得認真,眉頭微微皺著,腦子裡在消化這個方案。她想了想,問了一個問題:“那如果持有鎖的例項突然宕機了,續期執行緒也掛了,鎖是不是就永遠不釋放了?”

蘇執看了她一眼,那一眼裡多了一點東西——不是誇獎,但比誇獎更讓明燦受用,那是一種“你終於開始想邊緣情況了”的認可。

“所以Redis分散式鎖有一個經典的缺陷,就是這個問題。嚴格意義上來說,它做不到百分之百的絕對安全,只能做到百分之九十九點九九。”蘇執的語氣不緊不慢,像在講一門精心準備過的課,“如果需要更高的一致性,可以考慮Zookeeper或者etcd,它們的分散式鎖是基於臨時順序節點和會話心跳實現的,客戶端宕機了節點會自動刪除,不會有死鎖問題。”

她說完,停了一下,看著明燦。

猜你喜歡

同題材或同分類的其他作品。