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

Java分布式鎖由淺入深介紹

 更新時間:2023年03月30日 09:25:51   作者:kazuhura  
這篇文章主要介紹了Java分布式鎖,數(shù)據(jù)庫實現(xiàn)分布式鎖方式比較多,如悲觀鎖(查詢時增加for?update)、樂觀鎖(通過version字段)、增加一個表記錄鎖信息等。因為依賴于數(shù)據(jù)庫,比較好理解,但是也存在一些問題

一、分布式鎖介紹

單機多線程: 在 Java 中,我們通常使用 ReetrantLock 類、synchronized 關(guān)鍵字這類 本地鎖 來控制一個 JVM 進程內(nèi)的多個線程對本地共享資源的訪問

分布式系統(tǒng): 不同的服務(wù)/客戶端通常運行在獨立的 JVM 進程上。如果多個 JVM 進程共享同一份資源的話,使用本地鎖就沒辦法實現(xiàn)資源的互斥訪問了。于是,分布式鎖就誕生了。

舉個例子:系統(tǒng)的訂單服務(wù)一共部署了 3 份,都對外提供服務(wù)。用戶下訂單之前需要檢查庫存,為了防止超賣,這里需要加鎖以實現(xiàn)對檢查庫存操作的同步訪問。由于訂單服務(wù)位于不同的 JVM 進程中,本地鎖在這種情況下就沒辦法正常工作了。我們需要用到分布式鎖,這樣的話,即使多個線程不在同一個 JVM 進程中也能獲取到同一把鎖,進而實現(xiàn)共享資源的互斥訪問。

一個最基本的分布式鎖需要滿足:

  • 互斥 :任意一個時刻,鎖只能被一個線程持有;
  • 高可用 :鎖服務(wù)是高可用的。并且,即使客戶端的釋放鎖的代碼邏輯出現(xiàn)問題,鎖最終一定還是會被釋放,不會影響其他線程對共享資源的訪問。
  • 可重入:一個節(jié)點獲取了鎖之后,還可以再次獲取鎖。

二、基于Redis實現(xiàn)分布式鎖

1. 如何基于 Redis 實現(xiàn)一個最簡易的分布式鎖

不論是本地鎖還是分布式鎖,核心都在于==“互斥”==。

在 Redis 中, SETNX 命令是可以幫助我們實現(xiàn)互斥。SETNX即 SET if Not eXists (對應(yīng) Java 中的 setIfAbsent 方法),如果 key 不存在的話,才會設(shè)置 key 的值。如果 key 已經(jīng)存在, SETNX 啥也不做。

> SETNX lockKey uniqueValue
(integer) 1
> SETNX lockKey uniqueValue
(integer) 0

釋放鎖的話,直接通過 DEL 命令刪除對應(yīng)的 key 即可

> DEL lockKey
(integer) 1

為了防止誤刪到其他的鎖,這里我們建議使用 Lua 腳本通過 key 對應(yīng)的 value(唯一值)來判斷。

選用 Lua 腳本是為了保證解鎖操作的原子性。因為 Redis 在執(zhí)行 Lua 腳本時,可以以原子性的方式執(zhí)行,從而保證了鎖釋放操作的原子性。

// 釋放鎖時,先比較鎖對應(yīng)的 value 值是否相等,避免鎖的誤釋放
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

這是一種最簡易的 Redis 分布式鎖實現(xiàn),實現(xiàn)方式比較簡單,性能也很高效。不過,這種方式實現(xiàn)分布式鎖存在一些問題。就比如應(yīng)用程序遇到一些問題比如釋放鎖的邏輯突然掛掉,可能會導(dǎo)致鎖無法被釋放,進而造成共享資源無法再被其他線程/進程訪問。

2. 為什么要給鎖設(shè)置一個過期時間

主要為了避免鎖無法被釋放

127.0.0.1:6379> SET lockKey uniqueValue EX 3 NX
OK

  • lockKey :加鎖的鎖名;
  • uniqueValue :能夠唯一標示鎖的隨機字符串;
  • NX :只有當(dāng) lockKey 對應(yīng)的 key 值不存在的時候才能 SET 成功;
  • EX :過期時間設(shè)置(秒為單位)EX 3 標示這個鎖有一個 3 秒的自動過期時間。與 EX 對應(yīng)的是 PX(毫秒為單位),這兩個都是過期時間設(shè)置。

一定要保證設(shè)置指定 key 的值和過期時間是一個原子操作!?。?不然的話,依然可能會出現(xiàn)鎖無法被釋放的問題。

這種解決辦法同樣存在漏洞:

  • 如果操作共享資源的時間大于過期時間,就會出現(xiàn)鎖提前過期的問題,進而導(dǎo)致分布式鎖直接失效
  • 如果鎖的超時時間設(shè)置過長,又會影響到性能

3. 如何實現(xiàn)鎖的優(yōu)雅續(xù)期

Redisson 是一個開源的 Java 語言 Redis 客戶端,提供了很多開箱即用的功能,不僅僅包括多種分布式鎖的實現(xiàn)。并且,Redisson 還支持 Redis 單機、Redis Sentinel 、Redis Cluster 等多種部署架構(gòu)。

Redisson 中的分布式鎖自帶自動續(xù)期機制,使用起來非常簡單,原理也比較簡單,其提供了一個專門用來監(jiān)控和續(xù)期鎖的 Watch Dog( 看門狗),如果操作共享資源的線程還未執(zhí)行完成的話,Watch Dog 會不斷地延長鎖的過期時間,進而保證鎖不會因為超時而被釋放。

使用方式舉例:

// 1.獲取指定的分布式鎖對象
RLock lock = redisson.getLock("lock");
// 2.拿鎖且不設(shè)置鎖超時時間,具備 Watch Dog 自動續(xù)期機制
lock.lock();
// 3.執(zhí)行業(yè)務(wù)
...
// 4.釋放鎖
lock.unlock();

只有未指定鎖超時時間,才會使用到 Watch Dog 自動續(xù)期機制。

// 手動給鎖設(shè)置過期時間,不具備 Watch Dog 自動續(xù)期機制
lock.lock(10, TimeUnit.SECONDS);

總的來說就是使用Redisson,它帶有自動的續(xù)期機制

4. 如何實現(xiàn)可重入鎖

所謂可重入鎖指的是在一個線程中可以多次獲取同一把鎖,比如一個線程在執(zhí)行一個帶鎖的方法,該方法中又調(diào)用了另一個需要相同鎖的方法,則該線程可以直接執(zhí)行調(diào)用的方法即可重入 ,而無需重新獲得鎖。像 Java 中的 synchronized 和 ReentrantLock 都屬于可重入鎖。

可重入分布式鎖的實現(xiàn)核心思路是線程在獲取鎖的時候判斷是否為自己的鎖,如果是的話,就不用再重新獲取了。為此,我們可以為每個鎖關(guān)聯(lián)一個可重入計數(shù)器和一個占有它的線程。當(dāng)可重入計數(shù)器大于 0 時,則鎖被占有,需要判斷占有該鎖的線程和請求獲取鎖的線程是否為同一個。

到此這篇關(guān)于Java分布式鎖由淺入深介紹的文章就介紹到這了,更多相關(guān)Java分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Cloud Alibaba Nacos Config加載配置詳解流程

    Spring Cloud Alibaba Nacos Config加載配置詳解流

    這篇文章主要介紹了Spring Cloud Alibaba Nacos Config配置中心實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-07-07
  • SpringBoot詳解shiro過濾器與權(quán)限控制

    SpringBoot詳解shiro過濾器與權(quán)限控制

    當(dāng)shiro被運用到web項目時,shiro會自動創(chuàng)建一些默認的過濾器對客戶端請求進行過濾。比如身份驗證、授權(quán)的相關(guān)的,這篇文章主要介紹了shiro過濾器與權(quán)限控制
    2022-07-07
  • Maven中<distributionManagement>的使用及說明

    Maven中<distributionManagement>的使用及說明

    本文主要介紹了Maven中的SNAPSHOT和RELEASE倉庫的區(qū)別,以及如何在POM文件中配置和使用快照版本,快照版本可以實現(xiàn)實時更新,方便開發(fā)過程中的依賴管理,同時,本文還總結(jié)了Maven的一些常用命令及其作用
    2025-01-01
  • SpringBoot JdbcTemplate批量操作的示例代碼

    SpringBoot JdbcTemplate批量操作的示例代碼

    本篇文章主要介紹了SpringBoot JdbcTemplate批量操作的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • springMVC返回復(fù)雜的json格式數(shù)據(jù)方法

    springMVC返回復(fù)雜的json格式數(shù)據(jù)方法

    下面小編就為大家分享一篇springMVC返回復(fù)雜的json格式數(shù)據(jù)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • 詳解Java 自動裝箱與拆箱的實現(xiàn)原理

    詳解Java 自動裝箱與拆箱的實現(xiàn)原理

    本篇文章主要介紹了詳解Java 自動裝箱與拆箱的實現(xiàn)原理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • Java基礎(chǔ)之位運算知識總結(jié)

    Java基礎(chǔ)之位運算知識總結(jié)

    最近接觸到了java位運算,之前對位運算的了解僅僅停留在表現(xiàn)結(jié)果上,乘2除以2,對背后的原理并不了解,現(xiàn)在學(xué)習(xí)記錄一下,需要的朋友可以參考下
    2021-05-05
  • 分析Spring框架之設(shè)計與實現(xiàn)資源加載器

    分析Spring框架之設(shè)計與實現(xiàn)資源加載器

    Spring框架是由于軟件開發(fā)的復(fù)雜性而創(chuàng)建的。然而,Spring的用途不僅僅限于服務(wù)器端的開發(fā)。從簡單性、可測試性和松耦合性角度而言,絕大部分Java應(yīng)用都可以從Spring中受益。今天來分析它的設(shè)計與實現(xiàn)資源加載器,從Spring.xml解析和注冊Bean對象
    2021-06-06
  • SpringBoot整合sharding-jdbc?實現(xiàn)分庫分表操作的示例代碼

    SpringBoot整合sharding-jdbc?實現(xiàn)分庫分表操作的示例代碼

    在Spring?Boot中使用ShardingSphere的Sharding-JDBC來實現(xiàn)數(shù)據(jù)庫的分庫分表是一個常見的需求,下面就拉具體介紹一下實現(xiàn)步驟,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04

最新評論

承德县| 双牌县| 甘南县| 平遥县| 楚雄市| 望奎县| 恭城| 五莲县| 治多县| 汉源县| 邯郸县| 将乐县| 万宁市| 莫力| 隆化县| 焉耆| 开封市| 始兴县| 綦江县| 夏津县| 淅川县| 修武县| 缙云县| 朝阳区| 汝城县| 枞阳县| 麻江县| 大荔县| 中江县| 甘泉县| 阳信县| 海口市| 朝阳县| 新乡市| 阿鲁科尔沁旗| 杭锦后旗| 科尔| 通许县| 屯昌县| 长顺县| 伊川县|