zoukankan      html  css  js  c++  java
  • redis实现分布式锁

    1.锁的处理

    • 单应用中(单进程多线程情况)锁的处理:
      • synchronized
      • lock
    • 分布式应用中锁的处理:
      • 数据库乐观锁;
      • 基于zookeeper的分布式锁;
      • 基于redis的分布式锁

    2.分布式锁需要注意事项

    • 互斥性: 在任意时刻,只有一个客户端能持有锁
    • 同一性:   加锁和解锁必须是同一个客户端,客户端自己不能把别的客户端加的锁给解了
    • 避免死锁:  即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁 

    3.获取锁

    方式一:使用set命令实现

     代码如下:

    /**
         * 使用redis的set命令实现获取分布式锁
         * @param lockKey       可以就是锁
         * @param requestId        请求ID,保证同一性
         * @param expireTime    过期时间,避免死锁
         * @return
         */
        public static boolean getLock(String lockKey,String requestId,int expireTime) {
            //NX:保证互斥性
            String result = jedis.set(lockKey, requestId, "NX", "EX", expireTime);
            if("OK".equals(result)) {
                return true;
            }
            
            return false;
        }
    方式二:使用setnx命令,这里使用synchronized保证方法的原子性
    1 public static synchronized boolean Lock2(String lockKey,String requestId,int expireTime) {
    2         Long result = jedis.setnx(lockKey, requestId);
    3         if(result == 1) {
    4             jedis.expire(lockKey, expireTime);
    5             return true;
    6         }
    7 
    8         return false;
    9     }

    4.释放锁

    方式一:使用del命令

        /**
         * 释放分布式锁
         * @param lockKey
         * @param requestId
         */
        public static void releaseLock(String lockKey,String requestId) {
            if (requestId.equals(jedis.get(lockKey))) {
                jedis.del(lockKey);
            }
        }

    方式二:使用Lua脚本

    public static boolean releaseLock(String lockKey, String requestId) {
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
    
            if (result.equals(1L)) {
                return true;
            }
            return false;
        }
  • 相关阅读:
    centos8.0 安装 jenkins
    No match for argument: mysql-community-server Error: Unable to find a match: mysql-community-server
    Navicat 远程连接 centos8.0
    centos8.0 安装 mysql
    -bash: java-version: command not found
    centos8.0 安装 JDK1.8
    [Err] 1062
    android之Fragment基础详解(一)
    Android之RecyclerView(一)
    Android之ProgressBar
  • 原文地址:https://www.cnblogs.com/kiwi-deng/p/11608874.html
Copyright © 2011-2022 走看看