亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

分布式鎖是一種用于在分布式系統(tǒng)中控制對(duì)共享資源的訪問(wèn)的鎖。它與傳統(tǒng)的單機(jī)鎖不同,因?yàn)樗枰诙鄠€(gè)節(jié)點(diǎn)之間協(xié)調(diào)以確保互斥訪問(wèn)。

本文將介紹什么是分布式鎖,以及使用redis實(shí)現(xiàn)分布式鎖的幾種方案。

前言

了解分布式鎖之前,需要先了解一下

  • 線程鎖
  • 進(jìn)程鎖
  • CAP理論

線程鎖

線程鎖主要用來(lái)給方法、代碼塊加鎖。

當(dāng)某個(gè)方法或代碼使用鎖,在同一時(shí)刻僅有一個(gè)線程執(zhí)行該方法或該代碼段。

線程鎖只在同一JVM中有效果,因?yàn)榫€程鎖的實(shí)現(xiàn),是通過(guò)線程之間共享內(nèi)存實(shí)現(xiàn)的,

一般實(shí)現(xiàn)方法:

  • Synchronized
  • Lock

進(jìn)程鎖

進(jìn)程鎖是控制同一操作系統(tǒng)中多個(gè)進(jìn)程訪問(wèn)某個(gè)共享資源

進(jìn)程具有獨(dú)立性,各個(gè)進(jìn)程無(wú)法訪問(wèn)其他進(jìn)程的資源,因此無(wú)法通過(guò)synchronized等線程鎖實(shí)現(xiàn)進(jìn)程鎖。

CAP理論

任何一個(gè)分布式系統(tǒng)都無(wú)法同時(shí)滿(mǎn)足

  • 一致性(Consistency)
  • 可用性(AvAIlability)
  • 分區(qū)容錯(cuò)性(Partition tolerance)

最多只能同時(shí)滿(mǎn)足兩項(xiàng)。

分布式鎖

概念

如果不同的系統(tǒng)或同一個(gè)系統(tǒng)的不同主機(jī)之間共享了某個(gè)臨界資源,往往需要互斥來(lái)防止彼此干擾,以保證一致性,就產(chǎn)生了分布式鎖。包含三個(gè)要素:

  • 分布式系統(tǒng)
  • 不同進(jìn)程
  • 共同訪問(wèn)共享資源

分布式鎖,實(shí)現(xiàn)的是CA,即一致性可用性

特性

  • 互斥性: 任意時(shí)刻,只有一個(gè)客戶(hù)端能持有鎖。
  • 鎖超時(shí)釋放:持有鎖超時(shí),可以釋放,防止不必要的資源浪費(fèi),也可以防止死鎖。
  • 可重入性:一個(gè)線程如果獲取了鎖之后,可以再次對(duì)其請(qǐng)求加鎖。
  • 高性能和高可用:加鎖和解鎖需要開(kāi)銷(xiāo)盡可能低,同時(shí)也要保證高可用,避免分布式鎖失效。
  • 安全性:鎖只能被持有的客戶(hù)端刪除,不能被其他客戶(hù)端刪除。

實(shí)現(xiàn)方案

Redisson框架

框架介紹

Redisson是一款基于JAVA的Redis客戶(hù)端,它封裝了Redis的Java客戶(hù)端Jedis、Lettuce等,并且提供了許多額外的功能,例如分布式鎖、分布式集合、分布式對(duì)象、布隆過(guò)濾器等。

框架特點(diǎn)

  1. 提供了豐富的API,簡(jiǎn)單易用。
  2. 提供了多種數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn),如分布式鎖、分布式集合、分布式Map、分布式Queue等。
  3. 支持多種Redis部署方式,如單節(jié)點(diǎn)、主從、哨兵、集群等。
  4. 提供了基?.NETty的高性能的Redis連接池。
  5. 提供了基于Ramp模型的分布式遠(yuǎn)程調(diào)用框架,可以方便的進(jìn)行分布式服務(wù)調(diào)用。

簡(jiǎn)單示例

  1. 引入Redisson的依賴(lài)
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.16.0</version>
</dependency>
  1. 創(chuàng)建RedissonClient對(duì)象
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redissonClient = Redisson.create(config);
  1. 使用RedissonClient對(duì)象進(jìn)行數(shù)據(jù)操作
 
// 獲取字符串對(duì)象
RBucket<String> bucket = redissonClient.getBucket("myKey");
bucket.set("myValue");
 
// 獲取Map對(duì)象
RMap<String, String> map = redissonClient.getMap("myMap");
map.put("key1", "value1");
 
// 獲取分布式鎖對(duì)象
RLock lock = redissonClient.getLock("myLock");
lock.lock();
try {
    // do something
} finally {
    lock.unlock();
}

基于SETNX命令實(shí)現(xiàn)

通過(guò)使用Redis中的SETNX命令(即SET if Not eXists),可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的分布式鎖。

SETNX命令是Redis中的一種原子性操作,用于將一個(gè)鍵值對(duì)(key-value)設(shè)置到Redis中,僅在鍵不存在時(shí)才會(huì)設(shè)置成功,否則設(shè)置失敗。利用SETNX命令的特性,可以實(shí)現(xiàn)分布式鎖的機(jī)制,具體步驟如下:

  • 設(shè)置鎖:在Redis中設(shè)置一個(gè)鍵值對(duì),鍵為鎖名稱(chēng),值為一個(gè)隨機(jī)生成的字符串,同時(shí)設(shè)置過(guò)期時(shí)間(防止鎖一直存在,導(dǎo)致死鎖)。可以使用以下Redis命令:
SETNX lock_name random_value
EXPIRE lock_name expire_time
  • 獲取鎖:如果SETNX命令返回1,則說(shuō)明鎖設(shè)置成功,此時(shí)獲取到了鎖;如果返回0,則說(shuō)明鎖已經(jīng)被其他節(jié)點(diǎn)持有,此時(shí)需要等待一段時(shí)間后重試獲取鎖。
  • 釋放鎖:釋放鎖時(shí),需要先判斷當(dāng)前線程持有的鎖是否與之前設(shè)置的鎖名稱(chēng)和值相同,如果相同,則通過(guò)DEL命令刪除該鍵值對(duì),釋放鎖。
if redis.call('get', KEYS[1]) == ARGV[1] then
    return redis.call('del', KEYS[1])
else
    return 0
end

基于RedLock實(shí)現(xiàn)

RedLock是一個(gè)多節(jié)點(diǎn)分布式鎖算法,它基于Redis和一些簡(jiǎn)單的算法來(lái)實(shí)現(xiàn)高可用的分布式鎖。

與傳統(tǒng)的Redis分布式鎖方案相比,RedLock可以更好地應(yīng)對(duì)網(wǎng)絡(luò)故障和硬件故障等異常情況,提高系統(tǒng)的可用性和穩(wěn)定性。

RedLock算法的基本思想是:將鎖的持有和釋放過(guò)程轉(zhuǎn)化為一個(gè)競(jìng)爭(zhēng)資源的問(wèn)題,通過(guò)多節(jié)點(diǎn)協(xié)作的方式來(lái)實(shí)現(xiàn)鎖的分配和釋放。

具體步驟如下:

  1. 對(duì)于要加鎖的資源,計(jì)算出一個(gè)唯一的標(biāo)識(shí)(比如使用hash函數(shù)將資源名稱(chēng)轉(zhuǎn)化為一個(gè)32位整數(shù)),作為鎖的名稱(chēng)。
  2. 獲取多個(gè)Redis節(jié)點(diǎn)的當(dāng)前時(shí)間戳,并計(jì)算出一個(gè)時(shí)鐘偏差(clock drift)。時(shí)鐘偏差可以通過(guò)取多個(gè)Redis節(jié)點(diǎn)的時(shí)間戳的平均值來(lái)計(jì)算。這樣可以避免不同Redis節(jié)點(diǎn)之間的時(shí)間不同步而導(dǎo)致的鎖沖突問(wèn)題。
  3. 獲取鎖:對(duì)于每個(gè)Redis節(jié)點(diǎn),嘗試通過(guò)SET命令獲取鎖。如果獲取鎖成功,則記錄鎖的名稱(chēng)、鎖的值(一個(gè)隨機(jī)字符串)、過(guò)期時(shí)間以及Redis節(jié)點(diǎn)的標(biāo)識(shí)信息(比如IP地址和端口號(hào))。如果獲取鎖失敗,則記錄失敗的節(jié)點(diǎn)信息。
  4. 判斷獲取鎖的結(jié)果:統(tǒng)計(jì)獲取鎖成功的節(jié)點(diǎn)數(shù),并根據(jù)Quorum算法(投票算法)來(lái)判斷是否獲取鎖成功。如果獲取鎖成功的節(jié)點(diǎn)數(shù)大于等于N/2+1(其中N為Redis節(jié)點(diǎn)數(shù)),則表示鎖獲取成功;否則,表示鎖獲取失敗。
  5. 執(zhí)行結(jié)果:如果鎖獲取成功,則執(zhí)行相應(yīng)的業(yè)務(wù)邏輯;如果鎖獲取失敗,則需要嘗試在所有失敗的節(jié)點(diǎn)中找到一個(gè)最新的鎖并釋放它,以避免死鎖問(wèn)題。
  6. 釋放鎖:釋放鎖時(shí),需要根據(jù)鎖的名稱(chēng)和值來(lái)判斷當(dāng)前節(jié)點(diǎn)是否持有該鎖。如果當(dāng)前節(jié)點(diǎn)持有該鎖,則通過(guò)DEL命令刪除該鍵值對(duì),釋放鎖。

需要注意的是,RedLock算法并不能保證絕對(duì)的可用性和正確性,仍然可能存在某些特殊情況下的鎖沖突問(wèn)題。

因此,在實(shí)際應(yīng)用中,需要根據(jù)具體業(yè)務(wù)場(chǎng)景和需求來(lái)選擇適合的分布式鎖方案,并進(jìn)行充分的測(cè)試和優(yōu)化。

基于Lua腳本實(shí)現(xiàn)

在Redis中可以使用Lua腳本來(lái)實(shí)現(xiàn)分布式鎖,其基本思想是通過(guò)原子操作將鎖的獲取和釋放過(guò)程合并為一個(gè)操作,保證鎖的原子性和一致性。

使用Lua腳本可以在Redis中實(shí)現(xiàn)一個(gè)基于SET命令的分布式鎖,具體實(shí)現(xiàn)步驟如下:

  1. 生成一個(gè)隨機(jī)字符串作為鎖的值,以確保不同的客戶(hù)端使用的鎖值不同。
  2. 使用SET命令將鎖名作為key,鎖值作為value,過(guò)期時(shí)間作為expire參數(shù)來(lái)設(shè)置鎖,加上NX(Not eXist)選項(xiàng),只有當(dāng)key不存在時(shí)才設(shè)置成功。
  3. 在Lua腳本中使用eval命令執(zhí)行以下腳本:
if redis.call('set', KEYS[1], ARGV[1], 'NX', 'PX', ARGV[2]) then
    return 1
else
    return 0
end

其中,KEYS[1]表示鎖的名稱(chēng),ARGV[1]表示鎖的值,ARGV[2]表示鎖的過(guò)期時(shí)間。

  1. 結(jié)果:如果eval命令返回1,則表示獲取鎖成功;如果返回0,則表示獲取鎖失敗。
  2. 釋放鎖時(shí),可以使用DEL命令刪除鎖的名稱(chēng)即可。

下面是一個(gè)完整的Lua例子:

if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then
    redis.call('expire', KEYS[1], ARGV[2])
    return 1
else
    return 0
end
 
-- 釋放鎖
if redis.call('get', KEYS[1]) == ARGV[1] then
    return redis.call('del', KEYS[1])
else
    return 0
end

上面的代碼包括兩個(gè)部分:獲取鎖和釋放鎖。

  • 獲取鎖:使用setnx命令來(lái)嘗試獲取鎖。如果獲取成功,則設(shè)置鎖的過(guò)期時(shí)間,并返回1表示獲取鎖成功;否則,返回0表示獲取鎖失敗。
  • 釋放鎖:先通過(guò)get命令獲取鎖的值,判斷當(dāng)前節(jié)點(diǎn)是否持有該鎖。如果持有,則使用del命令刪除該鍵值對(duì)并返回1表示釋放鎖成功;否則,返回0表示釋放鎖失敗。

總結(jié)

上面提到的通過(guò)Redis實(shí)現(xiàn)的分布式鎖幾種方案,在高并發(fā)的情況下,可能存在鎖沖突的問(wèn)題,因此需要根據(jù)實(shí)際業(yè)務(wù)場(chǎng)景來(lái)選擇適合的鎖方案,并進(jìn)行充分的測(cè)試和優(yōu)化。

分享到:
標(biāo)簽:Redis
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定