Maison > Java > javaDidacticiel > le corps du texte

Explication détaillée de l'utilisation de Redis pour implémenter des verrous distribués (exemple de code)

不言
Libérer: 2018-10-20 17:00:28
avant
3459 Les gens l'ont consulté

Cet article vous apporte une explication détaillée (exemple de code) de l'utilisation de Redis pour implémenter des verrous distribués. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Raisons du choix de Redis pour implémenter des verrous distribués

Redis a des performances élevées

La commande Redis prend mieux en charge cela et est plus pratique à implémenter

Introduction à l'utilisation des commandes

SETNX

SETNX key val
Si et seulement si la clé n'existe pas, définissez une chaîne avec key val et renvoyez 1 ; Si la clé existe, ne faites rien et renvoyez 0.

expire

expire key timeout
Définissez un délai d'expiration pour la clé en secondes. Le verrou sera automatiquement libéré après ce délai pour éviter une impasse.

delete

delete key
delete key

Lors de l'utilisation de Redis pour implémenter des verrous distribués, ces trois commandes sont principalement utilisées.

implémente

en utilisant jedis pour se connecter à Redis.

Idée d'implémentation

Lors de l'acquisition du verrou, utilisez setnx pour le verrouiller et utilisez la commande expire pour ajouter un délai d'attente au verrou. Après ce délai, le le verrou sera automatiquement libéré. ​​La valeur est un UUID généré aléatoirement, qui est utilisé pour juger du moment où le verrou est libéré.

Lors de l'acquisition du verrou, un délai d'attente est également défini pour l'acquisition. Si ce délai est dépassé, l'acquisition du verrou sera abandonnée.

Lors de la libération d'un verrou, utilisez l'UUID pour déterminer s'il s'agit du verrou. S'il s'agit du verrou, exécutez delete pour libérer le verrou.

Le code de base du verrou distribué est le suivant :

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.exceptions.JedisException;
 
import java.util.List;
import java.util.UUID;
 
public class DistributedLock {
    private final JedisPool jedisPool;
 
    public DistributedLock(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
    }
 
    /**
     * 加锁
     * @param locaName  锁的key
     * @param acquireTimeout  获取超时时间
     * @param timeout   锁的超时时间
     * @return 锁标识
     */
    public String lockWithTimeout(String locaName,
                                  long acquireTimeout, long timeout) {
        Jedis conn = null;
        String retIdentifier = null;
        try {
            // 获取连接
            conn = jedisPool.getResource();
            // 随机生成一个value
            String identifier = UUID.randomUUID().toString();
            // 锁名,即key值
            String lockKey = "lock:" + locaName;
            // 超时时间,上锁后超过此时间则自动释放锁
            int lockExpire = (int)(timeout / 1000);
 
            // 获取锁的超时时间,超过这个时间则放弃获取锁
            long end = System.currentTimeMillis() + acquireTimeout;
            while (System.currentTimeMillis()  results = transaction.exec();
                    if (results == null) {
                        continue;
                    }
                    retFlag = true;
                }
                conn.unwatch();
                break;
            }
        } catch (JedisException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return retFlag;
    }
}
Copier après la connexion

Test

Ce qui suit est un exemple simple pour tester le verrou distribué qui vient d'être implémenté.
Dans l'exemple, 50 threads sont utilisés pour simuler une vente flash d'un produit, et l'opérateur -- est utilisé pour réduire le produit. L'ordre des résultats permet de voir s'il est dans un état verrouillé. .

Simulez le service de vente flash, configurez-y le pool de threads Jedis et transmettez-le au verrou distribué lors de l'initialisation pour son utilisation.

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class Service {
    private static JedisPool pool = null;
 
    static {
        JedisPoolConfig config = new JedisPoolConfig();
        // 设置最大连接数
        config.setMaxTotal(200);
        // 设置最大空闲数
        config.setMaxIdle(8);
        // 设置最大等待时间
        config.setMaxWaitMillis(1000 * 100);
        // 在borrow一个jedis实例时,是否需要验证,若为true,则所有jedis实例均是可用的
        config.setTestOnBorrow(true);
        pool = new JedisPool(config, "127.0.0.1", 6379, 3000);
    }
 
    DistributedLock lock = new DistributedLock(pool);
 
    int n = 500;
 
    public void seckill() {
        // 返回锁的value值,供释放锁时候进行判断
        String indentifier = lock.lockWithTimeout("resource", 5000, 1000);
        System.out.println(Thread.currentThread().getName() + "获得了锁");
        System.out.println(--n);
        lock.releaseLock("resource", indentifier);
    }
}
Copier après la connexion

Simuler le fil pour effectuer un service de vente flash

public class ThreadA extends Thread {
    private Service service;
 
    public ThreadA(Service service) {
        this.service = service;
    }
 
    @Override
    public void run() {
        service.seckill();
    }
}
 
public class Test {
    public static void main(String[] args) {
        Service service = new Service();
        for (int i = 0; i <p>Les résultats sont les suivants, et les résultats sont dans l'ordre. </p><p style="text-align: center;"><span class="img-wrap"><img src="https://img.php.cn//upload/image/211/984/157/1540025904941327.png" title="1540025904941327.png" alt="Explication détaillée de lutilisation de Redis pour implémenter des verrous distribués (exemple de code)"></span></p><p>Si vous commentez la partie qui utilise des verrous </p><pre class="brush:php;toolbar:false">public void seckill() {
    // 返回锁的value值,供释放锁时候进行判断
    //String indentifier = lock.lockWithTimeout("resource", 5000, 1000);
    System.out.println(Thread.currentThread().getName() + "获得了锁");
    System.out.println(--n);
    //lock.releaseLock("resource", indentifier);
}
Copier après la connexion

Comme le montrent les résultats, certains sont exécutés de manière asynchrone.

Explication détaillée de lutilisation de Redis pour implémenter des verrous distribués (exemple de code)

Dans un environnement distribué, il est parfois important de verrouiller les ressources, par exemple en récupérant une certaine ressource. Dans ce cas, vous pouvez utiliser des verrous distribués. assurer un bon contrôle des ressources.

Bien sûr, dans une utilisation spécifique, de nombreux facteurs doivent être pris en compte, tels que la sélection du délai d'attente et la sélection du temps d'acquisition du verrou, qui ont un grand impact sur le degré de concurrence du verrou distribué implémenté. ci-dessus n'est qu'une implémentation simple est principalement une idée.

[En fait, la fiabilité de l'utilisation de zookeeper est supérieure à celle du verrouillage distribué implémenté par Redis, mais en comparaison, les performances de Redis sont meilleures. ]

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:segmentfault.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