redis筆記6 拓展內容

集羣情況下的分佈式鎖

集羣情況下,redis的分佈式鎖有不安全的因素,下面這個場景:

  1. 主節點擁有鎖
  2. 客戶端獲取鎖後,主節點掛掉
  3. 從節點接替,成爲主節點,但是從節點沒有客戶端獲取的鎖
  4. 新來的客戶端向現在的主節點獲取鎖,會成功,導致出現數據競爭

RedLock算法可以解決該問題,該算法基本的思想是,加鎖時向過半節點發送set(key, value, nx=True, ex=xxx)指令,只要半數節點set成功,則加鎖成功;釋放鎖時,向所有節點發送del指令。實際的情況還要考慮出錯重試和時漂移等,比較複雜。

該算法可以保證高可用性,但是犧牲性能,而且需要更多的redis實例。

過期策略

定時刪除: Redis把過期的key放在一個單獨的字典中,之後會定時遍歷該字典,然後刪除已經過期的key。集中處理
惰性刪除:客戶端訪問一個key時,redis先檢查key是否過期,如果過期則立刻刪除。零散處理

redis默認每10秒掃描一次過期詞典,定時掃描策略如下:

  1. 從過期詞典中隨機選出20個key
  2. 刪除20個key中已經過期的
  3. 如果過期的key超過14\frac{1}{4},則重複步驟1

爲了防止循環過度,redis默認上限的循環時間時25ms,過時立刻停止,不影響服務。

如果redis中大量的key在同一時刻過期,可能會造成redis卡頓,原因有2個:

  • redis持續掃描過期詞典,直到key稀疏
  • 內存管理器需要頻繁回收內存頁,產生CPU消耗

服務器如果處於掃描過期狀態,則客戶端請求至少25ms才能得到應答,此時在業務上,會出現大量連接超時關閉的異常。redis的slowlog的慢查詢記錄無法看到,因爲這個記錄只是記錄了執行的時間,不包括等待時間。因此,如果有大批量的key,請設置隨機的超時時間,防止同時過期。

從節點沒有定期掃描機制,過期處理時被動的。主節點的key到期時,會在AOF中追加del指令,這樣同步到所有的從節點,從節點執行該指令來刪除過期的key。同步指令異步執行,如果執行不及時,則可能出現數據不一致的情況。

Redis的刪除機制

如果內存超出物理限制,內存數據會和磁盤交換,redis爲了效率,不允許這種情況。

Redis使用類似LRU的算法。因爲LRU算法本身比較消耗內存。隨機LRU給每個key一個24bit的空間,用於表示時間戳。當redis執行寫操作時,如果超過maxmemory限制時,隨機選出5個(可調節)key,然後刪除這些key,如果任然超時,則繼續刪除,直到滿足條件爲止。

懶惰刪除

redis的單線程,不是完全只有一個線程,而是隻有一個主線程處理邏輯等操作,多個異步線程處理異步任務。

ulink key

是把key丟個後臺異步線程刪除。這裏不會有數據競爭,一旦使用該命令,則外界不會獲取到該key了。

flushall async  # 異步刪除,同樣的原理,沒有數據競爭。

主線程把數據“刪除”後,對應的key的內存,會進入一個線程安全的異步隊列,由後臺線程完成內存回收。同樣的,AOF操作也是有自己的任務隊列。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章