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

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

相关推荐
独泪了无痕5 小时前
Spring Data Redis 快速上手
spring boot·redis·后端
IT19955 小时前
Fail2Ban 防护 MySQL 实战|登录失败 3 次,IP 封禁 24 小时
数据库·mysql
夕除5 小时前
redis--IO 多路复用(select + poll)
数据库·sql
lzhdim9 小时前
100条常用SQL语句
数据库·sql·mysql·mybatis
天河归来9 小时前
从原始消息到业务数据:三层数据架构的设计与实践
数据库·数据仓库·架构
数据库小学妹9 小时前
金融数据库成本怎么算?五笔钱加一张TCO表
数据库·金融行业·数据库选型·国产化替代·tco·金融数据库
KaiwuDB10 小时前
KaiwuDB 分布式集群扩缩容,从原理到完整操作踩坑总结
运维·数据库·分布式
用户529589316685010 小时前
三马代驾实战:抢单池的 Redis 锁 + RabbitMQ 异步消费怎么做
redis
auspicious航10 小时前
PostgreSQL的备份与恢复
数据库·postgresql
这个DBA有点耶10 小时前
从 MySQL 到时序数据库:我帮朋友做迁移的完整记录
数据库·架构·dba