redis 分布式锁实现方式

目录

一、分布式锁一般有三种实现方式:

二、数据库乐观锁(待补充)

三、基于Redis的分布式锁

四、基于ZooKeeper的分布式锁(贴一下别人的帖子)


一、分布式锁一般有三种实现方式:

1. 数据库乐观锁;

2. 基于Redis的分布式锁;

3. 基于ZooKeeper的分布式锁。

为了确保分布式锁可用,至少要确保同时满足以下四个条件:

1、互斥性。在任意时刻,只有一个客户端能持有锁;

2、不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁;

3、具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁;

4、解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。

二、数据库乐观锁(待补充)

https://blog.csdn.net/tianjiabin123/article/details/72625156/

三、基于Redis的分布式锁

public class RedisLock {

    @Autowired
    public StringRedisTemplate stringRedisTemplate;

    private static final Logger log = LoggerFactory.getLogger(UserResource.class);

    /**
     * 加锁
     * @param key
     * @param value 当前时间+超时时间
     * @return
     */
    public boolean lock(String key, String value) {
        
        if (stringRedisTemplate.opsForValue().setIfAbsent(key, value)) {
            return true;
        }
        String currentValue = stringRedisTemplate.opsForValue().get(key);
        //如果锁过期
        if (StringUtils.isEmpty(currentValue) && (Long.parseLong(currentValue) < System.currentTimeMillis())) {
            String oldValue = stringRedisTemplate.opsForValue().getAndSet(key, value);
            if (!StringUtils.isEmpty(oldValue) && oldValue.equals(value)) {
                return true;
            }
        }
        return false;
    }
     /**
     * 解锁
     * @param key
     * @param value
     */
    public void unLock(String key, String value) {
        try {
            String currentValue = stringRedisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
                stringRedisTemplate.opsForValue().getOperations().delete(key);
            }
        } catch (Throwable e) {
            log.error("redis分布式锁,解锁异常, {}", e.getMessage(), e);
        }
    }
}

调用加锁和解锁

public class ProjectService {

    private static final int TIMEOUT = 10 * 1000; //超时时间10秒

    @Autowired
    private RedisLock redisLock;

    /**
     *  秒杀调用接口
     * @param productId
     */
    public void orderProductMockDiffUser(String productId) {

        long time = System.currentTimeMillis() + TIMEOUT;
        if(!redisLock.lock(productId, String.valueOf(time))) {
            throw new SellException(10001, "人太多,请重新~");
        };

        redisLock.unLock(productId, String.valueOf(time));
    }
}

 使用Redis分布式锁要先熟悉两个命令:

--- 将key设置值为value,如果key不存在,则等同于SET命令。 当key存在时,什么也不做。SETNX是”SET if Not eXists”的简写

SETNX key value

--- 自动将key对应到value并且返回原来key对应的value。如果key存在但是对应的value不是字符串,就返回错误。

GETSET key value

四、基于ZooKeeper的分布式锁(贴一下别人的帖子)

https://www.cnblogs.com/nevermorewang/p/8306903.html

你可能感兴趣的:(架构,Redis,锁)