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

分布式鎖的實現(xiàn)(redis)

這篇具有很好參考價值的文章主要介紹了分布式鎖的實現(xiàn)(redis)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1、單機鎖

考慮在并發(fā)場景并且存在競態(tài)的狀況下,我們就要實現(xiàn)同步機制了,最簡單的同步機制就是加鎖。

加鎖可以幫我們鎖住資源,如內(nèi)存中的變量,或者鎖住臨界區(qū)(線程中的一段代碼),使得同一個時刻只有一個線程能訪問某一個區(qū)域。

如果是單實例(單進程部署),那么單機鎖就可以滿足我們的要求了,如synchronized,ReentrantLock。

因為在一個進程中的不同線程可以共享這個鎖。

2、分布式鎖

但是如果場景來到了分布式系統(tǒng)呢?

分布式系統(tǒng)部署在不同的機器上,或者只是簡單的多進程部署。這樣各個進程之間無法共享同一個鎖。

這時候我們要加分布式鎖。

分布式鎖大概就是這么一個東西:通過共享的存儲緩存一個狀態(tài)值,用狀態(tài)值的變化標識鎖的占用和釋放。

可以通過mysql,redis,zk等實現(xiàn)分布式鎖,這里我們實現(xiàn)一個redis的。如果你用java其實使用zk會很簡單。

3、為什么redis能用來實現(xiàn)分布式鎖?

1)Redis是單進程單線程模式

redis實現(xiàn)為單進程單線程模式,這樣多個客戶端并不存在競態(tài)關(guān)系。

2)原子性原語

redis提供了可以實現(xiàn)原子操作的原語如setnx、getset等。

setnx

1)SETNX key value

將 key 的值設(shè)為 value ,當且僅當 key 不存在。

若給定的 key 已經(jīng)存在,則 SETNX 不做任何動作。

SETNX 是『SET if Not eXists』(如果不存在,則 SET)的簡寫。

可用版本:
>= 1.0.0
時間復(fù)雜度:
O(1)
返回值:
設(shè)置成功,返回 1 。
設(shè)置失敗,返回 0 。

復(fù)制

getset

GETSET key value

將給定 key 的值設(shè)為 value ,并返回 key 的舊值(old value)。

當 key 存在但不是字符串類型時,返回一個錯誤。

可用版本:
>= 1.0.0
時間復(fù)雜度:
O(1)
返回值:
返回給定 key 的舊值。
當 key 沒有舊值時,也即是, key 不存在時,返回 nil 。

復(fù)制

4、實現(xiàn)

package com.xiaoju.dqa.fusor.utils;

import com.xiaoju.dqa.fusor.client.RedisClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


@Component
public class DistributeLockUtil {

    // 鎖超時時間, 防止死鎖
    private static final long LOCK_TIMEOUT = 60;

    @Autowired
    private RedisClient redisClient;

    private boolean locked = false;

    public boolean lock(String key) {
        String expireTime = String.valueOf(System.currentTimeMillis() + LOCK_TIMEOUT * 1000);
        /*
        *   setnx 返回1
        *   說明: 1)key不存在, 2)成功寫入鎖, 并更新鎖的生存時間
        *   也就是get鎖
        * */
        if (redisClient.setnx(key, expireTime) == 1) {
            locked = true;
            return true;
        }
        /*
        *  沒有g(shù)et鎖, 下面進入判斷鎖超時邏輯
        * */
        String currentExpireTime = redisClient.get(key);
        /*
        *   鎖生存時間已經(jīng)過了, 說明鎖已經(jīng)超時
        * */
        if (Long.parseLong(currentExpireTime) < System.currentTimeMillis()) {
            String oldValueStr = redisClient.getSet(key, expireTime);
            /*
            *   判斷鎖生存時間和你改的寫那個時間是否相等
            *   相當于你競爭了一個更新鎖
            * */
            if (oldValueStr.equals(currentExpireTime)) {
                locked = true;
                return true;
            }
        }
        return false;
    }

    public void release(String key) {
        if (locked) {
            redisClient.del(key);
            locked = false;
        }
    }

}

復(fù)制

5、死鎖

為了解決死鎖,這里設(shè)置了鎖的超時時間。

    private static final long LOCK_TIMEOUT = 60;

復(fù)制

并通過setnx時更新鎖生存時間來維護鎖超時的判定。

String expireTime = String.valueOf(System.currentTimeMillis() + LOCK_TIMEOUT * 1000);
...
if (redisClient.setnx(key, expireTime) == 1) {
...
}
...
String oldValueStr = redisClient.getSet(key, expireTime);
...

復(fù)制

為什么要使用這種方式,而不是expire呢?

因為setnx和expire不能作為一個原子性的操作存在,設(shè)想如果setnx之后,在執(zhí)行expire之前出現(xiàn)了異常,那么鎖將沒有超時時間。也就是死鎖。

6、解決鎖超時引入的競態(tài)

設(shè)想三個客戶端,C0,C1,C2

如果C0持有鎖并且崩潰,鎖沒有釋放。

C1和C2同時發(fā)現(xiàn)了鎖超時。

然后都通過getset去拿到了舊值,在對比了舊值和之前值之后,如果相等,那么說明“我”成功修改了舊值,那么我就拿到了鎖。

7、 時鐘同步

我們看到foo.lock的value值為時間戳,所以要在多客戶端情況下,保證鎖有效,一定要同步各服務(wù)器的時間,如果各服務(wù)器間,時間有差異。時間不一致的客戶端,在判斷鎖超時,就會出現(xiàn)偏差,從而產(chǎn)生競爭條件。 鎖的超時與否,嚴格依賴時間戳,時間戳本身也是有精度限制,假如我們的時間精度為秒,從加鎖到執(zhí)行操作再到解鎖,一般操作肯定都能在一秒內(nèi)完成。這樣的話,我們上面的CASE,就很容易出現(xiàn)。所以,最好把時間精度提升到毫秒級。這樣的話,可以保證毫秒級別的鎖是安全的。

8、一些處理不了的情況

設(shè)想三個客戶端,C0,C1,C2

如果C0持有鎖很長,鎖已經(jīng)超時。這時候有C1,C2判斷鎖超時了,然后通過超時競爭,C1拿到了鎖。

這時C0醒了過來,刪除了C1的鎖。

這時,C1認為自己獨占了鎖,其他的進程也進入了競爭鎖的情況

對于這種情況,這里是沒有提供解決辦法的。

思路是:你降級你的鎖,比如給你的鎖加上uuid,對不同的業(yè)務(wù)或者不同的session加上對應(yīng)粒度的鎖。文章來源地址http://www.zghlxwxcb.cn/news/detail-518333.html

到了這里,關(guān)于分布式鎖的實現(xiàn)(redis)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • Zookeeper 和 Redis 哪種更好? 為什么使用分布式鎖? 1. 利用 Redis 提供的 第二種,基于 ZK 實現(xiàn)分布式鎖的落地方案 對于 redis 的分布式鎖而言,它有以下缺點:

    關(guān)于這個問題,我們 可以從 3 個方面來說: 為什么使用分布式鎖? 使用分布式鎖的目的,是為了保證同一時間只有一個 JVM 進程可以對共享資源進行操作。 根據(jù)鎖的用途可以細分為以下兩類: 允許多個客戶端操作共享資源,我們稱為共享鎖 這種鎖的一般是對共享資源具有

    2024年01月16日
    瀏覽(23)
  • 【Redis】Redis分布式鎖的10個坑

    【Redis】Redis分布式鎖的10個坑

    日常開發(fā)中,經(jīng)常會碰到秒殺搶購等業(yè)務(wù)。為了避免并發(fā)請求造成的庫存超賣等問題,我們一般會用到Redis分布式鎖。但是使用Redis分布式鎖,很容易踩坑哦~ 本文將給大家分析闡述,Redis分布式鎖的10個坑~ 一說到實現(xiàn)Redis的分布式鎖,很多小伙伴馬上就會想到setnx+ expire命令。

    2024年02月05日
    瀏覽(26)
  • Redis——》Redis的部署方式對分布式鎖的影響

    Redis——》Redis的部署方式對分布式鎖的影響

    推薦鏈接: ????總結(jié)——》【Java】 ????總結(jié)——》【Mysql】 ????總結(jié)——》【Redis】 ????總結(jié)——》【Kafka】 ????總結(jié)——》【Spring】 ????總結(jié)——》【SpringBoot】 ????總結(jié)——》【MyBatis、MyBatis-Plus】 ????總結(jié)——》【Linux】 ????總結(jié)——》【MongoDB】 ???

    2024年02月10日
    瀏覽(23)
  • 【面試題24】你是如何使用Redis分布式鎖的

    本文已收錄于PHP全棧系列專欄:PHP面試專區(qū)。 計劃將全覆蓋PHP開發(fā)領(lǐng)域所有的面試題, 對標資深工程師/架構(gòu)師序列 ,歡迎大家提前關(guān)注鎖定。 Redis分布式鎖是一種利用Redis實現(xiàn)的分布式鎖機制。它通過在共享的Redis實例上設(shè)置一個特定的鍵值對來實現(xiàn)對資源的互斥訪問。今

    2024年02月11日
    瀏覽(17)
  • 在Spring中,可以使用不同的方式來實現(xiàn)分布式鎖,例如基于數(shù)據(jù)庫、Redis、ZooKeeper等

    在Spring中,可以使用不同的方式來實現(xiàn)分布式鎖,例如基于數(shù)據(jù)庫、Redis、ZooKeeper等

    在Spring中,可以使用不同的方式來實現(xiàn)分布式鎖,例如基于數(shù)據(jù)庫、Redis、ZooKeeper等。下面是兩種常見的實現(xiàn)方式: 使用Redis實現(xiàn)分布式鎖: 使用自定義注解實現(xiàn)本地鎖: 以上是兩種常見的在Spring中實現(xiàn)分布式鎖的方式。第一種方式使用Redis作為分布式鎖的存儲介質(zhì),通過

    2024年03月17日
    瀏覽(24)
  • 【征服redis15】分布式鎖的功能與整體設(shè)計方案

    【征服redis15】分布式鎖的功能與整體設(shè)計方案

    目錄 ?1. 分布式鎖的概念 2.基于數(shù)據(jù)庫做分布式鎖 2.1 基于表主鍵唯一做分布式鎖 2.2 基于表字段版本號做分布式鎖 2.3 基于數(shù)據(jù)庫排他鎖做分布式鎖 3.使用Redis做分布式鎖 3.1 redis實現(xiàn)分布式鎖的基本原理 3.2 問題一:增加超時機制,防止長期持有的情況 3.3 問題2:重入的問題

    2024年01月22日
    瀏覽(22)
  • 分布式鎖的幾種實現(xiàn)方式:

    redis是基于單線程,在某個時刻只會有一個線程執(zhí)行命令,可以利用set原子性的操作,配合set nx(RedisStringCommands.SetOption.SET_IF_ABSENT) ,這樣,當多個線程或多個節(jié)點嘗試獲取鎖時,只有一個可以成功,其他的會因為鎖已存在而獲取失敗。這種方式通過 Redis 來實現(xiàn)分布式鎖,

    2024年01月18日
    瀏覽(18)
  • 分布式天梯圖算法在 Redis 圖數(shù)據(jù)庫中的應(yīng)用

    Redis是一個高性能的鍵值對數(shù)據(jù)庫,支持常用的數(shù)據(jù)結(jié)構(gòu)和分布式操作,被廣泛應(yīng)用于緩存、消息隊列和排行榜等場景。除了基本的數(shù)據(jù)結(jié)構(gòu),Redis還支持圖數(shù)據(jù)結(jié)構(gòu)并提供了一些算法支持。 天梯圖算法是一種基于貪心的圖搜索算法,在尋找最短路徑問題中具有很高的效率。

    2024年02月14日
    瀏覽(25)
  • ZooKeeper分布式鎖的實現(xiàn)與應(yīng)用

    ZooKeeper是一種分布式應(yīng)用程序協(xié)調(diào)服務(wù),它可以管理大規(guī)模的集群,并提供可靠的、有序的、高效的數(shù)據(jù)通信。其中,ZooKeeper提供的分布式鎖是一種常見的分布式鎖實現(xiàn),本文將對其進行詳細介紹。 在分布式系統(tǒng)中,多個進程或節(jié)點可能需要同時訪問共享資源。為了確保數(shù)據(jù)

    2024年02月02日
    瀏覽(21)
  • 高并發(fā)緩存問題分析以及分布式鎖的實現(xiàn)

    高并發(fā)緩存問題分析以及分布式鎖的實現(xiàn)

    在高并發(fā)的環(huán)境下,比如淘寶,京東不定時的促銷活動,大量的用戶訪問會導(dǎo)致數(shù)據(jù)庫的性能下降,進而有可能數(shù)據(jù)庫宕機從而不能產(chǎn)生正常的服務(wù),一般一個系統(tǒng)最大的性能瓶頸,就是數(shù)據(jù)庫的io操作,如果發(fā)生大量的io那么他的問題也會隨之而來。從數(shù)據(jù)庫入手也是調(diào)優(yōu)性價比最高

    2024年01月19日
    瀏覽(34)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包