redis緩存加鎖
㈠ 緩存擊穿、穿透、雪崩及Redis分布式鎖
分布式鎖: setnx ,redisson 並發問題
冪等問題: 落表狀態,Redis
緩存擊穿: 指緩存中無,db中有
原因: 一個key高並發恰好失效導致大量請求到db
方案: 加鎖,自旋鎖,或一個線程查db,一個線程監控(直接用Redisson分布式鎖)
緩存穿透:指緩存和db中均無
原因: 一般是惡意請求
方案: 加布隆過濾,或查db無時,也設置緩存,value為某些特殊表示或"null"
雪崩:指緩存同時大量失效
原因: 大量的key同時失效,db壓力加大
方案: 設置失效時間是增加隨機數
問題方案文獻:
https://www.jianshu.com/p/31ab9b020cd9 (圖例分析)
https://blog.csdn.net/fcvtb/article/details/89478554
Redis分布式鎖:
事務未執行完鎖已到期釋放問題:使用Redissoin解決續租問題,內部已解決
分布式鎖文獻:
https://www.jianshu.com/p/4838f8be00c9
https://blog.csdn.net/qq_30038111/article/details/90696233 (setnx + expire同時操作)
====================================
https://www.runoob.com/redis/keys-scan.html
https://www.jianshu.com/p/611a492d9121 Redis原理與應用
㈡ 濡備綍浣跨敤redis瀹炵幇鍒嗗竷寮忛攣鍔熻兘錛
鐢變簬redis鏄鍗曠嚎紼嬬殑涓旀ц兘寰堝揩錛屾墍浠ユ瘮杈冮傚悎鍋氬叏灞鍒嗗竷寮忛攣銆
鍩烘湰嫻佺▼灝辨槸鍦ㄦ搷浣滃彲鑳芥煇涓鍏ㄥ矓鍐茬獊璧勬簮鐨勬椂鍊欙紝浣跨敤涓涓鍏ㄥ矓鍞涓key鏉ュ垽鏂鏄鍚︽湁鍏朵粬綰跨▼鍗犵敤浜嗚祫婧愶紝濡傛灉鏈夊叾浠栫嚎紼嬪崰鐢錛屽垯鎶ラ敊閫鍑烘垨鑰呭驚鐜絳夊緟銆傚傛灉娌℃湁鍏朵粬綰跨▼鍗犵敤錛屽垯灝卞彲浠ラ氳繃娣誨姞鍒嗗竷寮忛攣鏉ュ崰鐢ㄨ繖涓璧勬簮錛岀劧鍚庡啀鎵ц屽悗緇鐨勪換鍔★紝鍦ㄤ換鍔℃墽琛屽畬鎴愪箣鍚庯紝鍐嶉噴鏀懼垎甯冨紡閿侊紝鍏朵粬綰跨▼灝卞彲浠ョ戶緇浣跨敤榪欎釜璧勬簮浜嗐
閭d箞閫氳繃redis鍔犻攣鐨勫姩浣滄槸浠涔堝憿錛
綆鍗曞姞閿佸懡浠わ細
鍛戒護鏄錛歴etnx
鍐呴儴鐨勫疄鐜版満鍒跺氨鏄鍒ゆ柇榪欎釜key浣嶇疆鏄涓嶆槸鏈夋暟鎹錛屾病鏈夋暟鎹灝辮劇疆鎴恦alue榪斿洖錛屾湁鏁版嵁灝辮繑鍥炰竴涓鐗規畩鏁板箋
浣嗘槸榪欓噷鏈変竴涓闂棰樻槸錛屽傛灉鍗犵敤璧勬簮鐨勭嚎紼嬮敊璇閫鍑轟簡錛屾病鏈夋潵寰楀強閲婃斁鍒嗗竷寮忛攣錛岃繖涓閿佸氨琚姘歌繙鐨勫崰鐢ㄤ簡
鏀硅繘鐗堢殑鍔犻攣錛
鍛戒護鏄錛1. setnx 2. expire
娣誨姞鍒嗗竷寮忛攣鐨勫悓鏃訛紝娣誨姞涓涓閿侀攣榪囨湡鐨勬椂闂淬傝繖鏍鳳紝褰撳姞閿佺嚎紼嬮鍑轟箣鍚庯紝鑷沖皯絳変竴孌墊椂闂翠箣鍚庯紝閿佹槸鏈夋満浼氶噴鏀炬帀鐨勩
榪欓噷鏈変竴涓灝忛棶棰樻槸錛岃繖涓や釜鍛戒護鏄鍒嗗紑鎵ц岀殑錛屼笉鏄鍘熷瓙鎿嶄綔銆傞偅涔堝氨瀛樺湪鐞嗚轟笂鏉ヨ達紝絎涓涓鍛戒護鎵ц屽畬涔嬪悗錛屽氨鍑虹幇閿欒錛屾潵涓嶅強鎵ц宔xpire鍛戒護鐨勫彲鑳斤紝涓縐嶅姙娉曟槸鑷宸卞啓lua鑴氭湰錛屽彲浠ュ疄鐜板氭潯鍛戒護鐨勫師瀛愬寲鎵ц屻備竴縐嶅姙娉曟槸寮曠敤涓浜涘紑婧愬簱銆傚湪2.8鐗堟湰涔嬪悗錛宺edis涓轟簡瑙e喅榪欎釜闂棰橈紝鎻愪緵浜嗗畼鏂圭増鐨勮В娉曪紝灝辨槸鍛戒護錛歴et key value nx expireTimeNum ex錛屽皢涓婅堪涓や釜鍛戒護鍚堝苟鎴愪簡涓涓鍛戒護銆
鏈変簡榪囨湡鏃墮棿涔嬪悗瑙e喅浜嗕竴閮ㄥ垎闂棰橈紝浣嗘槸涔熸湁鍙鑳藉嚭鐜伴攣閮借繃鏈熶簡錛屼絾鏄涓闂存墽琛岀殑浠誨姟榪樻病鏈夌粨鏉燂紝絎涓涓綰跨▼榪樺湪鎵ц屼簡錛岀浜屼釜綰跨▼宸茬粡鎷垮埌閿佸紑濮嬫墽琛屼簡錛岄偅涔堣繖鏃跺欑涓涓綰跨▼濡傛灉鎵ц屽畬鎴愪箣鍚庯紝閭d箞灝變細灝嗙浜屼釜綰跨▼鐨勯攣閲婃斁鎺変簡銆傜浜屼釜綰跨▼閲婃斁閿佺殑鏃跺欙紝瑕佷笉鐒跺嚭閿欙紝瑕佷笉鐒舵槸閲婃斁鐨勫叾浠栫嚎紼嬬殑閿侊紝榪欐牱涔熶細鍜岄勬湡涓嶇︺
濡傛灉鍗曠函鍦拌佽В鍐寵繖涓闂棰樼殑璇濓紝鍙浠ュ湪璁劇疆value鐨勬椂鍊欎嬌鐢ㄤ竴涓闅忔満鏁幫紝閲婃斁閿佺殑鏃跺欙紝鍏堝垽鏂榪欎釜闅忔満鏁版槸鍚︿竴鑷達紝濡傛灉涓鑷村啀鍒犻櫎閿侊紝鍚﹀垯灝遍鍑恆備絾鏄鍒ゆ柇value鍜屽垹闄key涔熶笉鏄涓涓鍘熷瓙鎿嶄綔錛岃繖鏃跺欏氨闇瑕佷嬌鐢╨ua鑴氭湰浜嗐
涓婇潰鐨勬柟妗堜緷鐒朵笉鑳借В鍐寵秴鏃墮噴鏀劇殑闂棰橈紝渚濈劧榪濊儗鍒嗗竷寮忛攣鐨勫垵琛楓傛庝箞鍔炰簡錛
瑙i樻濊礬鏄鍙﹀栧惎鍔ㄤ竴涓綰跨▼錛屽畠鐨勪換鍔″氨鏄姣忛殧涓孌墊椂闂村垽鏂涓涓嬪傛灉鍙戠幇褰撳墠綰跨▼鐨勪換鍔″揩榪囨湡浜嗚繕娌℃湁瀹屾垚錛屽垯瀹氭湡緇欏綋鍓嶇嚎紼嬬殑閿佺畫涓鏈熴
鏈変釜寮婧愬簱瑙e喅浜嗚繖涓闂棰橈紝瀹冨ぇ姒傜巼浼氭瘮浣犲疄鐜板緱鏇村ソ涓浜涖傝繖涓搴撳氨鏄痳edisson錛岄潪甯稿ソ璁幫紝灝辨槸redis鐨勫効瀛恠on錛岃繛璧鋒潵灝辨槸reidsson錛岃櫧鐒跺彲鑳戒笉鏄浜茬殑錛屼絾鏄涔熻凍澶熶簡銆
榪欎釜搴撻噷闈㈡湁涓涓緇勪歡鏄痺atchdog錛岀洿璇戣繃鏉ュ氨鏄鐪嬮棬鐙楋紝瀹冪殑浣滅敤灝辨槸姣忛殧涓孌墊椂闂村垽鏂鐨勩
鍐嶇戶緇鎬濊冿紝榪樻湁涓涓鏇存瀬絝鐨勯棶棰樻槸錛宺edis濡傛灉鏄鍗曡妭鐐圭殑錛屽畠瀹曟満浜嗭紱鎴栬呮槸涓誨囪妭鐐圭殑錛屼絾鏄澶囦喚鑺傜偣榪樻病鏈夋潵寰楀強鍚屾ヤ富鑺傜偣鐨勬暟鎹錛屼富鑺傜偣鎷垮埌閿佷箣鍚庯紝鍦ㄥ悓姝ユ暟鎹涔嬪墠灝遍┈涓婂畷鏈轟簡錛屽垯涔熸湁鍙鑳藉嚭鐜伴攣涓嶄綇鐨勯棶棰樸傚傛灉璁や負榪欐槸涓涓闂棰橈紝鎯寵佽В鍐寵繖涓闂棰橈紝榪欎釜闂棰樻庝箞瑙e喅浜嗭紵
鎬濊礬鏄鍦ㄥ姞閿佺殑鏃跺欏氬姞閿佸嚑鍙皉edis鏈嶅姟鍣錛岄氬父鎯呭喌涓媟edis閮ㄧ講鐨勬椂鍊欐槸2n+1鍙幫紝閭d箞鍦ㄥ姞閿佺殑鏃跺欓渶瑕佷繚璇佽繃鍗婃暟鏈嶅姟鍣ㄥ姞閿佹垚鍔熶簡錛屼篃灝辨槸璇磏+1鍙版湇鍔″櫒銆傝繖鏃跺欓櫎闈炴暣涓闆嗙兢閮戒笉鍙鐢ㄤ簡錛屽垯榪欎釜瀹夊叏鎬у皢澶у箙搴︽彁鍗囥
榪欎釜闂棰樹篃鏈夊紑婧愬簱瑙e喅浜嗭紝灝辨槸redis綰㈤攣銆
涓嬩竴涓闂棰樻槸鍒嗗竷寮忛攣鍙浠ラ噸鍏ヤ箞錛
濡傛灉鎯寵佸疄鐜板彲閲嶅叆鐨勫垎甯冨紡閿佺殑璇濓紝闇瑕佸湪璁劇疆value鐨勬椂鍊欏姞涓婄嚎紼嬩俊鎮鍜屽姞閿佹℃暟鐨勪俊鎮銆備絾鏄榪欐槸綆鍗曠殑鎬濊礬錛屽傛灉鍔犱笂榪囨湡鏃墮棿絳夐棶棰樹箣鍚庯紝鍙閲嶅叆閿佸氨鍙鑳芥瘮杈冨嶆潅浜嗐
㈢ Redis怎麼實現分布式鎖
阿粉最近迷上了 Redis,為什麼呢?感覺 Redis 確實功能很強大呀,一個基於內存的系統 Key-Value 存儲的資料庫,竟然有這么多的功能,而阿粉也要實實在在地把 Redis 來弄一下,畢竟面試的時候,Redis 可以說是一個非常不錯的加分項。
為什麼需要分布式鎖?
目前很多的大型項目全部都是基於分布式的,而分布式場景中的數據一致性問題一直是一個不可忽視的問題,大家知道關於分布式的 CAP 理論么?
CAP 理論就是說任何一個分布式系統都無法同時滿足一致性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance),最多隻能同時滿足兩項。
而我們的系統最終滿足的永遠都是最終一致性,而這種最終一致性,有些時候有人會喜歡問關於分布式事務,而有些人則偏重在分布式鎖上。
但是阿粉選擇的就是使用緩存來實現分布式鎖,也就是我們在項目中最經常使用的 Redis ,談到 Redis,那真是可以用在太多地方了,比如說:
我們今天就來實現用 Redis 來實現分布式鎖,並且要學會怎麼使用。
1.准備使用 Jedis 的 jar 包,在項目中導入 jar 包。
jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); 這個加鎖的姿勢才是我們最需要了解的,不然你用的時候都不知道怎麼使用。
key:加鎖的鍵,實際上就是相當於一個唯一的標志位,不同的業務,你可以使用不同的標志位進行加鎖。
requestId:這個東西實際上就是用來標識他是哪一個請求進行的加鎖,因為在分布式鎖中,我們要知道一件事,就是加鎖的和解鎖的,必須是同一個客戶端才可以。
而且還有一種比較經典的就是 B 把 A 的鎖給釋放了,導致釋放混亂,如果你不加相同的請求,A 線程處理業務,執行了加鎖,鎖的過期時間是5s, B線程嘗試獲取鎖,如果 A 處理業務時間超過5s,這時候 A 就要開始釋放鎖,而B在這時候沒有檢測到這個鎖,從而進行了加鎖,這時候加鎖的時候,A還沒處理完對應業務,當他處理完了之後,再釋放鎖的話,要是就是直接把 B 剛加的鎖釋放了,要麼就是壓根都沒辦法釋放鎖。
SET_IF_NOT_EXIST:看字面意思,如果 key 不存在,我們進行Set操作,如果存在,啥都不幹,也就不在進行加鎖。
SET_WITH_EXPIRE_TIME:是否過期
expireTime:這是給 key 設置一個過期的時間,萬一你這業務一直被鎖著了,然後之後的業務想加鎖,你直接給一直持有這個這個鎖,不進行過期之後的釋放,那豈不是要涼了。
上面的方法中 tryGetDistributedLock 這個方法也就是我們通常使用的加鎖的方法。
大家看到這個 script 的時候,會感覺有點奇怪,實際上他就是一個 Lua 的腳本,而 Lua 腳本的意思也比較簡單。
其實這時候就有些人說,直接 del 刪除不行么?你試試你如果這么寫的話,你們的領導會不會把你的腿給你打斷。
這種不先判斷鎖的擁有者而直接解鎖的方式,會導致任何客戶端都可以隨時進行解鎖,也就是說,這鎖就算不是我加的,我都能開,這怎麼能行呢?
在這里給大家放一段使用的代碼,比較簡單,但是可以直接用到你們的項目當中
我們先把這個實現方式實現了,然後我們再來說說大家最不願意看的理論知識,畢竟這理論知識是你面試的時候經常會被問到的。
分布式CAP理論:
加州大學伯克利分校的 Eric Brewer 教授在 ACM PODC 會議上提出 CAP 猜想。2年後,麻省理工學院的 Seth Gilbert 和 Nancy Lynch 從理論上證明了 CAP。之後,CAP 理論正式成為分布式計算領域的公認定理。
也就是說,在二十年前的時候,CAP 理論只是個猜想。結果兩年之後被證實了,於是,大家在考慮分布式的時候,就有根據來想了,不再是空想了。
什麼是分布式的 CAP 理論 ?
一個分布式系統最多隻能同時滿足一致性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance)這三項中的兩項
這個和(Atomicity)不太一樣,因為之前看有些人說,在 CAP 理論中的 A 和資料庫事務中的 A 是一樣的,單詞都不一樣,那能一樣么?
Availability :分布式中的 A 表示的是可用性,也就是說服務一直可用,而且是正常響應時間。
而你在搭建分布式系統的時候,要保證每個節點都是穩定的,不然你的可用性就沒有得到相對應的保證,也談不上是什麼分布式了。只能稱之為一個偽分布式。
Consistency: 一致性
也就是說你的更新操作成功並返回客戶端完成後,所有節點在同一時間的數據完全一致,這個如果你在使用 Redis 做數據展示的時候,很多面試官都會問你,那你們是怎麼保證資料庫和緩存的一致性的呢?
畢竟你只是讀取的話,沒什麼問題,但是設計到更新的時候,不管是先寫資料庫,再刪除緩存;還是先刪除緩存,再寫庫,都有可能出現數據不一致的情況。
所以如果你對這個很感興趣,可以研究一下,比如說:
如果你能在面試的時候把這些都給面試官說清楚,至少感覺你應該能達到你自己的工資要求。
Partition tolerance:分區容錯性
分布式系統在遇到某節點或網路分區故障的時候,仍然能夠對外提供滿足一致性和可用性的服務。
其實在 CAP 理論當中,我們是沒有辦法同時滿足一致性、可用性和分區容錯性這三個特性,所以有所取捨就可以了。
關於使用 Redis 分布式鎖,大家學會了么?
㈣ 使用redis實現的分布式鎖原理是什麼
一、寫在前面
現在面試,一般都會聊聊分布式系統這塊的東西。通常面試官都會從服務框架(Spring Cloud、Dubbo)聊起,一路聊到分布式事務、分布式鎖、ZooKeeper等知識。
所以咱們這篇文章就來聊聊分布式鎖這塊知識,具體的來看看Redis分布式鎖的實現原理。
說實話,如果在公司里落地生產環境用分布式鎖的時候,一定是會用開源類庫的,比如Redis分布式鎖,一般就是用Redisson框架就好了,非常的簡便易用。
大家如果有興趣,可以去看看Redisson的官網,看看如何在項目中引入Redisson的依賴,然後基於Redis實現分布式鎖的加鎖與釋放鎖。
下面給大家看一段簡單的使用代碼片段,先直觀的感受一下:
大家看到了吧,那個myLock的hash數據結構中的那個客戶端ID,就對應著加鎖的次數
(5)釋放鎖機制
如果執行lock.unlock(),就可以釋放分布式鎖,此時的業務邏輯也是非常簡單的。
其實說白了,就是每次都對myLock數據結構中的那個加鎖次數減1。
如果發現加鎖次數是0了,說明這個客戶端已經不再持有鎖了,此時就會用:
「del myLock」命令,從redis里刪除這個key。
然後呢,另外的客戶端2就可以嘗試完成加鎖了。
這就是所謂的分布式鎖的開源Redisson框架的實現機制。
一般我們在生產系統中,可以用Redisson框架提供的這個類庫來基於redis進行分布式鎖的加鎖與釋放鎖。
(6)上述Redis分布式鎖的缺點
其實上面那種方案最大的問題,就是如果你對某個redis master實例,寫入了myLock這種鎖key的value,此時會非同步復制給對應的master slave實例。
但是這個過程中一旦發生redis master宕機,主備切換,redis slave變為了redis master。
接著就會導致,客戶端2來嘗試加鎖的時候,在新的redis master上完成了加鎖,而客戶端1也以為自己成功加了鎖。
此時就會導致多個客戶端對一個分布式鎖完成了加鎖。
這時系統在業務語義上一定會出現問題,導致各種臟數據的產生。
所以這個就是redis cluster,或者是redis master-slave架構的主從非同步復制導致的redis分布式鎖的最大缺陷:在redis master實例宕機的時候,可能導致多個客戶端同時完成加鎖。