Redis(72)Redis分布式锁的常见使用场景有哪些?

Redis分布式锁在很多需要协调多个分布式系统或组件的场景中都能发挥重要作用。以下是一些常见的使用场景以及相应的代码示例:

常见使用场景

  1. 防止资源竞争

    • 多个进程或线程需要访问同一共享资源时,使用分布式锁可以防止资源竞争,确保同一时间只有一个进程或线程在操作该资源。
  2. 定时任务调度

    • 在分布式系统中,确保某个定时任务在同一时刻只被一个调度器执行,避免重复执行任务。
  3. 库存扣减

    • 电商系统中,多个用户同时下单时,需要确保库存扣减操作的原子性和一致性。
  4. 分布式事务

    • 在跨多个服务的分布式事务中,使用分布式锁可以协调各服务的操作,确保事务的一致性。
  5. ID生成器

    • 分布式系统中生成全局唯一ID时,使用分布式锁可以确保ID的唯一性和有序性。

场景示例和相应代码

1. 防止资源竞争

假设有多个进程同时写入一个文件,我们需要确保同一时间只有一个进程在写入。

java 复制代码
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

public class FileWriteWithDistributedLock {
    private Jedis jedis;
    private String lockKey;
    private String lockValue;
    private int expireTime;

    public FileWriteWithDistributedLock(Jedis jedis, String lockKey, int expireTime) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.expireTime = expireTime;
        this.lockValue = String.valueOf(Thread.currentThread().getId());
    }

    public boolean acquireLock() {
        SetParams params = new SetParams().nx().px(expireTime);
        String result = jedis.set(lockKey, lockValue, params);
        return "OK".equals(result);
    }

    public boolean releaseLock() {
        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                           "return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(luaScript, 1, lockKey, lockValue);
        return result.equals(1L);
    }

    public void writeToFile(String content) {
        if (acquireLock()) {
            try {
                // 模拟文件写操作
                System.out.println("Writing to file: " + content);
            } finally {
                boolean released = releaseLock();
                if (released) {
                    System.out.println("Lock released after writing.");
                } else {
                    System.out.println("Failed to release lock.");
                }
            }
        } else {
            System.out.println("Failed to acquire lock, try again later.");
        }
    }

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        FileWriteWithDistributedLock fileLock = new FileWriteWithDistributedLock(jedis, "file_write_lock", 10000);
        fileLock.writeToFile("Hello, World!");
        jedis.close();
    }
}

2. 定时任务调度

确保定时任务在分布式系统中同一时刻只被一个节点执行。

java 复制代码
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

public class ScheduledTaskWithDistributedLock {
    private Jedis jedis;
    private String lockKey;
    private String lockValue;
    private int expireTime;

    public ScheduledTaskWithDistributedLock(Jedis jedis, String lockKey, int expireTime) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.expireTime = expireTime;
        this.lockValue = String.valueOf(Thread.currentThread().getId());
    }

    public boolean acquireLock() {
        SetParams params = new SetParams().nx().px(expireTime);
        String result = jedis.set(lockKey, lockValue, params);
        return "OK".equals(result);
    }

    public boolean releaseLock() {
        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                           "return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(luaScript, 1, lockKey, lockValue);
        return result.equals(1L);
    }

    public void executeScheduledTask() {
        if (acquireLock()) {
            try {
                // 执行定时任务
                System.out.println("Executing scheduled task.");
            } finally {
                boolean released = releaseLock();
                if (released) {
                    System.out.println("Lock released after executing task.");
                } else {
                    System.out.println("Failed to release lock.");
                }
            }
        } else {
            System.out.println("Failed to acquire lock, another instance might be executing the task.");
        }
    }

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        ScheduledTaskWithDistributedLock taskLock = new ScheduledTaskWithDistributedLock(jedis, "scheduled_task_lock", 10000);
        taskLock.executeScheduledTask();
        jedis.close();
    }
}

3. 库存扣减

在电商系统中,同时对同一个商品下单时需要确保库存扣减操作的原子性。

java 复制代码
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

public class InventoryReductionWithDistributedLock {
    private Jedis jedis;
    private String lockKey;
    private String lockValue;
    private int expireTime;

    public InventoryReductionWithDistributedLock(Jedis jedis, String lockKey, int expireTime) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.expireTime = expireTime;
        this.lockValue = String.valueOf(Thread.currentThread().getId());
    }

    public boolean acquireLock() {
        SetParams params = new SetParams().nx().px(expireTime);
        String result = jedis.set(lockKey, lockValue, params);
        return "OK".equals(result);
    }

    public boolean releaseLock() {
        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                           "return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(luaScript, 1, lockKey, lockValue);
        return result.equals(1L);
    }

    public void reduceInventory(String itemId, int quantity) {
        if (acquireLock()) {
            try {
                // 模拟库存扣减操作
                System.out.println("Reducing inventory for item: " + itemId + " by " + quantity);
            } finally {
                boolean released = releaseLock();
                if (released) {
                    System.out.println("Lock released after reducing inventory.");
                } else {
                    System.out.println("Failed to release lock.");
                }
            }
        } else {
            System.out.println("Failed to acquire lock, try again later.");
        }
    }

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        InventoryReductionWithDistributedLock inventoryLock = new InventoryReductionWithDistributedLock(jedis, "inventory_lock", 10000);
        inventoryLock.reduceInventory("item123", 1);
        jedis.close();
    }
}

4. 分布式事务

在跨多个服务的分布式事务中,通过分布式锁来协调操作,确保事务的一致性。

java 复制代码
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

public class DistributedTransactionWithLock {
    private Jedis jedis;
    private String lockKey;
    private String lockValue;
    private int expireTime;

    public DistributedTransactionWithLock(Jedis jedis, String lockKey, int expireTime) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.expireTime = expireTime;
        this.lockValue = String.valueOf(Thread.currentThread().getId());
    }

    public boolean acquireLock() {
        SetParams params = new SetParams().nx().px(expireTime);
        String result = jedis.set(lockKey, lockValue, params);
        return "OK".equals(result);
    }

    public boolean releaseLock() {
        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                           "return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(luaScript, 1, lockKey, lockValue);
        return result.equals(1L);
    }

    public void executeDistributedTransaction() {
        if (acquireLock()) {
            try {
                // 执行分布式事务的协调操作
                System.out.println("Executing distributed transaction.");
            } finally {
                boolean released = releaseLock();
                if (released) {
                    System.out.println("Lock released after executing transaction.");
                } else {
                    System.out.println("Failed to release lock.");
                }
            }
        } else {
            System.out.println("Failed to acquire lock, try again later.");
        }
    }
相关推荐
oak隔壁找我3 小时前
MySQL中 SHOW FULL PROCESSLIST` 输出中 `State` 列的所有可能值
后端
上进小菜猪3 小时前
基于 YOLOv8 的面向文档智能处理的表格区域检测系统 [目标检测完整源码]
后端
oak隔壁找我3 小时前
JVM常用调优参数
java·后端
IT_陈寒7 小时前
React状态管理终极对决:Redux vs Context API谁更胜一筹?
前端·人工智能·后端
晨星shine8 小时前
GC、Dispose、Unmanaged Resource 和 Managed Resource
后端·c#
蝎子莱莱爱打怪8 小时前
OpenClaw 从零配置指南:接入飞书 + 常用命令 + 原理图解
java·后端·ai编程
倚栏听风雨8 小时前
【ES避坑指南】明明存的是 "CodingAddress",为什么 term 查询死活查不到?彻底搞懂 text 和 keyword
后端
程序员爱钓鱼8 小时前
Go 操作 Windows COM 自动化实战:深入解析 go-ole
后端·go·排序算法
回家路上绕了弯9 小时前
深入解析Agent Subagent架构:原理、协同逻辑与实战落地指南
分布式·后端
子玖9 小时前
实现微信扫码注册登录-基于参数二维码
后端·微信·go