Redis分布式锁

package com.das.service.lock;

import com.das.common.constant.EtcConstant;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Author liangmy
 * @Date 2019/10/23
 */
public interface LockService {

    /**
     * liangmy
     *
     * @param carOwnerUserId
     * @param strategy
     * @return
     */
    Object doSomething2(Long carOwnerUserId, EtcConstant.UserMoneyConstant.ModifyMoneyProgress strategy);

    /**
     * 分布式锁 一
     * 一般是使用 setnx(set if not exists) 指令,只允许被一个客户端占用资源。先来先占,用完了,再调用 del 指令释放资源
     * 但是有个问题,如果逻辑执行到中间出现异常了,可能会导致 del 指令没有被调用,这样 就会陷入死锁,锁永远得不到释放
     * 于是我们在拿到锁之后,再给锁加上一个过期时间,比如 5s,这样即使中间出现异常也 可以保证 5 秒之后锁会自动释放。
     * 但是以上逻辑还有问题。如果在 setnx 和 expire 之间服务器进程突然挂掉了,可能是因 为机器掉电或者是被人为杀掉的,就会导致 expire 得不到执行,也会造成死锁。
     * Redis 2.8 版本中作者加入了 set 指令的扩展参数,使得 setnx 和 expire 指令可以一起执行
     * set key value [EX seconds] [PX milliseconds] [NX|XX]
     *
     * @param carOwnerUserId
     * @param strategy
     * @return
     */
    Object doSomething3(Long carOwnerUserId, EtcConstant.UserMoneyConstant.ModifyMoneyProgress strategy);

    /**
     * 分布式锁 二 : 超时问题
     * 如果在加锁和释放锁之间的逻辑执行的太长,以至 于超出了锁的超时限制,就会出现问题。
     * 因为这时候锁过期了,第二个线程重新持有了这把锁, 但是紧接着第一个线程执行完了业务逻辑,就把锁给释放了,
     * 第三个线程就会在第二个线程逻 辑执行完之间拿到了锁。
     * 安全的方案是为 set 指令的 value 参数设置为一个随机数,释放锁时先匹配 随机数是否一致,然后再删除 key
     * 但是匹配 value 和删除 key 不是一个原子操作,这就需要使用 Lua 脚本来处理了,因为 Lua 脚本可 以保证连续多个指令的原子性执行。
     * if redis.call("get",KEYS[1]) == ARGV[1] then
     *     return redis.call("del",KEYS[1])
     * else
     *     return 0
     * end
     *
     * @param carOwnerUserId
     * @param strategy
     * @return
     */
    Object doSomething4(Long carOwnerUserId, EtcConstant.UserMoneyConstant.ModifyMoneyProgress strategy);
}

 

你可能感兴趣的:(Redis)