【锁】定时任务推送数据-redission加锁实例优化

文章目录

  • redission 加锁代码-有问题
  • 优化代码
  • 看门狗是什么?

redission 加锁代码-有问题

    /**
     * 收货入库物料标签(包装码)推送接口
     *
     * @throws Exception
     */
    public void synReceiveMaterialTags() throws Exception {
        String tag = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        String key = RedisKeyPre.synReceiveMaterialTagsLock;
        RLock rLock = redissonClient.getLock(key);
        try {
            // 尝试加锁,最多等待3秒,上锁以后1200秒自动解锁,没有Watch Dog,1200s后自动释放
            boolean res = rLock.tryLock(3, 1200, TimeUnit.SECONDS);
            if (!res) {
                Log.info(LogBuilder.builder().business("synReceiveMaterialTags:" + tag + ":获取锁失败,稍后重试").build());
                return;
            } else {
                wmsSyncService.synReceiveMaterialTags();
            }
        } catch (Exception e) {
            Log.error(LogBuilder.builder().business("synReceiveMaterialTags error:" + e).build());
        } finally {
            releaseLock(rLock);
        }
    }

    private void releaseLock(RLock rLock) {
        if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
            rLock.unlock();
        }
    }

rLock.tryLock(3, 1200, TimeUnit.SECONDS)表示尝试获取锁,最多等待3秒,锁的持有时间为1200秒(20分钟),超过持有时间后锁会自动释放。这样可以避免锁被长时间占用,提高代码的健壮性和性能。

如果不需要等待时间和自动释放时间,可以将tryLock()方法的参数调整为rLock.tryLock(),这样会立即尝试获取锁,如果锁不可用,则立即返回结果。但是需要注意,这样可能会导致线程频繁尝试获取锁,增加系统负载和竞争,需要根据具体情况进行评估和调整。

【锁】定时任务推送数据-redission加锁实例优化_第1张图片

优化代码

这段代码存在一些问题:

  1. 异常处理不够详细:在synReceiveMaterialTags方法中,捕获了异常并记录了错误日志,但没有对异常进行具体的处理。建议根据实际情况,对异常进行适当的处理,例如回滚事务、发送通知等。

  2. 锁的释放方式不正确:在releaseLock方法中,使用isLocked和isHeldByCurrentThread方法来判断锁是否被当前线程持有,并进行解锁操作。然而,这种方式可能存在并发问题,因为在判断锁状态和解锁之间,其他线程可能已经获取了锁并修改了锁状态。建议使用try-finally语句来确保锁的正确释放,无论是否发生异常。

  3. 日志记录不规范:在日志记录中,使用了字符串拼接的方式来构建日志信息。建议使用日志框架,如Log4j或Slf4j,来记录日志,并使用占位符或参数化日志的方式,以提高性能和可读性。

优化后的代码示例:

public void synReceiveMaterialTags() {
	String tag = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
	String key = RedisKeyPre.synReceiveMaterialTagsLock;
	RLock rLock = redissonClient.getLock(key);
	try {
		// 尝试加锁,最多等待3秒,上锁以后1200秒自动解锁,没有Watch Dog,1200s后自动释放
		boolean res = rLock.tryLock(3, 1200, TimeUnit.SECONDS);
		if (!res) {
			Log.info("synReceiveMaterialTags:{}:获取锁失败,稍后重试", tag);
		return;
		} else {
		wmsSyncService.synReceiveMaterialTags();
		}
	} catch (Exception e) {
	Log.error("synReceiveMaterialTags error:{}", e);
	// 异常处理逻辑
	} finally {
		try {
		rLock.unlock();
		} catch (IllegalStateException e) {}
		// 锁已经

看门狗是什么?

在这段代码中,"没有Watch Dog"是指在加锁的过程中没有使用监视器(watchdog)来监控锁的状态。通常情况下,当一个线程获取了锁但在一定时间内没有释放锁时,监视器会检测到这种情况并自动释放锁,以防止死锁的发生。

在这段代码中,锁的超时时间设置为1200秒,但没有使用监视器来监控锁的状态。这意味着如果某个线程获取了锁后,在1200秒内没有释放锁,其他线程将无法获取到锁,可能会导致程序出现长时间的等待或阻塞。

为了避免这种情况,建议在加锁时使用监视器来监控锁的状态,并在一定时间内自动释放锁,以提高程序的健壮性和性能。

你可能感兴趣的:(java,spring,boot,spring,redis)