How to Prevent Duplicate Scheduled Tasks in Distributed Systems with ElasticJob
This article explains why scheduled jobs run twice in a multi‑node deployment, shows how to isolate the timing logic into a single service, and demonstrates using ElasticJob with Zookeeper for sharding, distributed locks, and high‑availability to ensure each task executes exactly once.
When a microservice that handles orders is deployed on multiple machines, a daily scheduled job that fetches successful orders from the previous day can be triggered on every instance, causing duplicate processing.
Using the Quartz @Scheduled(cron = "0 0 10 * * ?") annotation works fine in a single‑node test environment, but in production each server runs the job at 10 am, leading to the same orders being sent twice.
One solution is to extract the timing logic into a dedicated "timed‑task" microservice that is deployed on only one machine. The service invokes the business‑logic APIs of the other microservices, and the load balancer decides which instance receives the call, eliminating duplicate execution.
However, a single‑node timed‑task service introduces a single‑point‑of‑failure risk. To mitigate this, you can run multiple instances of the timed‑task service and use a distributed lock (e.g., Redis SET key value NX EX or Zookeeper temporary nodes) so that only one instance acquires the lock and performs the job.
// Example using Redis for a distributed lock
@Scheduled(cron = "0 0 10 * * ?")
public void sendOrder() {
// try to acquire lock
if (SET key value expireTime NX) {
// only the lock holder calls the order RPC
callOrderRPC();
}
}ElasticJob provides a more robust way to achieve the same goal with built‑in sharding and high availability.
ElasticJob
ElasticJob is a job‑processing system that supports elastic sharding, allowing a job to be split across multiple instances.
Quick start with Spring Boot:
<dependency>
<groupId>org.apache.shardingsphere.elasticjob</groupId>
<artifactId>elasticjob-lite-spring-boot-starter</artifactId>
<version>3.0.1</version>
</dependency>Implement a SimpleJob:
package com.example.elasticjobtest;
@Slf4j
@Component
public class SpringBootJob implements SimpleJob {
@Override
public void execute(ShardingContext shardingContext) {
log.info("SpringBootJob, total shards [{}], current shard [{}], param [{}]",
shardingContext.getShardingTotalCount(),
shardingContext.getShardingItem(),
shardingContext.getShardingParameter());
}
}Configure in application.yml:
elasticjob:
regcenter:
serverlists: 127.0.0.1:2181
namespace: why-elastic-job
jobs:
springJob:
elasticJobClass: com.example.elasticjobtest.SpringBootJob
cron: 0/5 * * * * ?
shardingTotalCount: 2
shardingItemParameters: 0=Beijing,1=ShanghaiRunning two instances of the Spring Boot application shows that each instance receives a different shard parameter (Beijing or Shanghai), proving that ElasticJob distributes the work without duplication.
Demo Running
Start a local Zookeeper server (the registration center), then launch the demo. Logs every 5 seconds display:
2023-12-16 16:31:45.020 SpringBootJob, total shards [2], current shard [0], param [Beijing]
2023-12-16 16:31:45.020 SpringBootJob, total shards [2], current shard [1], param [Shanghai]Adding a third instance and increasing shardingTotalCount to 3 automatically creates three shards (0,1,2). Each instance processes only the data whose ID modulo 3 matches its shard parameter, e.g., shard 0 handles IDs 0,3,6,9.
ElasticJob’s Zookeeper nodes ( config, instances, sharding, servers, leader) store job configuration, running instances, shard assignments, and leader election information. The leader performs the sharding calculation, while other instances simply execute the assigned shard.
Key points from the source code:
The ListenerManager starts all Zookeeper listeners.
The ShardingService sets a resharding flag when the shard count or instance list changes.
Only the leader node runs the actual sharding algorithm.
Three built‑in sharding strategies are provided; they are straightforward to debug.
By understanding these mechanisms, you can read ElasticJob’s source code with confidence and adapt the framework to your own distributed scheduling needs.
In summary, ElasticJob solves the duplicate‑execution problem by combining Zookeeper‑based leader election, distributed locking, and sharding, allowing you to scale scheduled jobs across multiple machines safely.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Su San Talks Tech
Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
