【分布式】Redis分布式锁代码实现Demo

本文介绍了分布式锁实现的三个关键要素:原子性、正常和正确释放,并探讨了锁的高可用性策略。示例展示了如何使用Redis实现分布式锁的加锁和解锁操作。
摘要由CSDN通过智能技术生成

分布式锁实现要素

分布式锁实现注意几个要素:

  • 加锁过程原子性:加锁时首先判断key是否存在、是否有值,没有值再设置,这3个步骤需要是原子操作;
  • 锁正常释放:出现超时、网络等问题时,保证加的锁可以正常释放;
  • 锁正确释放:锁A释放时,需要保证只能由加A锁的客户端释放,否则可能就会出现误删锁;
  • 锁高可用保证:分布式锁如Redis或ZK出现宕机时,如何保证加锁功能不被影响,需要根据业务考虑到CP、CA抉择选择合适的实现方式;同时可以添加兜底逻辑,如使用CA模型的ZK分布式锁时,当出现分布式不可用时,可以退化成本地锁或MySQL实现的分布式锁等。

Redis分布式锁代码示例

下面代码实现了Redis分布式锁加锁、解锁的过程:

public interface DistributedLock {
   
    Lock obtainLock(String key);
}

public class RedisDistributedLock implements DistributedLock {
   

    private static final Logger logger = LoggerFactory.getLogger(RedisDistributedLock.class);
    /**
     * Get redis lock script.
     * param1 - KEYS[1]: redisKey
     * params2 -  ARGV[1]: clientId
     * params3 - ARGV[2]: expire time
     *
     */
    private static final String OBTAIN_LOCK_SCRIPT =
            "local lockClientId = redis.call('GET', KEYS[1])\n" +
                    "if lockClientId == ARGV[1] then\n" +
                    "  redis.call('PEXPIRE', KEYS[1], ARGV[2])\n" +
                    "  return true\n" +
                    "elseif not lockClientId then\n" +
                    "  redis.call('SET', KEYS[1], ARGV[1], 'PX', ARGV[2])\n" +
                    "  return true\n" +
                    "end\n" +
                    "return false";
    private final String clientId = UUID.randomUUID().toString();
    private final long expireTime;
    private final Map<String, RedisLocalLock> locks = new ConcurrentHashMap<>();
    private final StringRedisTemplate redisTemplate;
    private final RedisScript<Boolean> redisScript;
    private Executor executorService = Executors.newFixedThreadPool(2, new CustomerThreadFactory("Redis-Lock-Executor"));

    static class CustomerThreadFactory implements ThreadFactory {
   

        private String name;

        public CustomerThreadFactory(String name) {
   
            this.name = name;
        }

        @Override
        public Thread newThread(Runnable r) {
   
            return new Thread();
        }
    }

    /**
     * Prefix path of a redis key, usually use project name.
     * eg: in a order service(driver-order),
     *     order pay redis key like this: driver-order:order:pay:13932032323288
     *     order cancel redis key like this: driver-order:order:cance
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值