This is a very wide topic. And there are many options to achieve this.
-
You can configure your application to have multiple profiles. For example use another profile ‘cron’ . And start your application on only one server with this profile. So for example, on a production environment you have three servers (S1, S2, S3), then you could run on S1 with profile prod and cron(
-Dspring.profiles.active=prod,cron
). And on S2 and S3 just use prod profile(-Dspring.profiles.active=prod
).And in code, you can use
@Profile("cron")
on scheduler classes. This way it will be executed only when cron profile is active -
Use a distributed lock. If you have Zookeeper in your environment, you can use this to achieve distributed locking system.
-
You can use some database(mysql) and create a sample code to get a lock on one of the table and add an entry. And whichever instance gets the lock, will make an entry in this database and will execute the cron job. You need to
put a check in your code, ifgetLock()
is successfull only then proceed with execution. Mysql has utilities likeLOCK TABLES
, which you could use to get away with concurrent read/writes. -
Use Spring shedlock. This library aims to solve this problem quite elegantly and with minimum code. Have a look at an example here
personally I would say, option 2 or option 4 is the best of all.