惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
A
About on SuperTechFans
The Cloudflare Blog
G
Google Developers Blog
博客园_首页
Martin Fowler
Martin Fowler
Apple Machine Learning Research
Apple Machine Learning Research
L
LangChain Blog
D
Docker
C
Check Point Blog
T
Tailwind CSS Blog
博客园 - 司徒正美
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
Microsoft Security Blog
Microsoft Security Blog
V
V2EX
博客园 - 叶小钗
T
The Blog of Author Tim Ferriss
酷 壳 – CoolShell
酷 壳 – CoolShell
IT之家
IT之家
M
MIT News - Artificial intelligence
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 【当耐特】
GbyAI
GbyAI

Yusuf Aytas

When Code Is Cheap, Does Quality Still Matter? Why Crouching Tiger, Hidden Dragon Is a Masterpiece Why We Ignore Advice The Mirror Is Part of the Machine When Too Many Maps Overlap on One Person The Work Runs on Different Maps Your Work Introduces You Trial By Fire The Dude Why Headcount Math Lies Capacity Is the Roadmap The Roadmap Is Not the System Torres del Paine W Trek Escaping Status Theater Incentives Drive Everything Scaling Culture Without Dilution What Good Looks Like Why Airport Security Feels Random Why Politics Appear How to Work with Me The Janus Protocol Multi-Horizon Delivery Framework What Good Execution Looks Like Managing Your Manager Why Kingdom of Heaven’s Director’s Cut Is Better AI Broke Interviews Most of What We Call Progress Managers Have Been Vibe Coding All Along Stop Wasting Brainpower Why Over-Engineering Happens
Simple Mutual Exclusion
Yusuf Aytas · 2018-07-11 · via Yusuf Aytas

Published · 3 min read

When we design services for high availability, we often deploy more than one instance of the same application. It might be two servers behind a load balancer or a few nodes sharing the same workload. This setup is great for redundancy and performance, but it introduces a simple question: how can we make sure that only one instance executes a specific piece of code at a time?

That is where mutual exclusion comes in. It ensures that a critical operation runs only once, even when multiple nodes are active.

Imagine a scheduled task that sends daily reports or reminder emails. You certainly do not want every node to send the same email twice. In Spring Framework, a typical implementation might look like this:

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

Now, the challenge is ensuring that only one node runs this method. Ideally, we could decorate it with something like this:

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

To solve this, I built a small library called dlock. It provides a simple mutual exclusion mechanism using relational databases such as PostgreSQL and MySQL. You can extend it to other coordination systems like ZooKeeper, Consul, or etcd if needed.

Although distributed locking can be done in many ways, my goal is to keep it lightweight and practical. Many production systems don't have a full cluster management solution, but almost all of them have a relational database. That made the database an ideal place to coordinate small-scale distributed locks.

This approach is not limited to scheduled jobs. You can use it anywhere you need to guarantee single execution, such as:

  • Message processing
  • File imports
  • Cleanup or migration jobs
  • Periodic billing tasks

Here’s another simple example:

@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);  
    }  
  }  
}

The principle is straightforward. Each node attempts to acquire the same lock before executing the critical section. The first one succeeds, the others wait or skip execution depending on your configuration.

Even a simple lock with an expiration time can prevent accidental duplication, inconsistent state, or race conditions in multi-node environments. In consequence, mutual exclusion remains one of the easiest and most reliable techniques to keep distributed systems consistent. In consequence, you can implement a simple lock with a timeout with dlock.