時序鎖

問題

我們傳統的互斥鎖,是不支持時序(按照搶鎖的先後順序獲取鎖。)
我們遇到一種情況,我們的一個任務超時時間設置的是30min。多個任務併發時,因爲存在共享資源A,需要對共享資源A加阻塞鎖,預計正常情況下每個任務會佔用鎖5分鐘。

我們的異步任務框架,限制同時正在運行的併發任務的個數是3個。按照傳統的思考方式,一個任務最多等待 2*5min,但是實際情況是,我們依次下發了10個任務a,b,c,d,e…,最後的執行結果是有些任務超時失敗了。爲什麼會出現這種情況。

獲取因爲獲取鎖的不確定性導致了這樣的一個獲取鎖的順序,
時間線—佔用鎖的對象
5-10min-------------a(b,c在阻塞等待)
10-15min-----------c(a執行完成,b,d在阻塞等待鎖)
15-20min-----------d(a,c執行完成,b,e在阻塞等待鎖)
20-25min-----------e (a,c,d執行完成,b,f在等待鎖)
25-30min-----------f(a,c,d,e執行完成,b,g在等待鎖)
30-35min-----------g(a,c,d,e執行完成,b執行超時,任務失敗

若干任務失敗。

如何讓任務能夠按照我們所期望的按照到來的順序,佔用鎖呢?

解決方案

這其實就是一個隊列的原理,先進先出唄;在我們原來的互斥鎖的基礎上,前面加一個隊列。挖個坑,我們的鎖是怎麼實現的呢?且聽下回分解,基於文件鎖實現的,爲什麼基於文件鎖實現而不使用threading庫中的互斥鎖,因爲web程序是多進程的。
先簡單介紹一下我們原來的阻塞鎖,循環sleep等待delay秒,一直到獲取到鎖或者超時。
藉助redis的隊列,
在這裏插入圖片描述

實現

源碼實現,注意考慮下面幾個異常點:

  1. 系統時間的不可靠
  2. 緩存的不可靠
  3. redis操作的原子性

擴展

  1. 減少鎖衝突,的另一個方法是減小鎖的粒度。
  2. 依賴系統時間不是一個好的辦法(耦合了系統時間,修改系統時間將會影響到此程序,而且寫此程序的時候需要考慮),最好是能依賴系統的uptime,這樣能減少對系統時間的耦合。
  3. redis 事務操作。
發佈了125 篇原創文章 · 獲贊 31 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章