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_runfield 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.