Spring中使用分布式任务同步ShedLock

💡 原文中文,约3400字,阅读约需8分钟。
📝

内容提要

本文介绍了使用ShedLock在Spring分布式系统中执行任务的方法,通过外部存储实现任务的同步执行,避免冲突和重复。文章提供了使用PostgreSQL作为外部存储的示例,并演示了创建锁表和配置Spring Boot项目的步骤。最后,介绍了ShedLock的使用方法和优势。

🔎

延伸解读

ShedLock 的“最多一次”语义与适用边界

ShedLock 保证计划任务“最多同时执行一次”,而非“恰好一次”。当某实例持有锁时,其他实例会直接跳过该次执行,不等待锁释放。因此它适合数据库清理、数据生成等允许偶尔跳过的任务;若业务要求每次触发都必须执行,则需额外补偿机制。

lockAtMostFor 与 lockAtLeastFor 的防护作用

lockAtMostFor 为锁设置最长持有时间,防止实例崩溃后锁被永久占用,示例中设为 50 秒。lockAtLeastFor 则确保锁至少保留一段时间,避免任务执行过快导致锁过早释放,同时减少实例间时钟不同步的影响。两者需根据任务实际耗时合理配置。

外部存储选型与数据库时间的重要性

ShedLock 依赖外部存储实现锁,支持 JDBC 关系数据库以及 Mongo、Redis、DynamoDB 等 NoSQL。示例使用 PostgreSQL 并创建 shedlock 表,配置中通过 usingDbTime() 使用数据库时间,有助于规避各实例本地时钟不一致带来的锁竞争问题。

❓

Q&A

ShedLock 是什么?它解决了分布式系统中的什么问题?

ShedLock 是一个用于在分布式系统中协调任务执行的库,它确保计划任务最多同时执行一次。它通过外部存储实现锁定,避免多个实例同时运行同一任务导致的冲突或重复。

ShedLock 支持哪些类型的外部存储?

ShedLock 支持通过 JDBC 工作的关系数据库(如 PostgreSQL、MySQL、Oracle 等),也支持 NoSQL 数据库(如 Mongo、Redis、DynamoDB)以及许多其他数据库。

如何在 Spring Boot 项目中配置 ShedLock?

需要添加依赖(如 shedlock-spring 和 shedlock-provider-jdbc-template),然后创建一个配置类,使用 @EnableScheduling 和 @EnableSchedulerLock 注解,并定义一个 LockProvider bean,例如使用 JdbcTemplateLockProvider 配置数据源。

使用 ShedLock 时,锁表需要哪些字段?

锁表需要包含 name(锁的唯一标识符)、lock_until(锁的过期时间)、locked_at(锁的获取时间)和 locked_by(获取锁的实例标识)字段,其中 name 是主键。

ShedLock 如何确保任务在多个实例中只执行一次?

当一个实例执行任务时,会在数据库中插入一条锁记录,其他实例尝试执行时会发现锁已存在,从而跳过执行。任务完成后,锁记录会被更新,释放锁。

ShedLock 中的 lockAtMostFor 和 lockAtLeastFor 参数有什么作用?

lockAtMostFor 设置锁的最大持有时间,防止实例崩溃后锁被永久占用;lockAtLeastFor 设置锁的最小持有时间,避免任务执行过快导致锁过早释放,确保任务不会在短时间内重复执行。

🏷️

标签

➡️

继续阅读