有时 Redlock 锁 Key 会同时被多个实例获取

问题描述 投票:0回答:1

在 Nestjs 中,我有一个 cron 作业,如果使用 Redlock 存在应用程序的多个实例,我想执行一次:

    @Cron('*/1 * * * * *')
    async test(): Promise<void> {

        try {
            const lockKey = 'test-cron-job-lock';
            const lock = await this.redisService.acquireLock(lockKey, 1000); // 1 second
            this.logger.log(`Cron job at ${this.getTimeWithoutMilliseconds()}`);

            await this.redisService.releaseLock(lock);
        } catch (e) {
            this.logger.error('Error in test cron job');
        }
    }

它可以工作,但有时

lockKey
会同时被多个实例获取。

应用程序A:

[Nest] 8872  - 10/04/2024, 4:06:48 PM     LOG Cron job at 2024-10-04T13:06:48Z
[Nest] 8872  - 10/04/2024, 4:06:49 PM   ERROR Error in test cron job
[Nest] 8872  - 10/04/2024, 4:06:50 PM   ERROR Error in test cron job
[Nest] 8872  - 10/04/2024, 4:06:51 PM     LOG Cron job at 2024-10-04T13:06:51Z
[Nest] 8872  - 10/04/2024, 4:06:52 PM     LOG Cron job at 2024-10-04T13:06:52Z
[Nest] 8872  - 10/04/2024, 4:06:53 PM     LOG Cron job at 2024-10-04T13:06:53Z

应用程序B:

[Nest] 8886  - 10/04/2024, 4:06:48 PM   ERROR Error in test cron job
[Nest] 8886  - 10/04/2024, 4:06:49 PM     LOG Cron job at 2024-10-04T13:06:49Z
[Nest] 8886  - 10/04/2024, 4:06:50 PM     LOG Cron job at 2024-10-04T13:06:50Z
[Nest] 8886  - 10/04/2024, 4:06:51 PM   ERROR Error in test cron job
[Nest] 8886  - 10/04/2024, 4:06:52 PM   ERROR Error in test cron job
[Nest] 8886  - 10/04/2024, 4:06:53 PM     LOG Cron job at 2024-10-04T13:06:53Z

如您所见,两个实例都在

2024-10-04T13:06:53Z
处运行作业。为什么?

redis nestjs locking
1个回答
0
投票

通常,

Redlock
的竞争条件很少见,但由于您在同一时间设置 cron 并且锁定 TTL 很短,因此偶尔发生一次竞争是可能的。

解决这个问题的方法很少,各有利弊 -

  1. 较长时间获得TTL,不完美但会减少比赛的机会。
  2. 抖动——添加随机延迟。确保延迟不长于 TTL,否则你会得到双重动作。
  3. 获取后使用
    SET
    NX
    以及
    EX
    和TTL作为参数,类似
    SET "running" NX EX 10
    ——如果key已经设置,你会得到null,否则你会得到
    OK
    ,这是原子的操作,因此不可能进行比赛,但在这种情况下,我会保留锁并单独使用该装置。
    EX
    确保按键在一段时间后释放。

一般来说,我会说

Redlock
适合您无法预测行为的情况,并且您希望确保始终只有一个客户拥有它。 但是,如果它们都同时开始,执行时间大约相同,并且您需要完全原子的东西,我会使用
SET key NX EX sec
并稍微抖动,您就是非常出色的子弹教授。

© www.soinside.com 2019 - 2024. All rights reserved.