Redis 分布式锁

【图灵学院】分布式架构-Redis高并发分布式锁

使用 Redis 当做分布式锁的核心就是 Redis 的 setnx 命令,setnx 命令 Redis 会保证只有一个线程设置成功。

注意点:

  • 释放锁操作必须在 finally 里执行,保证锁的成功释放。
  • key 必须设置过期时间,避免因系统异常、线程崩溃导致 key 一直存在,引发死锁。
  • 设置过期时间必须使用 setnx(key,vaule,expiredTime) 的原子操作。
  • 释放锁,必须保证只能是持有锁的线程来进行释放,因此可以为每个线程分配个唯一编号,然后设置为 key 的值,删除时进行判断。
  • key 的过期时间到了后,如果业务代码还未执行完,那么需要考虑为 key 延长过期时间,即续命。

最简陋的使用方式如下:

java 复制代码
public String deductStock() throws InterruptedException {
    String lockKey = "product_001";
    // String clientId = UUID.randomUUID().toString();
    RLock redissonLock = redisson.getLock(lockKey);
    try {
        // jedis.setnx(key,value)
        // Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, "zhuge");
        //stringRedisTemplate.expire(lockKey,30, TimeUnit.SECONDS);
        /* Boolean result = stringRedisTemplate.opsForValue()
        		.setIfAbsent(lockKey, clientId, 30, TimeUnit.SECONDS);

            if (!result) {
                return "1001";
            }*/

        // 加锁,实现锁续命功能
        redissonLock.lock();
        // jedis.get("stock")
        int stock = Integer.parseInt(Objects.requireNonNull(stringRedisTemplate.opsForValue().get("stock")));
        if (stock > 0) {
            int realStock = stock - 1;
            // jedis.set(key,value)
            stringRedisTemplate.opsForValue().set("stock", realStock + "");
            System.out.println("扣减成功,剩余库存:" + realStock + "");
        } else {
            System.out.println("扣减失败,库存不足");
        }
    } finally {
        redissonLock.unlock();
        // 这里也是有可能有问题的 有可能线程 A 刚进入到 if 里,然后被挂起了,而线程 B 加锁成功了,
        // 此时也会发生线程 A 删除了线程 B 的锁
        /*if (clientId.equals(stringRedisTemplate.opsForValue().get(lockKey))){
        	stringRedisTemplate.delete(lockKey);
        }*/
    }
    return "end";
}

同一个商品的并发 --> 可以对库存进行分段,使用分段锁来提高并发

相关推荐
懵逼的小黑子1 小时前
解释两个 Django 命令 makemigrations和migrate
数据库·django
乌旭2 小时前
量子计算与GPU的异构加速:基于CUDA Quantum的混合编程实践
人工智能·pytorch·分布式·深度学习·ai·gpu算力·量子计算
Lxinccode3 小时前
Java查询数据库表信息导出Word-获取数据库实现[1]:KingbaseES
java·数据库·word·获取数据库信息·获取kingbasees信息
豆沙沙包?4 小时前
5.学习笔记-SpringMVC(P61-P70)
数据库·笔记·学习
朴拙数科6 小时前
MongoDB Atlas与MongoDB连接MCP服务器的区别解析
服务器·数据库·mongodb
柏油6 小时前
MySQL InnoDB 行锁
数据库·后端·mysql
A-Kamen6 小时前
MySQL 存储引擎对比:InnoDB vs MyISAM vs Memory
数据库·mysql·spark
极限实验室6 小时前
【Workshop 第一期 - 北京站】搜索服务统一治理(跨引擎多个集群监控管理、流量管控、服务编排)
数据库
鹏翼丶7 小时前
搭建动态SQL取数
数据库·sql·动态sql
辰哥单片机设计7 小时前
PH传感器详解(STM32)
数据库·mongodb