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.");
        }
    }
相关推荐
qq_297574671 天前
【实战教程】SpringBoot 实现多文件批量下载并打包为 ZIP 压缩包
java·spring boot·后端
计算机程序设计小李同学1 天前
基于 Spring Boot + Vue 的龙虾专营店管理系统的设计与实现
java·spring boot·后端·spring·vue
Charlie_lll1 天前
力扣解题-[3379]转换数组
数据结构·后端·算法·leetcode
VX:Fegn08951 天前
计算机毕业设计|基于springboot + vue云租车平台系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
汤姆yu1 天前
2026基于springboot的在线招聘系统
java·spring boot·后端
计算机学姐2 天前
基于SpringBoot的校园社团管理系统
java·vue.js·spring boot·后端·spring·信息可视化·推荐算法
hssfscv2 天前
Javaweb学习笔记——后端实战8 springboot原理
笔记·后端·学习
咚为2 天前
Rust tokio:Task ≠ Thread:Tokio 调度模型中的“假并发”与真实代价
开发语言·后端·rust
Anastasiozzzz2 天前
对抗大文件上传---分片加多重Hash判重
服务器·后端·算法·哈希算法
Vivienne_ChenW2 天前
DDD领域模型在项目中的实战
java·开发语言·后端·设计模式