Distributed lock — prevent concurrent access across multiple servers.
1const Redis = require("ioredis");2const { v4: uuidv4 } = require("uuid");34class DistributedLock {5 constructor(redis) {6 this.redis = redis;7 }89 async acquire(key, ttlMs = 10000) {10 const value = uuidv4();11 const acquired = await this.redis.set(12 `lock:${key}`,13 value,14 "PX",15 ttlMs,16 "NX"17 );18 return acquired ? value : null;19 }2021 async release(key, value) {22 const script = `23 if redis.call("get", KEYS[1]) == ARGV[1] then24 return redis.call("del", KEYS[1])25 else26 return 027 end28 `;29 return this.redis.eval(script, 1, `lock:${key}`, value);30 }3132 async withLock(key, fn, ttlMs = 10000) {33 const lockValue = await this.acquire(key, ttlMs);34 if (!lockValue) throw new Error("Could not acquire lock");3536 try {37 return await fn();38 } finally {39 await this.release(key, lockValue);40 }41 }42}4344// Usage45const lock = new DistributedLock(redis);4647await lock.withLock("order:123", async () => {48 // Only one server processes this at a time49 const order = await db.getOrder(123);50 await processPayment(order);51});