django_cron默认锁机制失效:多服务器任务重复执行排查
Let me walk through the key issues here and how to resolve them:
1. Default Locking Doesn’t Work Across Servers
The django_cron 0.5.0 package uses local file-based locking (FileLock) by default. Since each of your 3 servers has its own independent filesystem, this lock won’t be shared between them—so every server thinks it’s safe to run the task when its crontab triggers.
To fix this, you need to switch to a database-backed lock that works across all servers (since they share the same Django database). Add this setting to your settings.py:
DJANGO_CRON_LOCK_CLASS = "django_cron.lock.DatabaseLock"
Don’t forget to run the migrations to create the necessary lock tables for django_cron:
python manage.py migrate django_cron
This will create tables like django_cron_cronjoblock that track active locks across all servers.
2. Crontab Frequency vs. Task Schedule
You mentioned your crontab runs every 20 minutes, while your task is set to run every 60 minutes. django_cron is designed to handle this—it checks if the task is due to run each time the crontab triggers it. However, without the shared lock, each server will independently check and run the task when the 60-minute mark hits.
Once you set up the database lock, even with a 20-minute crontab interval, only one server will be able to acquire the lock and run the task at the scheduled time. Just make sure all servers have synchronized system clocks (use NTP) to avoid timing mismatches.
3. Verify Task Uniqueness
Your task already has the required unique code = 'CreateMissingItems'—this is correct, as django_cron uses this identifier to track task execution history and locks. No changes needed here, but double-check that this code is identical across all server deployments.
Post-Fix Validation
- After applying the migration, check your database for the
django_cron_cronjoblocktable. When the task runs, you should see a single lock entry (not one per server). - Monitor your task logs to confirm it only runs once per hour across all servers.
内容的提问来源于stack exchange,提问作者user2880391

