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.");
        }
    }
相关推荐
忧郁的Mr.Li6 分钟前
SpringBoot中实现多数据源配置
java·spring boot·后端
暮色妖娆丶1 小时前
SpringBoot 启动流程源码分析 ~ 它其实不复杂
spring boot·后端·spring
Coder_Boy_1 小时前
Deeplearning4j+ Spring Boot 电商用户复购预测案例中相关概念
java·人工智能·spring boot·后端·spring
Java后端的Ai之路1 小时前
【Spring全家桶】-一文弄懂Spring Cloud Gateway
java·后端·spring cloud·gateway
野犬寒鸦1 小时前
从零起步学习并发编程 || 第七章:ThreadLocal深层解析及常见问题解决方案
java·服务器·开发语言·jvm·后端·学习
Honmaple2 小时前
OpenClaw 实战经验总结
后端
golang学习记2 小时前
Go 嵌入结构体方法访问全解析:从基础到进阶陷阱
后端
NAGNIP3 小时前
程序员效率翻倍的快捷键大全!
前端·后端·程序员
qq_256247053 小时前
从“人工智障”到“神经网络”:一口气看懂 AI 的核心原理
后端
无心水3 小时前
分布式定时任务与SELECT FOR UPDATE:从致命陷阱到优雅解决方案(实战案例+架构演进)
服务器·人工智能·分布式·后端·spring·架构·wpf