成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官:如何用 Redis 實(shí)現(xiàn)分布式鎖?

數(shù)據(jù)庫
Redis 本身可以被多個(gè)客戶端共享訪問,正好就是一個(gè)共享存儲(chǔ)系統(tǒng),可以用來保存分布式鎖,而且 Redis 的讀寫性能高,可以應(yīng)對高并發(fā)的鎖操作場景。

今天跟大家聊聊兩個(gè)問題:

  • 如何用 Redis 實(shí)現(xiàn)分布式鎖?
  • Redis 是如何解決集群情況下分布式鎖的可靠性問題的?

如何用 Redis 實(shí)現(xiàn)分布式鎖的?

分布式鎖是用于分布式環(huán)境下并發(fā)控制的一種機(jī)制,用于控制某個(gè)資源在同一時(shí)刻只能被一個(gè)應(yīng)用所使用。如下圖所示:

Redis 本身可以被多個(gè)客戶端共享訪問,正好就是一個(gè)共享存儲(chǔ)系統(tǒng),可以用來保存分布式鎖,而且 Redis 的讀寫性能高,可以應(yīng)對高并發(fā)的鎖操作場景。

Redis 的 SET 命令有個(gè) NX 參數(shù)可以實(shí)現(xiàn)「key不存在才插入」,所以可以用它來實(shí)現(xiàn)分布式鎖:

  • 如果 key 不存在,則顯示插入成功,可以用來表示加鎖成功;
  • 如果 key 存在,則會(huì)顯示插入失敗,可以用來表示加鎖失敗。

基于 Redis 節(jié)點(diǎn)實(shí)現(xiàn)分布式鎖時(shí),對于加鎖操作,我們需要滿足三個(gè)條件。

  • 加鎖包括了讀取鎖變量、檢查鎖變量值和設(shè)置鎖變量值三個(gè)操作,但需要以原子操作的方式完成,所以,我們使用 SET 命令帶上 NX 選項(xiàng)來實(shí)現(xiàn)加鎖;
  • 鎖變量需要設(shè)置過期時(shí)間,以免客戶端拿到鎖后發(fā)生異常,導(dǎo)致鎖一直無法釋放,所以,我們在 SET 命令執(zhí)行時(shí)加上 EX/PX 選項(xiàng),設(shè)置其過期時(shí)間;
  • 鎖變量的值需要能區(qū)分來自不同客戶端的加鎖操作,以免在釋放鎖時(shí),出現(xiàn)誤釋放操作,所以,我們使用 SET 命令設(shè)置鎖變量值時(shí),每個(gè)客戶端設(shè)置的值是一個(gè)唯一值,用于標(biāo)識(shí)客戶端;

滿足這三個(gè)條件的分布式命令如下:

SET lock_key unique_value NX PX 10000
  • lock_key 就是 key 鍵;
  • unique_value 是客戶端生成的唯一的標(biāo)識(shí),區(qū)分來自不同客戶端的鎖操作;
  • NX 代表只在 lock_key 不存在時(shí),才對 lock_key 進(jìn)行設(shè)置操作;
  • PX 10000 表示設(shè)置 lock_key 的過期時(shí)間為 10s,這是為了避免客戶端發(fā)生異常而無法釋放鎖。

而解鎖的過程就是將 lock_key 鍵刪除(del lock_key),但不能亂刪,要保證執(zhí)行操作的客戶端就是加鎖的客戶端。所以,解鎖的時(shí)候,我們要先判斷鎖的 unique_value 是否為加鎖客戶端,是的話,才將 lock_key 鍵刪除。

可以看到,解鎖是有兩個(gè)操作,這時(shí)就需要 Lua 腳本來保證解鎖的原子性,因?yàn)?Redis 在執(zhí)行 Lua 腳本時(shí),可以以原子性的方式執(zhí)行,保證了鎖釋放操作的原子性。

// 釋放鎖時(shí),先比較 unique_value 是否相等,避免鎖的誤釋放
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end

這樣一來,就通過使用 SET 命令和 Lua 腳本在 Redis 單節(jié)點(diǎn)上完成了分布式鎖的加鎖和解鎖。

  • 基于 Redis 實(shí)現(xiàn)分布式鎖有什么優(yōu)缺點(diǎn)?

基于 Redis 實(shí)現(xiàn)分布式鎖的優(yōu)點(diǎn):

  1. 性能高效(這是選擇緩存實(shí)現(xiàn)分布式鎖最核心的出發(fā)點(diǎn))。
  2. 實(shí)現(xiàn)方便。很多研發(fā)工程師選擇使用 Redis 來實(shí)現(xiàn)分布式鎖,很大成分上是因?yàn)?Redis 提供了 setnx 方法,實(shí)現(xiàn)分布式鎖很方便。
  3. 避免單點(diǎn)故障(因?yàn)?Redis 是跨集群部署的,自然就避免了單點(diǎn)故障)。

基于 Redis 實(shí)現(xiàn)分布式鎖的缺點(diǎn):

  • 超時(shí)時(shí)間不好設(shè)置。如果鎖的超時(shí)時(shí)間設(shè)置過長,會(huì)影響性能,如果設(shè)置的超時(shí)時(shí)間過短會(huì)保護(hù)不到共享資源。比如在有些場景中,一個(gè)線程 A 獲取到了鎖之后,由于業(yè)務(wù)代碼執(zhí)行時(shí)間可能比較長,導(dǎo)致超過了鎖的超時(shí)時(shí)間,自動(dòng)失效,注意 A 線程沒執(zhí)行完,后續(xù)線程 B 又意外的持有了鎖,意味著可以操作共享資源,那么兩個(gè)線程之間的共享資源就沒辦法進(jìn)行保護(hù)了。
  • 那么如何合理設(shè)置超時(shí)時(shí)間呢? 我們可以基于續(xù)約的方式設(shè)置超時(shí)時(shí)間:先給鎖設(shè)置一個(gè)超時(shí)時(shí)間,然后啟動(dòng)一個(gè)守護(hù)線程,讓守護(hù)線程在一段時(shí)間后,重新設(shè)置這個(gè)鎖的超時(shí)時(shí)間。實(shí)現(xiàn)方式就是:寫一個(gè)守護(hù)線程,然后去判斷鎖的情況,當(dāng)鎖快失效的時(shí)候,再次進(jìn)行續(xù)約加鎖,當(dāng)主線程執(zhí)行完成后,銷毀續(xù)約鎖即可,不過這種方式實(shí)現(xiàn)起來相對復(fù)雜。
  • Redis 主從復(fù)制模式中的數(shù)據(jù)是異步復(fù)制的,這樣導(dǎo)致分布式鎖的不可靠性。如果在 Redis 主節(jié)點(diǎn)獲取到鎖后,在沒有同步到其他節(jié)點(diǎn)時(shí),Redis 主節(jié)點(diǎn)宕機(jī)了,此時(shí)新的 Redis 主節(jié)點(diǎn)依然可以獲取鎖,所以多個(gè)應(yīng)用服務(wù)就可以同時(shí)獲取到鎖。

Redis 如何解決集群情況下分布式鎖的可靠性?

為了保證集群環(huán)境下分布式鎖的可靠性,Redis 官方已經(jīng)設(shè)計(jì)了一個(gè)分布式鎖算法 Redlock(紅鎖)。

它是基于多個(gè) Redis 節(jié)點(diǎn)的分布式鎖,即使有節(jié)點(diǎn)發(fā)生了故障,鎖變量仍然是存在的,客戶端還是可以完成鎖操作。

Redlock 算法的基本思路,是讓客戶端和多個(gè)獨(dú)立的 Redis 節(jié)點(diǎn)依次請求申請加鎖,如果客戶端能夠和半數(shù)以上的節(jié)點(diǎn)成功地完成加鎖操作,那么我們就認(rèn)為,客戶端成功地獲得分布式鎖,否則加鎖失敗。

這樣一來,即使有某個(gè) Redis 節(jié)點(diǎn)發(fā)生故障,因?yàn)殒i的數(shù)據(jù)在其他節(jié)點(diǎn)上也有保存,所以客戶端仍然可以正常地進(jìn)行鎖操作,鎖的數(shù)據(jù)也不會(huì)丟失。

Redlock 算法加鎖三個(gè)過程:

  • 第一步是,客戶端獲取當(dāng)前時(shí)間。
  • 第二步是,客戶端按順序依次向 N 個(gè) Redis 節(jié)點(diǎn)執(zhí)行加鎖操作:
  • 加鎖操作使用 SET 命令,帶上 NX,EX/PX 選項(xiàng),以及帶上客戶端的唯一標(biāo)識(shí)。
  • 如果某個(gè) Redis 節(jié)點(diǎn)發(fā)生故障了,為了保證在這種情況下,Redlock 算法能夠繼續(xù)運(yùn)行,我們需要給「加鎖操作」設(shè)置一個(gè)超時(shí)時(shí)間(不是對「鎖」設(shè)置超時(shí)時(shí)間,而是對「加鎖操作」設(shè)置超時(shí)時(shí)間)。
  • 第三步是,一旦客戶端完成了和所有 Redis 節(jié)點(diǎn)的加鎖操作,客戶端就要計(jì)算整個(gè)加鎖過程的總耗時(shí)(t1)。

加鎖成功要同時(shí)滿足兩個(gè)條件(簡述:如果有超過半數(shù)的 Redis 節(jié)點(diǎn)成功的獲取到了鎖,并且總耗時(shí)沒有超過鎖的有效時(shí)間,那么就是加鎖成功):

  • 條件一:客戶端從超過半數(shù)(大于等于 N/2+1)的 Redis 節(jié)點(diǎn)上成功獲取到了鎖;
  • 條件二:客戶端獲取鎖的總耗時(shí)(t1)沒有超過鎖的有效時(shí)間。

加鎖成功后,客戶端需要重新計(jì)算這把鎖的有效時(shí)間,計(jì)算的結(jié)果是「鎖的最初有效時(shí)間」減去「客戶端為獲取鎖的總耗時(shí)(t1)」。

加鎖失敗后,客戶端向所有 Redis 節(jié)點(diǎn)發(fā)起釋放鎖的操作,釋放鎖的操作和在單節(jié)點(diǎn)上釋放鎖的操作一樣,只要執(zhí)行釋放鎖的 Lua 腳本就可以了。

責(zé)任編輯:龐桂玉 來源: 數(shù)據(jù)庫開發(fā)
相關(guān)推薦

2024-09-24 16:30:46

分布式鎖Redis數(shù)據(jù)中間件

2023-08-21 19:10:34

Redis分布式

2020-09-27 06:52:22

分布式存儲(chǔ)服務(wù)器

2024-10-07 10:07:31

2024-04-01 05:10:00

Redis數(shù)據(jù)庫分布式鎖

2023-01-12 08:24:45

ZookeeperZK服務(wù)器

2021-06-03 08:55:54

分布式事務(wù)ACID

2022-01-06 10:58:07

Redis數(shù)據(jù)分布式鎖

2019-02-26 09:51:52

分布式鎖RedisZookeeper

2019-06-19 15:40:06

分布式鎖RedisJava

2020-07-09 13:30:03

RedisJava分布式鎖

2024-04-09 10:40:04

2024-10-22 16:39:07

2024-06-26 11:55:44

2024-01-02 13:15:00

分布式鎖RedissonRedis

2021-11-01 12:25:56

Redis分布式

2020-07-30 09:35:09

Redis分布式鎖數(shù)據(jù)庫

2020-07-15 16:50:57

Spring BootRedisJava

2023-03-01 08:07:51

2024-07-19 08:14:21

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 黄色网址大全在线观看 | 91视频在线| 天天拍天天草 | 激情av免费看 | 欧美精品一区二区在线观看 | 黄色毛片大全 | 欧美一二三四成人免费视频 | 国产精品中文字幕在线 | 亚洲品质自拍视频 | 国产精品爱久久久久久久 | 国产一区二区在线播放视频 | 九九色综合 | 国产精品欧美一区二区三区不卡 | 91影视 | 美日韩一区二区 | 性高朝久久久久久久3小时 av一区二区三区四区 | 99久久精品国产一区二区三区 | 欧美中文字幕在线 | 午夜视频在线免费观看 | 精品在线一区 | 一区二区国产精品 | 国产亚洲一区二区三区 | 99这里只有精品 | 久久久久国产精品一区 | 精品国产亚洲一区二区三区大结局 | 99视频精品 | 国产在线精品一区二区 | 亚洲在线| 成人在线播放 | 午夜影院操 | 精品久久久久香蕉网 | 欧美精品一 | 福利精品在线观看 | 亚洲精久 | 精品久久久久久久 | 欧美精品一区二区三区在线 | 婷婷国产一区 | 亚洲精品一 | 亚洲高清久久 | 国产精品69av | 欧美福利在线 |