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";
}

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

相关推荐
李广坤12 小时前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
初次攀爬者2 天前
ZooKeeper 实现分布式锁的两种方式
分布式·后端·zookeeper
爱可生开源社区2 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1772 天前
《从零搭建NestJS项目》
数据库·typescript
加号32 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏2 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐2 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再2 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip
tryCbest2 天前
数据库SQL学习
数据库·sql
jnrjian2 天前
ORA-01017 查找机器名 用户名 以及library cache lock 参数含义
数据库·oracle