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>
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技術方案詳解,喜歡的能夠點贊關注哦~