Redisson分布式锁封装-高级封装

Redisson工具介绍

  1. 锁是保护资源的一种实现方式,事务也是受保护的资源,所以必须是锁包裹事务,事务必须要在锁内执行
  2. 此工具类方便快捷的使用redis分布式锁,提高开发效率
  3. 完整代码封装如下:不废话直接上代码
//RedissonLockException
public class RedissonLockException extends RuntimeException {

    public RedissonLockException(String message) {
        super(message);
    }

    public RedissonLockException(String message, Throwable cause) {
        super(message, cause);
    }

    public RedissonLockException(Throwable cause) {
        super(cause);
    }

    public RedissonLockException() {
        super();
    }
}
//RedissonLockWorker
public interface RedissonLockWorker<T> {

    /**
     * 获取锁成功后执行业务逻辑
     *
     * @return 业务逻辑对象
     * @throws Exception 异常信息
     */
    T execute() throws Exception;
}
//RedissonLockService
public interface RedissonLockService {

    boolean lock(String lockName) throws Exception;

    <T> T lock(String lockName, RedissonLockWorker<T> worker);

    <T> T lock(String lockName, int lockTime, RedissonLockWorker<T> worker);

    <T> T multiLock(List<String> lockNames, RedissonLockWorker<T> worker);

    <T> T multiLock(List<String> lockNames, int lockTime, RedissonLockWorker<T> worker);

    void lockVoid(String lockName, RedissonLockWorker<Void> worker);

    void lockVoid(String lockName, int lockTime, RedissonLockWorker<Void> worker);

    void multiLockVoid(List<String> lockNames, RedissonLockWorker<Void> worker);

    void multiLockVoid(List<String> lockNames, int lockTime, RedissonLockWorker<Void> worker);

    void unLock(String lockName);


    //以下是携带事务的锁
    <T> T lockTransaction(String lockName, RedissonLockWorker<T> worker);

    <T> T lockTransaction(String lockName, int lockTime, RedissonLockWorker<T> worker);

    <T> T multiLockTransaction(List<String> lockNames, RedissonLockWorker<T> worker);

    <T> T multiLockTransaction(List<String> lockNames, int lockTime, RedissonLockWorker<T> worker);


    void lockTransactionVoid(String lockName, RedissonLockWorker<Void> worker);

    void lockTransactionVoid(String lockName, int lockTime, RedissonLockWorker<Void> worker);

    void multiLockTransactionVoid(List<String> lockNames, RedissonLockWorker<Void> worker);

    void multiLockTransactionVoid(List<String> lockNames, int lockTime, RedissonLockWorker<Void> worker);


}
//RedissonLocker
@Component
@Slf4j
@RequiredArgsConstructor
public class RedissonLocker implements RedissonLockService {

    private static final int LOCK_EXPIRE = 30;
    private static final int MAX_WAIT_TIME = 10;
    private final RedissonClient redissonClient;
    private final TransactionTemplate transactionTemplate;

    private RedissonMultiLock getMultiLock(List<String> lockNames) {
        if (CollectionUtil.isEmpty(lockNames)) {
            throw new IllegalArgumentException("lockNames cannot be empty");
        }
        RLock[] locks = new RLock[lockNames.size()];
        for (int i = 0; i < lockNames.size(); i++) {
            locks[i] = getLock(lockNames.get(i));
        }
        return new RedissonMultiLock(locks);
    }

    private RLock getLock(String lockName) {
        if (StrUtil.isBlank(lockName)) {
            throw new IllegalArgumentException("lockName cannot be empty");
        }
        return redissonClient.getLock(lockName);
    }

    private <T> T executeWithLock(RLock lock, int lockTime, RedissonLockWorker<T> worker) {
        boolean acquired = false;
        try {
            acquired = lock.tryLock(MAX_WAIT_TIME, lockTime, TimeUnit.SECONDS);
            if (acquired) {
                String lockName = (lock instanceof RedissonMultiLock) ? "multi-lock" : lock.getName();
                log.info("Thread {} acquired lock {}", Thread.currentThread().getName(), lockName);
                return worker.execute();
            } else {
                String lockName = (lock instanceof RedissonMultiLock) ? "multi-lock" : lock.getName();
                log.error("Thread {} failed to acquire lock {}", Thread.currentThread().getName(), lockName);
                throw new RedissonLockException("系统业务繁忙,请稍后再试");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            String lockName = (lock instanceof RedissonMultiLock) ? "multi-lock" : lock.getName();
            log.error("Thread {} was interrupted while acquiring lock {}", Thread.currentThread().getName(), lockName, e);
            throw new RedissonLockException("系统异常终止,请稍后再试");
        } catch (Exception e) {
            Thread.currentThread().interrupt();
            String lockName = (lock instanceof RedissonMultiLock) ? "multi-lock" : lock.getName();
            log.error("Thread {} was interrupted while acquiring lock {}", Thread.currentThread().getName(), lockName, e);
            throw new RedissonLockException("系统未知异常,请稍后再试");
        } finally {
            if (acquired) {
                try {
                    lock.unlock();
                    String lockName = (lock instanceof RedissonMultiLock) ? "multi-lock" : lock.getName();
                    log.info("Thread {} released lock {}", Thread.currentThread().getName(), lockName);
                } catch (Exception e) {
                    String lockName = (lock instanceof RedissonMultiLock) ? "multi-lock" : lock.getName();
                    log.error("Thread {} failed to release lock {}", Thread.currentThread().getName(), lockName, e);
                }
            }
        }
    }


    private <T> T executeWithTransaction(RLock lock, int lockTime, RedissonLockWorker<T> worker) {
        return executeWithLock(lock, lockTime, () -> {
            return transactionTemplate.execute(status -> {
                try {
                    return worker.execute();
                } catch (Exception e) {
                    status.setRollbackOnly();
                    log.error("Execution failed within the lock, transaction rolled back", e);
                    throw new RuntimeException("系统执行异常,请稍后再试");
                }
            });
        });
    }

    @Override
    public boolean lock(String lockName) {
        RLock rLock = getLock(lockName);
        return executeWithLock(rLock, LOCK_EXPIRE, () -> true);
    }


    @Override
    public <T> T lock(String lockName, RedissonLockWorker<T> worker) {
        return lock(lockName, LOCK_EXPIRE, worker);
    }


    @Override
    public <T> T lock(String lockName, int lockTime, RedissonLockWorker<T> worker) {
        RLock rLock = getLock(lockName);
        return executeWithLock(rLock, lockTime, worker);
    }


    @Override
    public <T> T multiLock(List<String> lockNames, RedissonLockWorker<T> worker) {
        return multiLock(lockNames, LOCK_EXPIRE, worker);
    }


    @Override
    public <T> T multiLock(List<String> lockNames, int lockTime, RedissonLockWorker<T> worker) {
        RedissonMultiLock multiLock = getMultiLock(lockNames);
        return executeWithLock(multiLock, lockTime, worker);
    }


    @Override
    public void lockVoid(String lockName, RedissonLockWorker<Void> worker) {
        lockVoid(lockName, LOCK_EXPIRE, worker);
    }

    @Override
    public void lockVoid(String lockName, int lockTime, RedissonLockWorker<Void> worker) {
        RLock rLock = getLock(lockName);
        executeWithLock(rLock, lockTime, () -> {
            worker.execute();
            return null;
        });
    }


    @Override
    public void multiLockVoid(List<String> lockNames, RedissonLockWorker<Void> worker) {
        multiLockVoid(lockNames, LOCK_EXPIRE, worker);
    }

    @Override
    public void multiLockVoid(List<String> lockNames, int lockTime, RedissonLockWorker<Void> worker) {
        RedissonMultiLock multiLock = getMultiLock(lockNames);
        executeWithLock(multiLock, lockTime, () -> {
            worker.execute();
            return null;
        });
    }


    @Override
    public void unLock(String lockName) {
        RLock rLock = getLock(lockName);
        if (rLock.isLocked()) {
            log.info("Thread {} is releasing the lock {}", Thread.currentThread().getName(), lockName);
            try {
                rLock.unlock();
                log.info("Thread {} released the lock {}", Thread.currentThread().getName(), lockName);
            } catch (Exception e) {
                log.error("Thread {} failed to release lock {}", Thread.currentThread().getName(), lockName, e);
            }
        } else {
            log.error("Thread {} tried to release a lock it does not hold {}", Thread.currentThread().getName(), lockName);
        }
    }

    @Override
    public <T> T lockTransaction(String lockName, RedissonLockWorker<T> worker) {
        return lockTransaction(lockName, LOCK_EXPIRE, worker);
    }


    @Override
    public <T> T lockTransaction(String lockName, int lockTime, RedissonLockWorker<T> worker) {
        RLock rLock = getLock(lockName);
        return executeWithTransaction(rLock, lockTime, worker);
    }

    @Override
    public <T> T multiLockTransaction(List<String> lockNames, RedissonLockWorker<T> worker) {
        return multiLockTransaction(lockNames, LOCK_EXPIRE, worker);
    }

    @Override
    public <T> T multiLockTransaction(List<String> lockNames, int lockTime, RedissonLockWorker<T> worker) {
        RedissonMultiLock multiLock = getMultiLock(lockNames);
        return executeWithTransaction(multiLock, lockTime, worker);
    }

    @Override
    public void lockTransactionVoid(String lockName, RedissonLockWorker<Void> worker) {
        lockTransactionVoid(lockName, LOCK_EXPIRE, worker);
    }

    @Override
    public void lockTransactionVoid(String lockName, int lockTime, RedissonLockWorker<Void> worker) {
        RLock rLock = getLock(lockName);
        executeWithTransaction(rLock, lockTime, () -> {
            worker.execute();
            return null;
        });
    }


    @Override
    public void multiLockTransactionVoid(List<String> lockNames, RedissonLockWorker<Void> worker) {
        multiLockTransactionVoid(lockNames, LOCK_EXPIRE, worker);
    }


    @Override
    public void multiLockTransactionVoid(List<String> lockNames, int lockTime, RedissonLockWorker<Void> worker) {
        RedissonMultiLock multiLock = getMultiLock(lockNames);
        executeWithTransaction(multiLock, lockTime, () -> {
            worker.execute();
            return null;
        });
    }


}

使用范例

    @Override
    public R distributionGiftPack(DistributionGiftPackDTO dto) {
        if (dto == null) {
            return R.failed("参数不能为空");
        }
        //TODO 其他参数判断
        return redissonLockService.lockTransaction(ActivityRedisKey.AC_KEY + dto.getActivityId(), () -> {
            virtualService.distributionGiftPack(dto.getActivityId(), dto.getCustomId(), dto.getCustomName(), dto.getOrderId(), dto.getGoodsIdList());
            return R.ok();
        });
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值