Maison > base de données > Redis > le corps du texte

Redis provoquera-t-il des problèmes de blocage ?

Libérer: 2019-07-08 09:14:05
original
5544 Les gens l'ont consulté

Redis provoquera-t-il des problèmes de blocage ?

En ce qui concerne les verrous distribués, un problème courant est que si un service setnx réussit, mais s'il y a un temps d'arrêt ou des facteurs spéciaux lors du déverrouillage, il ne peut pas être déverrouillé. Ensuite, d’autres services tomberont dans une impasse. Par conséquent, lors de l'utilisation de setnx, nous envisageons d'utiliser l'instruction expire pour effectuer une opération d'expiration sur le verrou. À partir des instructions, nous pouvons voir que les instructions setnx et expire sont distinctes. S'il y a des facteurs spéciaux pendant le processus d'intervalle, le l’instruction ne peut pas continuer, conduira également à une impasse.

Solution :

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
 
@Component
public class RedisLock {
 
    Logger logger = LoggerFactory.getLogger(this.getClass());
 
    @Autowired
    private StringRedisTemplate redisTemplate;
 
    /**
     * 加锁
     * @param key   
     * @param value 当前时间 + 超时时间
     * @return
     */
    public boolean lock(String key, String value) {
    
        if (redisTemplate.opsForValue().setIfAbsent(key, value)) {     
            // 这个其实就是setnx命令,只不过在java这边稍有变化,返回的是boolean
            // 设置个过期时间,当然如果在这中间的空隙过程中如果有特殊因素导致指令无法继续,也会导致死锁的产生,如果死锁出现,则后续代码会处理
            redisTemplate.expire(key, lockTime, TimeUnit.SECONDS);
            return true;
        }
 
        // 避免死锁,且只让一个线程拿到锁
        String currentValue = redisTemplate.opsForValue().get(key);
        // 如果锁过期了
        if (!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) {
            //获取上一个锁的时间
            String oldValues = redisTemplate.opsForValue().getAndSet(key, value);
 
            /*
               只会让一个线程拿到锁
               如果旧的value和currentValue相等,只会有一个线程达成条件,因为第二个线程拿到的oldValue已经和currentValue不一样了
             */
            if (!StringUtils.isEmpty(oldValues) && oldValues.equals(currentValue)) {
                return true;
            }
        }
        return false;
    }
 
 
    /**
     * 解锁
     * @param key
     * @param value
     */
    public void unlock(String key, String value) {
        try {
            String currentValue = redisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        } catch (Exception e) {
            logger.error("redis分布式锁解锁异常,{}", e);
        }
    }
}
Copier après la connexion

Appel :

 //加锁
    long time = System.currentTimeMillis() + 1000 * lockTime //超时时间:10秒,最好设为常量
 
    boolean isLock = redisLock.lock(...keyName, String.valueOf(time));
    if(!isLock){
        throw new RuntimeException("系统正忙");
    }
    
    // doSomething...
    
    
    //解锁
    redisLock.unlock(...keyName, String.valueOf(time));
Copier après la connexion

Pour plus de connaissances sur Redis, veuillez visiter la colonne Tutoriel d'utilisation de Redis !

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:php.cn
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
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!