最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

redis樂(lè)觀鎖與悲觀鎖的實(shí)戰(zhàn)?

 更新時(shí)間:2023年04月13日 08:35:42   作者:不拿博客專家不改名  
Redis提供了兩種鎖機(jī)制,即樂(lè)觀鎖和悲觀鎖。本文主要介紹了redis樂(lè)觀鎖與悲觀鎖的實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

概念

Redis是一個(gè)內(nèi)存中的鍵值存儲(chǔ)系統(tǒng),支持多種數(shù)據(jù)結(jié)構(gòu),如字符串、哈希、列表等。Redis提供了兩種鎖機(jī)制,即樂(lè)觀鎖和悲觀鎖。

樂(lè)觀鎖

樂(lè)觀鎖是一種樂(lè)觀的并發(fā)控制策略,它認(rèn)為數(shù)據(jù)在大多數(shù)情況下不會(huì)被其他線程占用,因此每次需要修改數(shù)據(jù)時(shí),都不會(huì)獲取鎖,而是直接進(jìn)行修改。在Redis中,可以通過(guò)WATCH和CAS命令來(lái)實(shí)現(xiàn)樂(lè)觀鎖,WATCH命令用于監(jiān)視一個(gè)或多個(gè)鍵,CAS命令用于檢查并更新鍵的值。

例如,假設(shè)有一個(gè)計(jì)數(shù)器鍵counter,多個(gè)客戶端都需要對(duì)其進(jìn)行操作。使用樂(lè)觀鎖的方式,可以在每個(gè)客戶端執(zhí)行操作之前,先通過(guò)WATCH命令監(jiān)視counter鍵:

WATCH counter
current_count = GET counter
new_count = current_count + 1
MULTI
SET counter new_count
EXEC

然后,在EXEC命令執(zhí)行之前,使用GET命令再次獲取counter鍵的值,并將其與之前獲取的值進(jìn)行比較。如果值相等,就說(shuō)明期間沒(méi)有其他客戶端對(duì)counter鍵進(jìn)行了修改,此時(shí)可以使用CAS命令將新值設(shè)置到counter鍵中。如果值不相等,則說(shuō)明期間有其他客戶端對(duì)counter鍵進(jìn)行了修改,需要重新執(zhí)行操作。

GET counter

悲觀鎖

悲觀鎖是一種悲觀的并發(fā)控制策略,它認(rèn)為數(shù)據(jù)在大多數(shù)情況下都會(huì)被其他線程占用,因此每次需要修改數(shù)據(jù)時(shí),都會(huì)先獲取鎖,確保在修改期間沒(méi)有其他線程可以訪問(wèn)該數(shù)據(jù)。在Redis中,可以通過(guò)WATCH命令來(lái)實(shí)現(xiàn)悲觀鎖,該命令可以監(jiān)視一個(gè)或多個(gè)鍵,如果在事務(wù)執(zhí)行期間有任何被監(jiān)視鍵的值發(fā)生了變化,整個(gè)事務(wù)會(huì)被回滾。

還是上文的例子

WATCH counter
current_count = GET counter
new_count = current_count + 1
MULTI
SET counter new_count
EXEC

如果在執(zhí)行事務(wù)期間,有其他客戶端修改了counter鍵,那么整個(gè)事務(wù)會(huì)被回滾,需要重新執(zhí)行。

悲觀鎖的優(yōu)點(diǎn)在于它可以確保數(shù)據(jù)的一致性,但缺點(diǎn)在于它需要獲取鎖,可能會(huì)引起線程的阻塞,影響并發(fā)性能。

樂(lè)觀鎖示例

假設(shè)有一個(gè)電商平臺(tái),用戶可以在平臺(tái)上購(gòu)買(mǎi)商品。為了保證數(shù)據(jù)的一致性,我們可以使用Redis的樂(lè)觀鎖來(lái)實(shí)現(xiàn)商品庫(kù)存的扣減。

首先,我們需要在Redis中保存每個(gè)商品的庫(kù)存信息,使用hash數(shù)據(jù)結(jié)構(gòu)來(lái)保存,例如:

然后,在業(yè)務(wù)邏輯中,當(dāng)用戶購(gòu)買(mǎi)一個(gè)商品時(shí),需要執(zhí)行以下步驟:

  • 使用WATCH命令監(jiān)視商品庫(kù)存鍵,例如stock:sku001;
  • 使用GET命令獲取當(dāng)前商品庫(kù)存數(shù)量;
  • 檢查商品庫(kù)存是否足夠,如果不足,直接返回錯(cuò)誤信息;
  • 計(jì)算新的庫(kù)存數(shù)量,并使用MULTI命令開(kāi)啟一個(gè)事務(wù);
  • 使用HSET命令將新的庫(kù)存數(shù)量保存到Redis中;
  • 執(zhí)行事務(wù),如果在執(zhí)行期間有其他客戶端修改了商品庫(kù)存,會(huì)回滾事務(wù),需要重新執(zhí)行。

下面是使用Spring Boot實(shí)現(xiàn)的示例代碼:

@Service
public class OrderService {
? ? private final RedisTemplate<String, Integer> redisTemplate;

? ? @Autowired
? ? public OrderService(RedisTemplate<String, Integer> redisTemplate) {
? ? ? ? this.redisTemplate = redisTemplate;
? ? }

? ? public void placeOrder(String sku, int quantity) {
? ? ? ? String stockKey = "stock:" + sku;
? ? ? ? while (true) {
? ? ? ? ? ? // 監(jiān)視商品庫(kù)存鍵,以便在事務(wù)開(kāi)始前檢測(cè)是否有其他客戶端修改了庫(kù)存
? ? ? ? ? ? redisTemplate.watch(stockKey);
? ? ? ? ? ? // 獲取當(dāng)前庫(kù)存數(shù)量
? ? ? ? ? ? int currentStock = redisTemplate.opsForHash().get(stockKey, sku);
? ? ? ? ? ? // 檢查庫(kù)存是否足夠
? ? ? ? ? ? if (currentStock < quantity) {
? ? ? ? ? ? ? ? // 庫(kù)存不足,放棄事務(wù)并拋出異常
? ? ? ? ? ? ? ? redisTemplate.unwatch();
? ? ? ? ? ? ? ? throw new RuntimeException("Out of stock");
? ? ? ? ? ? }
? ? ? ? ? ? // 計(jì)算新的庫(kù)存數(shù)量
? ? ? ? ? ? int newStock = currentStock - quantity;
? ? ? ? ? ? // 開(kāi)始事務(wù)
? ? ? ? ? ? redisTemplate.multi();
? ? ? ? ? ? // 更新庫(kù)存數(shù)量
? ? ? ? ? ? redisTemplate.opsForHash().put(stockKey, sku, newStock);
? ? ? ? ? ? // 提交事務(wù)
? ? ? ? ? ? List<Object> results = redisTemplate.exec();
? ? ? ? ? ? // 如果事務(wù)執(zhí)行成功,則退出循環(huán)
? ? ? ? ? ? if (results != null) {
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? // 如果事務(wù)執(zhí)行失敗,則重試
? ? ? ? }
? ? }
}

在上面的代碼中,我們使用RedisTemplate來(lái)操作Redis,其中watch方法用于監(jiān)視商品庫(kù)存鍵,opsForHash方法用于獲取和修改商品庫(kù)存的值,multi和exec方法用于開(kāi)啟和提交事務(wù)。

悲觀鎖示例

除了樂(lè)觀鎖,Redis還支持悲觀鎖,可以通過(guò)設(shè)置NX(Not Exist)或XX(Exist)標(biāo)志來(lái)實(shí)現(xiàn)。例如,當(dāng)NX標(biāo)志設(shè)置為true時(shí),如果鎖不存在,會(huì)返回OK,并創(chuàng)建一個(gè)鎖;如果鎖已經(jīng)存在,會(huì)返回null,表示獲取鎖失敗。反之,當(dāng)XX標(biāo)志設(shè)置為true時(shí),如果鎖已經(jīng)存在,會(huì)返回OK,表示獲取鎖成功;如果鎖不存在,會(huì)返回null,表示獲取鎖失敗。

下面是使用Spring Boot實(shí)現(xiàn)的悲觀鎖示例代碼:

@Service
public class OrderService {
? ? private final RedisTemplate<String, String> redisTemplate;

? ? @Autowired
? ? public OrderService(RedisTemplate<String, String> redisTemplate) {
? ? ? ? this.redisTemplate = redisTemplate;
? ? }

? ? public void placeOrder(String sku, int quantity) {
? ? ? ? String lockKey = "lock:" + sku;
? ? ? ? // 嘗試獲取鎖,如果鎖已經(jīng)存在,說(shuō)明有其他線程正在執(zhí)行相關(guān)操作
? ? ? ? Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "locked");
? ? ? ? if (!locked) {
? ? ? ? ? ? // 獲取鎖失敗,拋出異常
? ? ? ? ? ? throw new RuntimeException("Unable to acquire lock");
? ? ? ? }
? ? ? ? // 設(shè)置鎖的過(guò)期時(shí)間,防止鎖被一直占用
? ? ? ? redisTemplate.expire(lockKey, 10, TimeUnit.SECONDS);
? ? ? ? try {
? ? ? ? ? ? // 執(zhí)行訂單創(chuàng)建、扣減庫(kù)存等操作
? ? ? ? } finally {
? ? ? ? ? ? // 釋放鎖
? ? ? ? ? ? redisTemplate.delete(lockKey);
? ? ? ? }
? ? }
}

在上面的代碼中,我們使用setIfAbsent方法來(lái)嘗試獲取鎖,如果鎖已經(jīng)存在,說(shuō)明其他線程正在執(zhí)行相關(guān)操作,此時(shí)會(huì)返回false,表示獲取鎖失敗;否則,會(huì)返回true,表示獲取鎖成功。如果獲取鎖成功,我們會(huì)設(shè)置鎖的過(guò)期時(shí)間,并執(zhí)行相關(guān)操作,最后釋放鎖。

總結(jié)提升

需要注意的是,悲觀鎖一般適用于并發(fā)量不大的場(chǎng)景,如果并發(fā)量較高,容易導(dǎo)致性能問(wèn)題。因此,在實(shí)際應(yīng)用中,需要根據(jù)具體情況選擇合適的鎖策略。

到此這篇關(guān)于redis樂(lè)觀鎖與悲觀鎖的實(shí)戰(zhàn) 的文章就介紹到這了,更多相關(guān)redis樂(lè)觀鎖與悲觀鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis教程(十五):C語(yǔ)言連接操作代碼實(shí)例

    Redis教程(十五):C語(yǔ)言連接操作代碼實(shí)例

    這篇文章主要介紹了Redis教程(十五):C語(yǔ)言連接操作代碼實(shí)例,本篇博客是該系列博客中的最后一篇,在這里將給出基于Redis客戶端組件訪問(wèn)并操作Redis服務(wù)器的代碼示例,需要的朋友可以參考下
    2015-05-05
  • 解決redis sentinel 頻繁主備切換的問(wèn)題

    解決redis sentinel 頻繁主備切換的問(wèn)題

    這篇文章主要介紹了解決redis sentinel 頻繁主備切換的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • 詳解redis集群選舉機(jī)制

    詳解redis集群選舉機(jī)制

    這篇文章主要介紹了詳解redis集群選舉機(jī)制,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • redis批量操作pipeline管道操作方法

    redis批量操作pipeline管道操作方法

    Redis本身是基于一個(gè)Request一個(gè)Response方式的同步請(qǐng)求,正常情況下,客戶端發(fā)送一個(gè)命令,這篇文章主要介紹了redis批量操作pipeline管道,需要的朋友可以參考下
    2022-09-09
  • Redis 刪除策略的三種實(shí)現(xiàn)

    Redis 刪除策略的三種實(shí)現(xiàn)

    本文主要介紹了Redis 刪除策略的三種實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 解決 Redis 數(shù)據(jù)傾斜、熱點(diǎn)等問(wèn)題

    解決 Redis 數(shù)據(jù)傾斜、熱點(diǎn)等問(wèn)題

    ?單臺(tái)機(jī)器的硬件配置有上限制約,一般我們會(huì)采用分布式架構(gòu)將多臺(tái)機(jī)器組成一個(gè)集群,這篇文章主要介紹了解決 Redis 數(shù)據(jù)傾斜、熱點(diǎn)等問(wèn)題,需要的朋友可以參考下
    2022-12-12
  • Redis進(jìn)行相關(guān)優(yōu)化詳解

    Redis進(jìn)行相關(guān)優(yōu)化詳解

    這篇文章主要介紹了Redis進(jìn)行相關(guān)優(yōu)化,Redis在項(xiàng)目中進(jìn)行廣泛使用,那么在日常的開(kāi)發(fā)過(guò)程中,我們?cè)谑褂肦edis的過(guò)程中需要注意那些呢?本文將從三個(gè)維度來(lái)講解如何進(jìn)行Redis的優(yōu)化
    2022-08-08
  • 在ssm項(xiàng)目中使用redis緩存查詢數(shù)據(jù)的方法

    在ssm項(xiàng)目中使用redis緩存查詢數(shù)據(jù)的方法

    本文主要簡(jiǎn)單的使用Java代碼進(jìn)行redis緩存,即在查詢的時(shí)候先在service層從redis緩存中獲取數(shù)據(jù)。如果大家對(duì)在ssm項(xiàng)目中使用redis緩存查詢數(shù)據(jù)的相關(guān)知識(shí)感興趣的朋友跟隨腳本之家小編一起看看吧
    2018-03-03
  • 全網(wǎng)最完整的Redis新手入門(mén)指導(dǎo)教程

    全網(wǎng)最完整的Redis新手入門(mén)指導(dǎo)教程

    這篇文章主要給大家介紹了Redis新手入門(mén)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Redis數(shù)據(jù)結(jié)構(gòu)之跳躍表使用學(xué)習(xí)

    Redis數(shù)據(jù)結(jié)構(gòu)之跳躍表使用學(xué)習(xí)

    這篇文章主要為大家介紹了Redis數(shù)據(jù)結(jié)構(gòu)之跳躍表使用學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07

最新評(píng)論

栖霞市| 五原县| 棋牌| 从化市| 佛山市| 饶阳县| 图木舒克市| 扶绥县| 离岛区| 化州市| 吴桥县| 泸溪县| 阳信县| 盐山县| 临沂市| 垦利县| 丽水市| 彰化市| 鄂托克前旗| 泰兴市| 黔西| 奉新县| 凤庆县| 台东县| 肇源县| 长白| 五莲县| 浏阳市| 武隆县| 太原市| 寻乌县| 白玉县| 湄潭县| 高州市| 深圳市| 桂平市| 平阴县| 宜兰县| 万全县| 汉中市| 淄博市|