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.");
        }
    }
相关推荐
程序猿阿越9 分钟前
Kafka源码(七)事务消息
java·后端·源码阅读
ArabySide33 分钟前
【Spring Boot】REST与RESTful详解,基于Spring Boot的RESTful API实现
spring boot·后端·restful
程序定小飞1 小时前
基于springboot的学院班级回忆录的设计与实现
java·vue.js·spring boot·后端·spring
dreams_dream2 小时前
Django序列化器
后端·python·django
懷淰メ3 小时前
python3GUI--短视频社交软件 By:Django+PyQt5(前后端分离项目)
后端·python·django·音视频·pyqt·抖音·前后端
有意义3 小时前
从零搭建:json-server+Bootstrap+OpenAI 全栈 AI 小项目
前端·后端·llm
汤姆yu4 小时前
基于springboot的民间救援队救助系统
java·spring boot·后端·救援队
IT_陈寒4 小时前
React性能优化实战:这5个Hooks技巧让我的应用快了40%
前端·人工智能·后端
韩立学长5 小时前
基于Springboot的智慧管网灌溉系统i1agupa7(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
一 乐5 小时前
高校教务|教务管理|基于springboot+vue的高校教务管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·教务管理