After searching hi and lo for the best way to run a cron job when deploying an app using on Amazon Elastic Beanstalk with auto-scaling enabled, I came across a few solutions.
Problem: the problem with running cron
on beanstalk (or auto-scaling cloud) is that every instance will have it's own cron daemon and the script will run many copies simultaneously (on each EC2 instance) when it auto-scales.
Solutions offered:
- Use a worker instance + SQS
- Problem: it's too complicated and I don't want to be billed for an additional instance for one simple cron job like sending an alert to the user.
- Use cronlock
- Problem: requires you to install a central redis sever.
My own solution:
My site already has a Mysql server (Amazon RDS) and so I was thinking that maybe this can work?
- I can create a table with just one field
last_run
. - Create the following script and add it to cron daemon instead:
LOCK TABLES crond WRITE
- Read the value in
crond
.last_run
- If
time()
-last_run
> 5 (i.e. 5 seconds have elapsed) then I update the time in thelast_run
field to currenttime
. - If
time()
-last_run
< 5 then I exit immediately saying, cron was executed less than 5 seconds ago (i.e. some other instance got the LOCK first) UNLOCK TABLES
.- Spawn the actual cron job script(s) if
last_run
> 5 (i.e. #3 is true)
Questions:
- Will this be sufficient to ensure that only one copy of cron runs at a time?
- Are there any easier alternatives to what I'm trying to achieve?
Your insights will be helpful before I design and test this thing.