Redis併發競爭key的解決方案詳解

01. 併發競爭的由來java

1.Redis高併發的問題redis

Redis緩存的高性能有目共睹,應用的場景也是很是普遍,可是在高併發的場景下,也會出現問題:緩存擊穿、緩存雪崩、緩存和數據一致性,以及今天要談到的緩存併發競爭。sql

這裏的併發指的是多個redis的client同時set key引發的併發問題。數據庫

2.出現併發設置Key的緣由緩存

Redis是一種單線程機制的nosql數據庫,基於key-value,數據可持久化落盤。因爲單線程因此Redis自己並無鎖的概念,多個客戶端鏈接並不存在競爭關係,可是利用jedis等客戶端對Redis進行併發訪問時會出現問題。併發

好比:同時有多個子系統去set一個key。這個時候要注意什麼呢?nosql

3.舉一個例子分佈式

多客戶端同時併發寫一個key,一個key的值是1,原本按順序修改成2,3,4,最後是4,可是順序變成了4,3,2,最後變成了2。函數

如何解決redis的併發競爭key問題呢?下面給到2個Redis併發競爭的解決方案。高併發

02. 第一種方案:分佈式鎖+時間戳

1.總體技術方案

這種狀況,主要是準備一個分佈式鎖,你們去搶鎖,搶到鎖就作set操做。
加鎖的目的實際上就是把並行讀寫改爲串行讀寫的方式,從而來避免資源競爭。

2.Redis分佈式鎖的實現

主要用到的redis函數是setnx()

用SETNX實現分佈式鎖

利用SETNX很是簡單地實現分佈式鎖。例如:某客戶端要得到一個名字youzhi的鎖,客戶端使用下面的命令進行獲取:
SETNX lock.youzhi<current Unix time + lock timeout + 1>

  • 如返回1,則該客戶端得到鎖,把lock.youzhi的鍵值設置爲時間值表示該鍵已被鎖定,該客戶端最後能夠經過DEL lock.foo來釋放該鎖。
  • 如返回0,代表該鎖已被其餘客戶端取得,這時咱們能夠先返回或進行重試等對方完成或等待鎖超時。

2.時間戳

因爲上面舉的例子,要求key的操做須要順序執行,因此須要保存一個時間戳判斷set順序。

系統A key 1 {ValueA 7:00}
系統B key 1 { ValueB 7:05}
複製代碼

假設系統B先搶到鎖,將key1設置爲{ValueB 7:05}。接下來系統A搶到鎖,發現本身的key1的時間戳早於緩存中的時間戳(7:00<7:05),那就不作set操做了。

3.什麼是分佈式鎖

由於傳統的加鎖的作法(如java的synchronized和Lock)這裏沒用,只適合單點。由於這是分佈式環境,須要的是分佈式鎖。
固然,分佈式鎖能夠基於不少種方式實現,好比zookeeper、redis等,無論哪一種方式實現,基本原理是不變的:用一個狀態值表示鎖,對鎖的佔用和釋放經過狀態值來標識。

03. 第二種方案:利用消息隊列

在併發量過大的狀況下,能夠經過消息中間件進行處理,把並行讀寫進行串行化。
把Redis.set操做放在隊列中使其串行化,必須的一個一個執行。

這種方式在一些高併發的場景中算是一種通用的解決方案。

end~

以上就是Redis併發競爭key技術方案詳解,喜歡的能夠點贊關注哦~

相關文章
相關標籤/搜索