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

Redis如何使用樂觀鎖(CAS)保證數(shù)據(jù)一致性

 更新時間:2022年03月25日 11:41:04   作者:翹翹腳_蹦高高  
本文主要介紹了Redis如何使用樂觀鎖(CAS)保證數(shù)據(jù)一致性,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

場景

在 Redis 中經(jīng)常會存在這么一種情況,讀取某一個 key 的值,做一些業(yè)務(wù)邏輯處理,然后根據(jù)讀取到的值來計算出一個新的值,重新 set 進(jìn)去。

如果客戶端 A 剛讀取到 key 值,緊接著客戶端 B 就修改這個 key 的值,那么就會存在并發(fā)安全的問題。

問題模擬

假設(shè) Redis Server 有個鍵名為 test 的key,里面存放的是一個 json 數(shù)組 [1, 2, 3]。

下面讓我們模擬一下,客戶端 A 與 客戶端 B 同時訪問修改的情況,代碼如下:

客戶端 A:

class RedisClientA(username: String, password: String, host: String, port: Int) {
    val jedis: Jedis

    init {
        val pool = JedisPool(JedisPoolConfig(), host, port)
        jedis = pool.resource
        jedis.auth(username, password)
    }

    fun update(key: String) {
        val idStr = jedis.get(key)
        val idList = Json.decodeFromString<MutableList<Int>>(idStr)

        // 等待2秒,模擬業(yè)務(wù)
        TimeUnit.SECONDS.sleep(2L)

        idList.add(4)
        println("new id list: $idList")

        jedis.set(key, Json.encodeToString(idList))
    }

    fun getVal(key: String): String? {
        return jedis.get(key)
    }
}

fun main() {
    val key = "test"
    val redisClientA = RedisClientA("default", "123456", "127.0.0.1", 6379)
    redisClientA.update(key)
    val res = redisClientA.getVal(key)
    println("res: $res")
}

客戶端 B:

class RedisClientB(username: String, password: String, host: String, port: Int) {
    val jedis: Jedis

    init {
        val pool = JedisPool(JedisPoolConfig(), host, port)
        jedis = pool.resource
        jedis.auth(username, password)
    }

    fun update(key: String) {
        val idStr = jedis.get(key)
        val idList = Json.decodeFromString<MutableList<Int>>(idStr)

        idList.add(5)
        println("new id list: $idList")

        jedis.set(key, Json.encodeToString(idList))
    }

    fun getVal(key: String): String? {
        return jedis.get(key)
    }
}

fun main() {
    val key = "test"
    val redisClientB = RedisClientB("default", "123456", "127.0.0.1", 6379)
    redisClientB.update(key)
    val res = redisClientB.getVal(key)
    println("res: $res")
}

客戶端 A 阻塞了 2 秒,用來模擬耗時業(yè)務(wù)邏輯的處理。正在處理的時候,客戶端 B 訪問了 “test”,并增加了 id:5。

在客戶端 A 耗時業(yè)務(wù)邏輯處理完的時候,增加了 id:4,并且會覆蓋掉 id:5。

最終“test” 里的內(nèi)容最終如下:

CAS 來保證數(shù)據(jù)一致性

WATCH 命令可以為 Redis 事務(wù)提供 check-and-set(CAS)行為。被 WATCH 的鍵會被監(jiān)視,并會發(fā)覺這些鍵是否被改動過了。如果有至少一個被監(jiān)視的建在 EXEC 執(zhí)行之前被修改了,那么整個事務(wù)都會被取消,EXEC 返回空(Null replay)來表示事務(wù)執(zhí)行失敗。我們只需要重復(fù)操作,希望在這個時間段內(nèi)不會有新的競爭。這種形式的鎖被稱作樂觀鎖,它是一種非常強(qiáng)大的鎖機(jī)制。

那么 CAS 的方式如何實現(xiàn)呢?我們只需要把 RedisClientA 的 update() 方法中的代碼修改如下:

fun update(key: String) {
    var flag = true

    while (flag) {
        jedis.watch(key)

        val idStr = jedis.get(key)
        val idList = Json.decodeFromString<MutableList<Int>>(idStr)

        // 等待2秒,模擬業(yè)務(wù)
        TimeUnit.SECONDS.sleep(2L)

        val transaction = jedis.multi()
        idList.add(4)
        println("new id list: $idList")

        transaction.set(key, Json.encodeToString(idList))

        transaction.exec()?.let {
            flag = false
        }
    }

}

最終 “test” 的內(nèi)容如下:

可見我們通過使用 WATCH 和 TRANACTION 命令,采用 CAS 樂觀鎖的方式實現(xiàn)了數(shù)據(jù)的一致性。

到此這篇關(guān)于Redis如何使用樂觀鎖(CAS)保證數(shù)據(jù)一致性的文章就介紹到這了,更多相關(guān)Redis 樂觀鎖保證數(shù)據(jù)一致性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis通過位圖法記錄在線用戶的狀態(tài)詳解

    redis通過位圖法記錄在線用戶的狀態(tài)詳解

    這篇文章主要給大家介紹了關(guān)于redis如何通過位圖法記錄在線用戶的狀態(tài)的相關(guān)資料,文中先對位圖進(jìn)行了一個簡單的介紹,而后通過示例代碼將實現(xiàn)的方法介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • Redis不同數(shù)據(jù)類型使用場景代碼實例

    Redis不同數(shù)據(jù)類型使用場景代碼實例

    這篇文章主要介紹了Redis不同數(shù)據(jù)類型使用場景代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-12-12
  • 配置redis的序列化,注入RedisTemplate方式

    配置redis的序列化,注入RedisTemplate方式

    這篇文章主要介紹了配置redis的序列化,注入RedisTemplate方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 一篇吃透Redis緩存穿透、雪崩、擊穿問題

    一篇吃透Redis緩存穿透、雪崩、擊穿問題

    這篇文主要介紹了Redis緩存穿透,緩存雪崩,緩存擊穿的問題解決方法,文中有詳細(xì)的圖文介紹,對大家了解Redis有一定的幫助,需要的朋友可以參考下
    2023-05-05
  • redis持久化的介紹

    redis持久化的介紹

    今天小編就為大家分享一篇關(guān)于redis持久化的介紹,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Redis數(shù)據(jù)一致性詳解

    Redis數(shù)據(jù)一致性詳解

    文章主要討論了分布式系統(tǒng)中的數(shù)據(jù)一致性模型、緩存使用場景以及數(shù)據(jù)同步策略,一致性模型包括強(qiáng)一致性、弱一致性和最終一致性,緩存使用場景主要在高并發(fā)讀取數(shù)據(jù)時提升性能,數(shù)據(jù)同步策略分為先刪除緩存再更新數(shù)據(jù)庫和先更新數(shù)據(jù)庫再刪除緩存兩種
    2024-11-11
  • 淺談Redis如何應(yīng)對并發(fā)訪問

    淺談Redis如何應(yīng)對并發(fā)訪問

    本文主要介紹了Redis如何應(yīng)對并發(fā)訪問,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 基于redis實現(xiàn)定時任務(wù)的方法詳解

    基于redis實現(xiàn)定時任務(wù)的方法詳解

    這篇文章主要給大家介紹了基于redis實現(xiàn)定時任務(wù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用redis具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Redis數(shù)據(jù)庫的應(yīng)用場景介紹

    Redis數(shù)據(jù)庫的應(yīng)用場景介紹

    這篇文章主要介紹了Redis數(shù)據(jù)庫的應(yīng)用場景介紹,本文講解了MySql+Memcached架構(gòu)的問題、Redis常用數(shù)據(jù)類型、Redis數(shù)據(jù)類型應(yīng)用和實現(xiàn)方式、Redis實際應(yīng)用場景等內(nèi)容,需要的朋友可以參考下
    2015-06-06
  • Redis在項目中常見的12種使用場景示例和說明

    Redis在項目中常見的12種使用場景示例和說明

    Redis是一個開源的高性能鍵值對數(shù)據(jù)庫,它以其內(nèi)存中數(shù)據(jù)存儲、鍵過期策略、持久化、事務(wù)、豐富的數(shù)據(jù)類型支持以及原子操作等特性,在許多項目中扮演著關(guān)鍵角色,以下是整理的12個Redis在項目中常見的使用場景舉例說明和解釋
    2024-06-06

最新評論

白河县| 胶南市| 榆中县| 鄂尔多斯市| 波密县| 虹口区| 虹口区| 和田县| 高密市| 墨江| 习水县| 荆门市| 丹江口市| 普安县| 淮南市| 仙桃市| 莆田市| 廉江市| 马关县| 临西县| 夏津县| 定州市| 开鲁县| 河间市| 秦皇岛市| 盐亭县| 中西区| 通道| 辽宁省| 砚山县| 弥勒县| 武鸣县| 夏河县| 天气| 钦州市| 如皋市| 丹阳市| 昆山市| 修文县| 林口县| 永胜县|