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

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

相关推荐
沃尔威武9 分钟前
性能调优实战:从火焰图定位到SQL优化的全流程
android·数据库·sql
数厘42 分钟前
2.7SQL 四大分类:理解与避坑
数据库·sql
亮子AI1 小时前
【PostgreSQL】推荐几个PostgreSQL管理工具
数据库·postgresql
AI应用实战 | RE1 小时前
011、向量数据库入门:Embeddings原理与ChromaDB实战
开发语言·数据库·langchain·php
captain3761 小时前
联合查询
数据库
华农DrLai1 小时前
怎么用大模型生成推荐的训练数据?Data Augmentation怎么做?
数据库·人工智能·大模型·nlp·prompt
XDHCOM1 小时前
ORA-31215: DBMS_LDAP PL/SQL无效LDAP修改值,Oracle报错故障修复与远程处理方案,快速解决连接配置难题
数据库·sql·oracle
深蓝电商API1 小时前
Redis在海淘场景下的缓存策略设计
数据库·redis·缓存·海淘
杰克尼1 小时前
redis(day04-达人探店)
数据库·redis·缓存
一叶飘零_sweeeet2 小时前
击穿 MySQL 性能天花板:InnoDB Buffer Pool 核心架构、LRU 优化与生产调优全解
数据库·mysql