Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Simple Mutual Exclusion

DZone's Guide to

Simple Mutual Exclusion

Learn how to increase your services' availability through a mutual exclusion mechanism, like the one we'll set up in this tutorial.

· Performance Zone ·
Free Resource

xMatters delivers integration-driven collaboration that relays data between systems, while engaging the right people to proactively resolve issues. Read the Monitoring in a Connected Enterprise whitepaper and learn about 3 tools for resolving incidents quickly.

Nowadays, for almost all services, we would like to set up at least poor man’s HA. This means we would have more than one node/server/pod at a time. This is great for load balancing and availability purposes. Nevertheless, there’s a simple problem with this setup. What if you want to execute a piece of code in only one node? We can do this via a simple mutual exclusion mechanism. There are various ways to this but I would like to limit this post to achieve mutual exclusion with Java and Spring Framework.

Now, imagine you have a cron job that sends an e-mail to your customers at 9 a.m. every day. You wouldn’t want to send the same e-mails twice, right? If you are using Spring Framework, you can simply do this via Scheduled annotation. A typical code would look like:

@Scheduled(cron = "59 59 8 * * *" /* Every day at 8:59:59am */)
public void sendEmails() {
  List<Email> emails = emailDAO.getEmails();
  emails.forEach(email -> sendEmail(email));
}

So, we need one node to execute above not the others. It would be great if we can do something like this right?

@Scheduled(cron = "59 59 8 * * *" /* Every day at 8:59:59am */)
@TryLock(name = "emailLock", owner = NODE_NAME, lockFor = TEN_MINUTE)
public void sendEmails() {
  List<Email> emails = emailDAO.getEmails();
  emails.forEach(email -> sendEmail(email));
}

Thus, I’ve implemented a little library to exactly do this. Currently, it offers synchronization through Postgres and MySQL but one can extend it to other technologies like ZooKeeper, Consul and etcd as well.

By the way, this isn’t just about crons. You can also synchronize over different stuff as well. For instance, you might want to process a message once even if it’s received by multiple nodes.

@Component
class MessageProcessor{
  ...
  @TryLock(name = "messageProcessor", owner = NODE_NAME, lockFor = TEN_MINUTE)
  public void processMessage(Message message) {
    ...
  }
}
@Component
class MessageService{
  ...
  @PostConstruct
  public void initProcessor(){
    while (true) {
      Message message = pollMessage();
      messageProcessor.processMessage(message);
    }
  }
}

In consequence, you can implement a simple lock with a timeout with dlock.

Discovering, responding to, and resolving incidents is a complex endeavor. Read this narrative to learn how you can do it quickly and effectively by connecting AppDynamics, Moogsoft and xMatters to create a monitoring toolchain.

Topics:
performance ,load balancing ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}