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.");
        }
    }
相关推荐
Java水解7 分钟前
Spring Boot 消息队列与异步处理
spring boot·后端
桦说编程21 分钟前
AI 真的让写代码变快了吗?
后端
AskHarries2 小时前
openclaw升级和参数调整
后端·ai编程
creaDelight2 小时前
基于 Django 5.x 的全功能博客系统 DjangoBlog 深度解析
后端·python·django
Rust语言中文社区3 小时前
【Rust日报】 Danube Messaging - 云原生消息平台
开发语言·后端·rust
菜鸟程序员专写BUG3 小时前
SpringBoot 接口返回异常全集|JSON解析失败/响应乱码/状态码错误完美解决
spring boot·后端·json
希望永不加班4 小时前
SpringBoot 编写第一个 REST 接口(Get/Post/Put/Delete)
java·spring boot·后端·spring
vx-程序开发4 小时前
springboot智慧农业信息服务平台-计算机毕业设计源码65287
spring boot·后端·课程设计
小雷君4 小时前
SpringBoot 接口开发5个高频踩坑总结
java·spring boot·后端·面试