redis分布式锁


由 黄森明创建, 最后修改于2022-七月-11,
1.配置类
@Primary
@Bean(“clusterObjectRedisTemplate”)
public RedisTemplate<String, Object> objectTemplate(RedisConnectionFactory factory) {

RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// key采用String的序列化方式
template.setKeySerializer(new StringRedisSerializer());
// value序列化方式采用jackson
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;

}
2.获取锁
2.1 lua脚本
private static final String TRY_LOCK_SCRIPT =
“if redis.call(‘SET’,KEYS[1], ARGV[1], ‘NX’, ‘EX’, ARGV[2]) ” +
“then ” +
” return 1 ” +
“else” +
” return 0 ” +
“end”;
2.2 获取锁
/**

  • 获取锁,获取锁成功返回true,获取失败返回false

  • @param lockKey 锁key值

  • @param identify 锁value值,通过value对比释放锁

  • @param expireMillisecond 过期时间

  • @return
    /
    public Boolean lock(String lockKey, String identify, Long expireMillisecond) {
    try {
    RedisScript redisScript = new DefaultRedisScript<>(TRY_LOCK_SCRIPT, Long.class);
    Object result = objectTemplate.execute(redisScript, Collections.singletonList(lockKey), identify, expireMillisecond);
    if (LOCK_SUCCESS.equals(result)) {
    return Boolean.TRUE;
    }
    } catch (Exception e) {
    logger.error(“获取锁失败,lockKey=[{}], identify=[{}]”, lockKey, identify, e);
    }
    return Boolean.FALSE;
    }
    2.3 尝试多次获取锁
    /
    *

  • 尝试获取锁

  • @param key

  • @param value

  • @param expireMillisecond 过期时间

  • @param waitMillisecond 等待锁的时间
    */
    public Boolean tryLock(String key,String value, Long expireMillisecond, Long waitMillisecond) {
    while(waitMillisecond > 0 ){
    Boolean lockFlag = lock(key, value, expireMillisecond);
    if(lockFlag) {
    return true;
    }else{
    try {
    Thread.sleep(INTERVAL_MILLISECOND);
    } catch (InterruptedException e) {
    logger.error(“睡眠中断”,e);
    }
    waitMillisecond = waitMillisecond – INTERVAL_MILLISECOND;
    }

    }
    return false;
    }
    3.释放锁
    3.1 lua脚本
    private static final String RELEASE_LOCK_SCRIPT =
    “if redis.call(‘get’, KEYS[1]) == ARGV[1] ” +
    “then ” +
    ” return redis.call(‘del’, KEYS[1]) ” +
    “else ” +
    ” return 0 ” +
    “end”;
    3.2 释放锁
    /**

  • 释放锁,释放成功返回true,释放失败返回false

  • @param lockKey 锁key值

  • @param identify 判断锁value是否相同,相同才释放锁

  • @return
    /
    public Boolean unLock(String lockKey, String identify) {
    try {
    RedisScript redisScript = new DefaultRedisScript<>(RELEASE_LOCK_SCRIPT, Long.class);
    Object result = objectTemplate.execute(redisScript, Collections.singletonList(lockKey), identify);
    if (LOCK_SUCCESS.equals(result)) {
    return Boolean.TRUE;
    }
    } catch (Exception e) {
    logger.error(“解锁失败,lockKey=[{}], identify=[{}]”, lockKey, identify, e);
    }
    return Boolean.FALSE;
    }
    4.获取锁测试
    @Test
    public void testLock() throws InterruptedException {
    int threadCount = 4;
    CountDownLatch countDownLatch = new CountDownLatch(threadCount);
    ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
    int j = 1;
    for (int i = 0; i < threadCount; i++) {
    executorService.submit(() -> {
    String uuid = UUIDUtil.getUUID();
    Boolean lock = redisUtil.tryLock(“a12312312312dadq”, uuid, 8 * 1000L,6
    1000L);
    if (lock) {
    try {
    log.error(“线程[{}]正在执行中,uuid:{}”, Thread.currentThread().getName(), uuid);
    try {
    Thread.sleep(7000);
    log.error(“线程[{}]执行完毕”, Thread.currentThread().getName());
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    } finally {
    boolean releaseResult = redisUtil.unLock(“a12312312312dadq”, uuid);
    log.error(“线程[{}]释放redis,uuid:{},释放状态:{}”, Thread.currentThread().getName(), uuid, releaseResult);
    }
    } else {
    log.error(“线程[{}]获取锁失败”, Thread.currentThread().getName());
    }
    countDownLatch.countDown();
    }, j++);
    }
    countDownLatch.await();
    }

原创文章,作者:sunnyman218,如若转载,请注明出处:https://blog.ytso.com/tech/database/275305.html

(0)
上一篇 2022年7月19日 03:43
下一篇 2022年7月19日 03:43

相关推荐

发表回复

登录后才能评论