美文网首页
基于Redis封装分布式锁

基于Redis封装分布式锁

作者: linrol | 来源:发表于2018-06-15 10:24 被阅读0次

    基于Redis的分布式锁封装记录

    • 首先搭建一个基于Redis Server端(略过)
    • Redis客户端连接池工具类(RedisPool.java)的封装
      • 利用类的static块初始化连接池
      • 初始化的参数包含最大连接数、最大空闲连接数、最小空闲连接数等基本参数


        image.png
    • 初始化连接池时读取mvc.default.properties配置文件中的jedis-pool配置,该配置值格式为:host,port连接到redis中,后续项目中可配置此自定义
    • 封装的加锁操作分为非阻塞锁和阻塞锁,阻塞锁下封装了自定义失效时间锁和默认失效时间(10s)锁
    Jedis jedis = RedisPool.getJedis();
    String result = jedis.set(key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
    RedisPool.close(jedis);
    
    • 阻塞锁的实现基于for(;;)循环,防止Cpu一直消耗,在循环体内加入Thread.sleep()保证时间片切换
    for (;;) {
      Jedis jedis = RedisPool.getJedis();
      String result = jedis.set(key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, 10 * TIME);
      RedisPool.close(jedis);
      if (LOCK_SUCCESS.equals(result)) {
        break;
      }
      // 防止一直消耗 CPU
      Thread.sleep(100);
    }
    
    • 释放锁时需要调用Lua脚本来完成,传统的释放锁会涉及get到资源,然后del掉,使用Java client语法操作两个步骤不能保障原子性,所以在此采用Lua脚本来保证get和del为原子操作
    public static boolean unlock(String key, String request) {
      String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
      Jedis jedis = RedisPool.getJedis();
      Object result = jedis.eval(script, Collections.singletonList(key), Collections.singletonList(request));
      RedisPool.close(jedis);
      if (RELEASE_SUCCESS.equals(result)) {
        return true;
      }
      return false;
    }
    

    相关文章

      网友评论

          本文标题:基于Redis封装分布式锁

          本文链接:https://www.haomeiwen.com/subject/qoojeftx.html