国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

一個(gè)注解解決分布式鎖和接口冪等性,springboot 實(shí)戰(zhàn) 。強(qiáng)到離大譜

這篇具有很好參考價(jià)值的文章主要介紹了一個(gè)注解解決分布式鎖和接口冪等性,springboot 實(shí)戰(zhàn) 。強(qiáng)到離大譜。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

如今基本上都是分布式、多節(jié)點(diǎn)時(shí)代,我們業(yè)務(wù)代碼中避免不了需要使用分布式鎖。admin4j-lock
為我們提供分布式鎖解決方案。支持redissonzookeeper分布式鎖

功能

  • 支持redisson分布式鎖和zookeeper 分布式鎖

  • 支持可重入鎖

  • 支持讀寫(xiě)鎖

  • 支持紅鎖 redLock

  • 支持一個(gè)注解解決分布式鎖問(wèn)題

  • 支持一個(gè)注解解決接口冪等性問(wèn)題

  • 支持編程式使用分布式鎖

  • 鎖名稱支持 el表達(dá)式

使用方式

引入POM, 默認(rèn)使用redisson分布式鎖

<dependency>
    <groupId>com.admin4j</groupId>
    <artifactId>lock-spring-boot-starter</artifactId>
    <version>0.2.0</version>
</dependency>

最新版查看 https://central.sonatype.com/artifact/com.admin4j/lock-spring-boot-starter/

注解方式使用

 	@DistributedLock(value = "'testDLock:'+#id", user = true)
    public R testDLock(String name, Integer id) throws InterruptedException {

        Thread.sleep(30000);
        return R.ok();
    }

DistributedLock 注解參數(shù)詳解

  • prefix:鎖key的前綴
  • lockModel:指定鎖模式 REENTRANT(可重入鎖),FAIR(公平鎖) ,REDLOCK(紅鎖),READ(讀鎖), WRITE(寫(xiě)鎖)
  • key、value: 鎖名稱,支持el 表達(dá)式
  • keyGenerator: 所名稱生成器。Spring注入基礎(chǔ)DLockKeyGenerator實(shí)現(xiàn)類即可
  • tryLock:是否嘗試獲取鎖。成功獲取則進(jìn)入鎖;獲取失敗則拋出異常。 true 獲取不到鎖,會(huì)立即返回,不會(huì)阻塞。false(默認(rèn))
    獲取不到鎖,會(huì)阻塞當(dāng)前線程
  • tenant: 是否開(kāi)啟租戶(默認(rèn)false)。開(kāi)啟租戶會(huì)在可能后面拼接上租戶。 需要實(shí)現(xiàn) ILoginUserInfoService 接口告訴當(dāng)前登錄用戶的租戶信息
  • user:是否開(kāi)啟用戶(默認(rèn)false)開(kāi)啟用戶模式 需要實(shí)現(xiàn) ILoginUserInfoService 接口告訴當(dāng)前登錄用戶的唯一ID標(biāo)識(shí)
  • executor: 分布式鎖執(zhí)行器。指定使用 redisson 還是 zookeeper 分布式鎖

編程式使用

//使用工具類
 DistributedLockUtil.tryLockWithError("DistributedLock:" + id, () -> {
            System.out.println("i get the lock   = " + name);
           //doSomething
        });

使用zookeeper 分布式鎖

        <dependency>
            <groupId>com.admin4j</groupId>
            <artifactId>lock-spring-boot-starter</artifactId>
            <version>0.2.0</version>
            <exclusions>
                <exclusion>
                    <artifactId>lock-redisson-spring-boot-starter</artifactId>
                    <groupId>com.admin4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.admin4j</groupId>
            <artifactId>lock-zookeeper-spring-boot-starter</artifactId>
            <version>0.2.0</version>
        </dependency>

引入lock-zookeeper-spring-boot-starter 依賴,默認(rèn)使用zookeeper分布式鎖

指定分布式鎖執(zhí)行器

同時(shí)引入 zookeeper 和 redisson 。默認(rèn)使用redisson,可以指定 executor 執(zhí)行器來(lái)切換分布式類型

        <dependency>
            <groupId>com.admin4j</groupId>
            <artifactId>lock-spring-boot-starter</artifactId>
            <version>0.2.0</version>
            <exclusions>
                <exclusion>
                    <artifactId>lock-redisson-spring-boot-starter</artifactId>
                    <groupId>com.admin4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.admin4j</groupId>
            <artifactId>lock-zookeeper-spring-boot-starter</artifactId>
            <version>0.2.0</version>
        </dependency>

指定 zookeeper分布式鎖 例子:

    @DistributedLock( value = "'testDLock:'+#id", user = true, executor = ZookeeperLockExecutor.class)
    public R testDLock(String name, Integer id) throws InterruptedException {

        Thread.sleep(30000);
        return R.ok();
    }

指定 redisson分布式鎖 例子:

    @DistributedLock( value = "'testDLock:'+#id", user = true, executor = RedissonLockExecutor.class)
    public R testDLock(String name, Integer id) throws InterruptedException {

        Thread.sleep(30000);
        return R.ok();
    }

使用示例代碼 https://github.com/admin4j/admin4j-example

一個(gè)注解搞定接口冪等性

	@GetMapping("Idempotent")
    @Idempotent(tryLock = true, key = "'Idempotent'+#id")
    public R Idempotent(String name, Integer id) throws InterruptedException {

        Thread.sleep(30000);
        return R.ok();
    }

需要實(shí)現(xiàn) ILoginUserInfoService 接口,返回當(dāng)前登錄用戶唯一ID

分布式鎖原理

1. redis 原生命令的不足

使用redis做分布式鎖相對(duì)于更簡(jiǎn)單和高效。但不是說(shuō)用了redis分布式鎖,就可以高枕無(wú)憂了,如果沒(méi)有用好或者用對(duì),也會(huì)引來(lái)一些意想不到的坑。

1.1 非原子性操作
if (jedis.setnx(lockKey, val) == 1) {
   jedis.expire(lockKey, timeout);
}

改進(jìn)方式使用

String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
if ("OK".equals(result)) {
    return true;
}
return false;
1.2 釋放了別人的鎖

假如線程A和線程B,都使用lockKey加鎖。線程A加鎖成功了,但是由于業(yè)務(wù)功能耗時(shí)時(shí)間很長(zhǎng),超過(guò)了設(shè)置的超時(shí)時(shí)間。這時(shí)候,redis會(huì)自動(dòng)釋放lockKey鎖。此時(shí),線程B就能給lockKey加鎖成功了,接下來(lái)執(zhí)行它的業(yè)務(wù)操作。恰好這個(gè)時(shí)候,線程A執(zhí)行完了業(yè)務(wù)功能,接下來(lái),在finally方法中釋放了鎖lockKey。這不就出問(wèn)題了,線程B的鎖,被線程A釋放了。不知道你們注意到?jīng)]?在使用set
命令加鎖時(shí),除了使用lockKey鎖標(biāo)識(shí),還多設(shè)置了一個(gè)參數(shù):requestId,為什么要需要記錄requestId呢?

答:requestId是在釋放鎖的時(shí)候用的。

在釋放鎖的時(shí)候,先獲取到該鎖的值(之前設(shè)置值就是requestId),然后判斷跟之前設(shè)置的值是否相同,如果相同才允許刪除鎖,返回成功。如果不同,則直接返回失敗。

此外,使用lua腳本,也能解決釋放了別人的鎖的問(wèn)題:

if redis.call('get', KEYS[1]) == ARGV[1] then 
 return redis.call('del', KEYS[1]) 
else 
  return 0 
end
1.3 搶不到鎖的線程不會(huì)阻塞,大量失敗請(qǐng)求

當(dāng)大量請(qǐng)求進(jìn)入時(shí),只有一個(gè)會(huì)成功,其他的都是失敗。每1萬(wàn)個(gè)請(qǐng)求,有1個(gè)成功。再1萬(wàn)個(gè)請(qǐng)求,有1個(gè)成功。如此下去,直到庫(kù)存不足。這就變成均勻分布的秒殺了,跟我們想象中的不一樣。

1.4 不支持鎖重入問(wèn)題
1.5 鎖競(jìng)爭(zhēng)問(wèn)題,不支持讀寫(xiě)鎖,鎖顆粒度大

如果有大量需要寫(xiě)入數(shù)據(jù)的業(yè)務(wù)場(chǎng)景,使用普通的redis分布式鎖是沒(méi)有問(wèn)題的。

但如果有些業(yè)務(wù)場(chǎng)景,寫(xiě)入的操作比較少,反而有大量讀取的操作。這樣直接使用普通的redis分布式鎖,會(huì)不會(huì)有點(diǎn)浪費(fèi)性能?

我們都知道,鎖的粒度越粗,多個(gè)線程搶鎖時(shí)競(jìng)爭(zhēng)就越激烈,造成多個(gè)線程鎖等待的時(shí)間也就越長(zhǎng),性能也就越差。

所以,提升redis分布式鎖性能的第一步,就是要把鎖的粒度變細(xì)。添加讀寫(xiě)鎖

1.6 鎖超時(shí)問(wèn)題

如果線程A加鎖成功了,但是由于業(yè)務(wù)功能耗時(shí)時(shí)間很長(zhǎng),超過(guò)了設(shè)置的超時(shí)時(shí)間,這時(shí)候redis會(huì)自動(dòng)釋放線程A加的鎖。其他線程就會(huì)搶到鎖,但是A線程還未結(jié)束

1.7 主從復(fù)制的問(wèn)題

如果redis存在多個(gè)實(shí)例。比如:做了主從,或者使用了哨兵模式,由于redis 主從復(fù)制是異步的(AP模型) 就會(huì)出現(xiàn)問(wèn)題??梢酝ㄟ^(guò)redLock
解決

2. redisson 分布式鎖接口方案

使用原生的redis 會(huì)有各種問(wèn)題,我們來(lái)看看redisson框架給我的解決方法

2.1 看門狗原理

如果負(fù)責(zé)儲(chǔ)存這個(gè)分布式鎖的 Redisson
節(jié)點(diǎn)宕機(jī)以后,而且這個(gè)鎖正好處于鎖住的狀態(tài)時(shí),這個(gè)鎖會(huì)出現(xiàn)鎖死的狀態(tài)。為了避免這種情況的發(fā)生,Redisson內(nèi)部提供了一個(gè)監(jiān)控鎖的看門狗,它的作用是在Redisson實(shí)例被關(guān)閉前,不斷的延長(zhǎng)鎖的有效期。

默認(rèn)情況下,看門狗的檢查鎖的超時(shí)時(shí)間是30秒鐘,也可以通過(guò)修改Config.lockWatchdogTimeout來(lái)另行指定。

如果我們未制定 lock 的超時(shí)時(shí)間,就使用 30 秒作為看門狗的默認(rèn)時(shí)間。只要占鎖成功,就會(huì)啟動(dòng)一個(gè)定時(shí)任務(wù):每隔 10
秒重新給鎖設(shè)置過(guò)期的時(shí)間,過(guò)期時(shí)間為 30 秒。

2.2 主從復(fù)制的問(wèn)題

提供了一個(gè)專門的類:RedissonRedLock,使用了Redlock算法。

Redisson
原理參考 https://blog.csdn.net/agonie201218/article/details/115339670

redisson
操作示例 https://blog.csdn.net/agonie201218/article/details/122084140

redis分布式鎖的坑 https://blog.csdn.net/agonie201218/article/details/121423212

3.Zookeeper 分布式鎖接口方案

zk 分布式鎖,其實(shí)可以做的比較簡(jiǎn)單,就是某個(gè)節(jié)點(diǎn)嘗試創(chuàng)建臨時(shí) znode,此時(shí)創(chuàng)建成功了就獲取了這個(gè)鎖;這個(gè)時(shí)候別的客戶端來(lái)創(chuàng)建鎖會(huì)失敗,只能
注冊(cè)個(gè)監(jiān)聽(tīng)器監(jiān)聽(tīng)這個(gè)鎖。釋放鎖就是刪除這個(gè) znode,一旦釋放掉就會(huì)通知客戶端,然后有一個(gè)等待著的客戶端就可以再次重新加鎖。

參考

java分布式鎖解決方案 redisson or
ZooKeeper https://blog.csdn.net/agonie201218/article/details/122446601

萬(wàn)字總結(jié)Zookeeper客戶端Curator操作Api https://andyoung.blog.csdn.net/article/details/130115913

項(xiàng)目地址

https://github.com/admin4j/admin4j-framework/tree/master/admin4j-lock文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-425850.html

到了這里,關(guān)于一個(gè)注解解決分布式鎖和接口冪等性,springboot 實(shí)戰(zhàn) 。強(qiáng)到離大譜的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 使用 redis 實(shí)現(xiàn)分布式接口限流注解 RedisLimit

    使用 redis 實(shí)現(xiàn)分布式接口限流注解 RedisLimit

    前言 很多時(shí)候,由于種種不可描述的原因,我們需要針對(duì)單個(gè)接口實(shí)現(xiàn)接口限流,防止訪問(wèn)次數(shù)過(guò)于頻繁。這里就用 redis+aop 實(shí)現(xiàn)一個(gè)限流接口注解 @RedisLimit 代碼 點(diǎn)擊查看RedisLimit注解代碼 AOP代碼 點(diǎn)擊查看aop代碼 lua腳本代碼 注意:腳本代碼是放在 resources 文件下的,它的類型是

    2024年02月08日
    瀏覽(25)
  • 【分布式】: 冪等性和實(shí)現(xiàn)方式

    【分布式】: 冪等性和實(shí)現(xiàn)方式

    冪等(idempotent、idempotence)是一個(gè)數(shù)學(xué)與計(jì)算機(jī)學(xué)概念, 常見(jiàn)于抽象代數(shù)中。在編程中一個(gè)冪等操作的特點(diǎn)是其任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同。冪等函數(shù),或冪等方法,是指可以使用相同參數(shù)重復(fù)執(zhí)行,并能獲得相同結(jié)果的函數(shù)。這些函數(shù)不會(huì)影響系統(tǒng)

    2024年02月08日
    瀏覽(29)
  • 如何保證分布式情況下的冪等性

    關(guān)于這個(gè)分布式服務(wù)的冪等性,這是在使用分布式服務(wù)的時(shí)候會(huì)經(jīng)常遇到的問(wèn)題,比如,重復(fù)提交的問(wèn)題。而冪等性,就是為了解決問(wèn)題存在的一個(gè)概念了。 什么是冪等 冪等(idempotent、idempotence)是?個(gè)數(shù)學(xué)與計(jì)算機(jī)學(xué)概念,常?于抽象代數(shù)中。 在編程中?個(gè)冪等操作的特

    2024年02月07日
    瀏覽(22)
  • 云事業(yè)群CTO線技術(shù)晉升考核機(jī)試題-分布式專題-G 分布式冪等架構(gòu)設(shè)計(jì)

    作者:田超凡 1 冪等的基本概念 答:冪等指的是同一塊業(yè)務(wù)邏輯重復(fù)多次執(zhí)行時(shí),只能令其生效一次,防止重復(fù)執(zhí)行。 2 冪等的發(fā)生場(chǎng)景 答: RPC 調(diào)用接口的冪等性問(wèn)題 MQ 消費(fèi)者防止重復(fù)消費(fèi)的冪等性問(wèn)題 定時(shí)任務(wù)防止重復(fù)執(zhí)行的冪等性問(wèn)題 3 RPC調(diào)用接口的冪等性問(wèn)題產(chǎn)生

    2024年02月16日
    瀏覽(119)
  • 一個(gè)注解實(shí)現(xiàn)接口冪等性,真心優(yōu)雅!

    一個(gè)注解實(shí)現(xiàn)接口冪等性,真心優(yōu)雅!

    簡(jiǎn)單來(lái)說(shuō),就是對(duì)一個(gè)接口執(zhí)行重復(fù)的多次請(qǐng)求,與一次請(qǐng)求所產(chǎn)生的結(jié)果是相同的,聽(tīng)起來(lái)非常容易理解,但要真正的在系統(tǒng)中要始終保持這個(gè)目標(biāo),是需要很嚴(yán)謹(jǐn)?shù)脑O(shè)計(jì)的,在實(shí)際的生產(chǎn)環(huán)境下,我們應(yīng)該保證任何接口都是冪等的,而如何正確的實(shí)現(xiàn)冪等,就是本文要討

    2024年02月03日
    瀏覽(27)
  • 【Spring Cloud系列】- 分布式系統(tǒng)中實(shí)現(xiàn)冪等性的幾種方式

    【Spring Cloud系列】- 分布式系統(tǒng)中實(shí)現(xiàn)冪等性的幾種方式

    在開(kāi)發(fā)訂單系統(tǒng)時(shí),我們常遇見(jiàn)支付問(wèn)題,既用戶購(gòu)買商品后支付,支付扣款成功,但是返回結(jié)果的時(shí)候網(wǎng)絡(luò)異常,此時(shí)錢已經(jīng)扣了,用戶再次點(diǎn)擊按鈕,此時(shí)會(huì)進(jìn)行第二次扣款,返回結(jié)果成功,用戶查詢余額發(fā)現(xiàn)多扣錢了,流水記錄也變成了兩條。在以前的單應(yīng)用系統(tǒng)中,

    2024年02月10日
    瀏覽(20)
  • 開(kāi)源:Taurus.Idempotent 分布式冪等性鎖框架,支持 .Net 和 .Net Core 雙系列版本

    開(kāi)源:Taurus.Idempotent 分布式冪等性鎖框架,支持 .Net 和 .Net Core 雙系列版本

    分布式冪等性框架的作用是確保在分布式系統(tǒng)中的操作具有冪等性,即無(wú)論操作被重復(fù)執(zhí)行多少次,最終的結(jié)果都是一致的。冪等性是指對(duì)同一操作的多次執(zhí)行所產(chǎn)生的效果與僅執(zhí)行一次的效果相同。 以下是分布式冪等性框架的主要作用: 避免重復(fù)操作: 在分布式系統(tǒng)中,

    2024年03月09日
    瀏覽(27)
  • 使用注解實(shí)現(xiàn)REDIS分布式鎖

    使用注解實(shí)現(xiàn)REDIS分布式鎖

    有些業(yè)務(wù)請(qǐng)求,屬于耗時(shí)操作,需要加鎖,防止后續(xù)的并發(fā)操作,同時(shí)對(duì)數(shù)據(jù)庫(kù)的數(shù)據(jù)進(jìn)行操作,需要避免對(duì)之前的業(yè)務(wù)造成影響。 使用 Redis 作為分布式鎖,將鎖的狀態(tài)放到 Redis 統(tǒng)一維護(hù),解決集群中單機(jī) JVM 信息不互通的問(wèn)題,規(guī)定操作順序,保護(hù)用戶的數(shù)據(jù)正確。 梳理

    2024年02月02日
    瀏覽(22)
  • 自定義注解,基于redis實(shí)現(xiàn)分布式鎖

    自定義注解,基于redis實(shí)現(xiàn)分布式鎖

    1.1、注解的基礎(chǔ)知識(shí) 實(shí)現(xiàn)自定義注解其實(shí)很簡(jiǎn)單,格式基本都差不多。也就參數(shù)可能變一變。 @Retention:取值決定了注解在什么時(shí)候生效,一般都是取運(yùn)行時(shí),也就是RetentionPolicy.RUNTIME。 @Target:決定了這個(gè)注解可以使用在哪些地方,可以取方法,字段,類等。 注解這就定義

    2024年02月08日
    瀏覽(20)
  • 使用Redission自定義注解實(shí)現(xiàn)分布式鎖(聲明式)

    1.主要依賴 配置redission 自定義注解 sepl工具類 aop

    2024年02月11日
    瀏覽(14)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包