Redis锁的实现方式

rredis 单机版锁最终解决方案解决 setnx+lua脚本一致性

RedisTemplate 配置

@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate redisTemplate = new RedisTemplate();

    redisTemplate.setConnectionFactory(redisConnectionFactory);

    GenericJackson2JsonRedisSerializer redisSerializer = new GenericJackson2JsonRedisSerializer();

    redisTemplate.setDefaultSerializer(redisSerializer);

    return redisTemplate;
}

@Component
public class RedisHandler {


    private final Logger logger = LoggerFactory.getLogger(RedisHandler.class);

    @Autowired
    RedisTemplate redisTemplate;
    

    public Object luaReleaseLock(String key, String value) {

        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end ";

        DefaultRedisScript<Integer> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(script);
        redisScript.setResultType(Integer.class);

        redisTemplate.execute(redisScript, Collections.singletonList(key), value);

        return null;

    }

}

业务逻辑

@RestController
public class GoodController {
  public static final String REDIS_LOCK_KEY = "redisLockPay";

  @Autowired private StringRedisTemplate stringRedisTemplate;

  @Value("${server.port}")
  private String serverPort;

  @GetMapping("/buy_goods")
  public String buy_Goods() {
    String value = UUID.randomUUID().toString() + Thread.currentThread().getName();

    try {
      Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK_KEY, value, 30L, TimeUnit.SECONDS);
      if (!flag) {
        return "抢夺锁失败,请下次尝试";
      }
      String result = stringRedisTemplate.opsForValue().get("goods:001");
      int goodsNumber = result == null ? 0 : Integer.parseInt(result);
      if (goodsNumber > 0) {
        int realNumber = goodsNumber - 1;
        stringRedisTemplate.opsForValue().set("goods:001", realNumber + "");
        System.out.println("你已经成功秒杀商品,此时还剩余:" + realNumber + "件" + "\t 服务器端口:" + serverPort);
        return "你已经成功秒杀商品,此时还剩余:" + realNumber + "件" + "\t 服务器端口:" + serverPort;
      } else {
        System.out.println("商品已经售罄/活动结束/调用超时,欢迎下次光临" + "\t 服务器端口:" + serverPort);
      }
      return "商品已经售罄/活动结束/调用超时,欢迎下次光临" + "\t 服务器端口:" + serverPort;
    } finally {
      String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end ";
      try {
        DefaultRedisScript<Integer> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(script);
        redisScript.setResultType(Integer.class);
        Integer result = stringRedisTemplate.execute(redisScript, Collections.singletonList(REDIS_LOCK_KEY), value);
        if ("1".equals(result.toString())) {
          System.out.println("------del REDIS_LOCK_KEY success");
        } else {
          System.out.println("------del REDIS_LOCK_KEY error");
        }
      } finally {
          
      }
    }
  }
}

rredis 分布式锁最终解决方案解决 redisson

@RestController
public class GoodController
{
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    public static final String KEY = "atguiguLock_0511";

    @Value("${server.port}")
    private String serverPort;
    @Autowired
    private Redisson redisson;

    @GetMapping("/buy_goods")
    public String buy_Goods() throws Exception
    {
        RLock redissonLock = redisson.getLock(KEY);
        redissonLock.lock();
        try {

            String result = stringRedisTemplate.opsForValue().get("goods:001");
            int goodsNumber = result == null ? 0 : Integer.parseInt(result);
            if(goodsNumber > 0) {
                int realNumber = goodsNumber - 1;
                stringRedisTemplate.opsForValue().set("goods:001",realNumber + "");
                System.out.println("你已经成功秒杀商品,此时还剩余:" + realNumber + "件"+"\t 服务器端口:"+serverPort);
                return "你已经成功秒杀商品,此时还剩余:" + realNumber + "件"+"\t 服务器端口:"+serverPort;
            }else{
                System.out.println("商品已经售罄/活动结束/调用超时,欢迎下次光临"+"\t 服务器端口:"+serverPort);
            }
            return "商品已经售罄/活动结束/调用超时,欢迎下次光临"+ "\t 服务器端口:"+serverPort;
        } finally {
            if(redissonLock.isLocked() && redissonLock.isHeldByCurrentThread())
            {
                redissonLock.unlock();
            }
        }

    }
}

QQ浏览器截图20210722001543.png

QQ浏览器截图20210722002753.png

Redis分布式锁的实现方式 QQ浏览器截图20210722002946  副本.png

QQ浏览器截图20210722002946.png