中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Redis怎么使用樂觀鎖保證數據一致性

發布時間:2022-03-28 09:49:39 來源:億速云 閱讀:283 作者:小新 欄目:開發技術

這篇文章主要介紹了Redis怎么使用樂觀鎖保證數據一致性,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

場景

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

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

問題模擬

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

Redis怎么使用樂觀鎖保證數據一致性

下面讓我們模擬一下,客戶端 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秒,模擬業務
        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 秒,用來模擬耗時業務邏輯的處理。正在處理的時候,客戶端 B 訪問了 “test”,并增加了 id:5。

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

最終“test” 里的內容最終如下:

Redis怎么使用樂觀鎖保證數據一致性

CAS 來保證數據一致性

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

那么 CAS 的方式如何實現呢?我們只需要把 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秒,模擬業務
        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” 的內容如下:

Redis怎么使用樂觀鎖保證數據一致性

可見我們通過使用 WATCH 和 TRANACTION 命令,采用 CAS 樂觀鎖的方式實現了數據的一致性。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Redis怎么使用樂觀鎖保證數據一致性”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

固阳县| 瑞丽市| 沙坪坝区| 杭州市| 栾川县| 长垣县| 嘉禾县| 锡林浩特市| 广德县| 涞水县| 永康市| 洛隆县| 喀喇| 九江县| 吴川市| 永宁县| 台安县| 祁阳县| 老河口市| 营口市| 抚宁县| 中阳县| 石台县| 汪清县| 射阳县| 新平| 任丘市| 科技| 图木舒克市| 荥经县| 潢川县| 普兰店市| 米泉市| 鄢陵县| 隆尧县| 广州市| 石台县| 伊宁市| 兴安盟| 民权县| 徐闻县|