您好,登錄后才能下訂單哦!
這篇文章主要介紹“Redis鎖的用法”,在日常操作中,相信很多人在Redis鎖的用法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Redis鎖的用法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
對于分布式鎖的實現(xiàn),除了redis鎖之外,還有很多,像zookeeper,memcache,數(shù)據(jù)庫,chubby等。redis鎖因為使用簡單,所以被大家廣泛使用。
本篇文章主要從以下幾個方面來講解redis鎖:
1.redis鎖使用的時候,有哪些問題2.這些問題會導致什么樣子的后果3.應該如何解決這些問題
一、redis鎖的實現(xiàn)
加鎖命令:
SETNX key value:當鍵不存在時,對鍵進行設置操作并返回成功1,否則返回失敗0。Key是鎖的唯一標識,一般按業(yè)務來決定命名;Value 往往用來比較加鎖的是哪一個線程或者哪一個消息,一般使用UUID.randomUUID().toString()方法生成。例如:setnx(key,1)
解鎖命令:
DEL key通過刪除鍵值對釋放鎖,以便其他線程可以通過 SETNX 命令來獲取鎖。例如:del(key)
鎖超時:
EXPIRE key timeout設置 key 的超時時間,以保證即使鎖沒有被顯式釋放,鎖也可以在一定時間后自動釋放,避免資源被永遠鎖住。例如:expire(key,30),表示30s超時釋放鎖。
備注:
Redis 2.6.12以上版本為set指令增加了可選參數(shù),偽代碼如下:
set(key,1,30,NX),它將加鎖和超時兩個動作合并到了一起,利用原子性封裝了起來。
二、redis鎖解決的具體場景
場景1: 為什么redis鎖需要設置超時?
原因分析:
1.redis與業(yè)務進程之間通常是使用網(wǎng)絡通訊的方式進行數(shù)據(jù)加鎖的,而網(wǎng)絡通訊就存在丟包的情況。
再加上加鎖和解鎖是兩個操作,這樣就會存在鎖永遠不能釋放的問題。
2.除此之外業(yè)務進程在加鎖之后,也可能panic掉,沒有辦法去釋放掉這個鎖,導致分布式鎖被永遠掛住。
基于上面的兩個原因:
分布式鎖就需要一個超時時間來主動釋放這個鎖,防止分布式鎖一直被掛住。
redis分布式鎖的解決辦法,1.通過加鎖和超時兩步操作來解決,不過我們最好使用set(key,1,30,NX)這種原子操作。2.使用setnx和expire兩個操作的話,因為它們不是原子性操作,也會存在上面1和2的問題,進而導致鎖被永遠鎖住,不過也不是沒有辦法,我們可以采用lua腳本在redis上面實現(xiàn)的方式來保證它們的原子性。
場景2: 鎖超時釋放了之后,加鎖的業(yè)務又過來釋放鎖怎么辦?
具體場景,進程1在超時釋放了鎖之后,進程2獲取到了鎖,后來進程1又釋放鎖,如此以來就有可能導致進程2沒有完成就被進程1釋放了鎖。如下所示:
解決上面問題的關鍵點,在于我們在釋放鎖的時候,能夠判斷出來是不是當前加鎖的進程發(fā)起的解鎖操作。
一般是將進程id作為vlaue放到setnx中,在解鎖之前先去判斷一把這個鎖是不是同一個進程的,
是就允許釋放,不是就不允許解鎖。
備注:這種操作其實是兩步操作,判斷鎖,釋放鎖,它們并不是一個原子操作,
如此以來就存在一步操作完成,另一步?jīng)]有被操作的情況。解決辦法是,利用lua腳本實現(xiàn)鎖的原子性。
場景3:鎖超時釋放之后,會不會存在兩個業(yè)務同時處理加鎖的代碼的情況?
這個場景與場景2是一個問題的延伸,一旦我們在設置鎖的超時時間過短,就會發(fā)生這個情況。
鎖在被進程2拿走之后,進程1還沒有執(zhí)行代碼結(jié)束,如此以來就會存在進程1和進程2同時操作那段公共代碼的情況,這樣就會出問題,也顯然不是我們期望的場景。
對于這個場景的解決辦法,往往有兩個:
1.調(diào)整超時時間,讓業(yè)務進程在這段時間之內(nèi)一定可以執(zhí)行完畢。2.啟動守護進程,在業(yè)務進程沒有執(zhí)行完成的時候,主動的去調(diào)節(jié)這個超時時間,讓鎖的超時時間變長。
場景4:鎖被使用之后,其他的業(yè)務如何才能獲取這個分布式鎖?
這個場景,是非?;镜膱鼍埃坏╂i被進程1獲取之后,在釋放鎖之前,進程2是怎么知道何時才能夠獲取到鎖呢?
這個解決辦法有點像操作系統(tǒng)的輪詢和信號量兩種。
1.輪詢的話,就需要進程2不停的去超時加鎖,直到能夠加鎖成功位置,不過這種實現(xiàn)比較耗費服務器資源。2.類似信號量的方法,業(yè)務進程2將加鎖消息進行訂閱操作,而訂閱模塊會維護一個消息隊列,等到鎖釋放之后,便從隊列中取出進程2,告知鎖已經(jīng)釋放的通知。進程2收到通知以后,就可以進行加鎖操作了。
場景5:redis是集群的話,使用redis分布式鎖會不會有問題?
為了保證redis的可用性,往往redis服務器會設置主從,主從服務器中的從服務器在檢測到主服務器掛掉之后,就會重新選舉一個作為主服務器,而redis鎖是操作在主服務器上的。
一旦,發(fā)生下面的現(xiàn)象:
1.主服務器剛剛被進程1加鎖完成,還沒有來得及同步數(shù)據(jù)到從服務器就掛掉了。2.從服務器經(jīng)過選舉,選出了新的主服務器。3.進程2在新的主服務器上加鎖成功。4.如此以來進程1和進程2都會同時操作那段公共代碼,這樣就會存在問題,算是加鎖失敗。
針對這種問題,我們其實沒有太好的辦法,不過還好這種數(shù)據(jù)的概率比較低。
Redis 分布式鎖只能作為一種緩解并發(fā)的手段,要完全解決并發(fā)問題,仍需要數(shù)據(jù)庫的防并發(fā)手段配合使用。
到此,關于“Redis鎖的用法”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。