Maison > base de données > Redis > Comment Redis utilise le verrouillage optimiste pour garantir la cohérence des données

Comment Redis utilise le verrouillage optimiste pour garantir la cohérence des données

WBOY
Libérer: 2023-06-02 16:52:42
avant
741 Les gens l'ont consulté

Scénario

Dans Redis, il arrive souvent que la valeur d'une certaine clé soit lue, qu'un traitement de logique métier soit effectué, puis qu'une nouvelle valeur soit calculée en fonction de la valeur lue et définie à nouveau.

Si le client A vient de lire la valeur de la clé, puis que le client B modifie la valeur de la clé, il y aura alors un problème de sécurité de concurrence.

Simulation de problèmes

Supposons que Redis Server ait une clé nommée test, qui stocke un tableau json [1, 2, 3].

Comment Redis utilise le verrouillage optimiste pour garantir la cohérence des données

Simulons la situation où le client A et le client B accèdent aux modifications en même temps. Le code est le suivant :

Client 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")
}
Copier après la connexion

Client 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")
}
Copier après la connexion

Le client A est bloqué pendant 2 secondes. , utilisé pour simuler un traitement de logique métier fastidieux. Le client B a accédé à « test » pendant le traitement et a ajouté l'identifiant : 5.

Lorsque le client A termine le traitement de la logique métier fastidieuse, l'identifiant : 4 est ajouté et l'identifiant : 5 sera écrasé.

Le contenu final de "test" est le suivant :

Comment Redis utilise le verrouillage optimiste pour garantir la cohérence des données

CAS pour garantir la cohérence des données

La commande WATCH de Redis fournit un comportement de vérification et de définition (CAS) pour les transactions Redis. Les clés surveillées seront surveillées et il sera découvert si elles ont été modifiées. Si au moins un objet surveillé est modifié avant l'exécution d'EXEC, la transaction entière sera annulée et EXEC renvoie une relecture Null pour indiquer l'échec de l'exécution de la transaction. Il suffit de répéter l'opération et d'espérer qu'il n'y aura pas de nouvelle concurrence pendant cette période. Cette forme de verrouillage est appelée verrouillage optimiste et constitue un mécanisme de verrouillage très puissant.

Alors comment mettre en œuvre CAS ? Il suffit de modifier le code dans la méthode update() de RedisClientA comme suit :

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
        }
    }

}
Copier après la connexion

Le contenu final du "test" est le suivant :

Comment Redis utilise le verrouillage optimiste pour garantir la cohérence des données

On voit que nous utilisons les commandes WATCH et TRANACTION pour implémenter données utilisant la cohérence de verrouillage optimiste CAS.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:yisu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal