注:每天进步一点点,记录每日成长,思考的第04/365天 ;
本文预计阅读时间: 5分钟
Redis分布式锁解决电商订单库存并发问题。
基于Redis使用分布式锁已经不是什么新鲜事了。这篇文章分享的是使用redis分布式锁解决商品超卖事故的一个案例。
库存超卖问题是有很多种技术解决方案的,比如悲观锁,分布式锁,乐观锁,队列串行化,Redis原子操作,等等解决方案。
常见分布式锁解决方案:
三种分布式锁实现方式对比:
1、数据库分布式锁实现缺点:
1)db操作性能较差,且有锁表的风险;
2)非阻塞操作失败后,需要轮询,占用cpu资源;
3)长时间不commit或者长时间轮询,可能会占用较多连接资源。
2、ZK分布式锁实现缺点:
性能不如redis,因为其写操作(获取锁释放锁)都需要在Leader上执行,然后同步到follower。
3、Redis(缓存)分布式锁实现缺点:
1)过期时间不好控制;
2)非阻塞,操作失败后,需要轮询,占用cpu资源;
1
01
使用原生redis实现
使用原生Redis
的SetNX+
Expire实现的分布式锁。
//方案1 setnx
String lockKey = "zhyRedis";
//通过val,给锁设置唯一id,防止其他线程删除锁
String clientId = UUID.randomUUID().toString(); //或者雪花生成位置ID
boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 10, TimeUnit.SECONDS);
// redisTemplate.expire(lockKey,10,TimeUnit.SECONDS) //旧版本redis(新版直接设置在后面,如上)
//如果获取不到锁,则返回失败
if(!result){
result "failed";
}
try {
//如果能获取到锁,则返回成功
Integer count = Integer.parseInt(redisTemplate.opsForValue.get("count").toString());
if (count > 0) {
Integer realCount = count - 1;
System.out.Println("购买成功,剩余库存:" + realCount.toString());
redisTemplate.opsForValue().set("count",realCount.toString());
}else{
System.out.Println("购买失败,库存不足");
}
} catch(Exception e){
e.printStackTrace();
return "failed";
} finally{
//解锁
//判断当前客户端id与redis分布式中持有的客户端id一致,才能删除锁
if(clientId.equals(redisTemplate.opsForValue().get(lockKey))){
redisTemplate.delete(lockKey)
}
}复制
1
02
使用redisson实现
Redis
的
SetNX+Expire
实现的分布式锁而言,
Redisson
的分布式锁组件可以解决原生
Redis
组合命令带来的一些缺陷,即redis的超时时间值不知道设置为多少才合适。如果此时
Redis
的服务器节点恰好出现宕机或者服务不能用的情况,那将会导致相应的
Key
永远存于缓存中,即处于所谓的“永久被锁死”的状态!
Redisson
内部提供了一个监控锁的看门狗
WatchDog
,其作用在于
Redis
实例被关闭之前,不断延长锁的有效期。
除此之外,Redisson
还通过加锁的方法提供了leaseTime
等参数来指定加锁的有效时间,即超过这个时间后“锁”便自动解开了。
//方案2 redisson
String lockKey = "zhyRedis";
RLock rLock = redisson.getLock(lockKey);
try {
rLock.lock(10, TimeUnit.SECONDS)
//如果能获取到锁,则返回成功
Integer count = Integer.parseInt(redisTemplate.opsForValue.get("count").toString());
if (count > 0) {
Integer realCount = count - 1;
System.out.Println("购买成功,剩余库存:" + realCount.toString());
redisTemplate.opsForValue().set("count",realCount.toString());
}else{
System.out.Println("购买失败,库存不足");
}
} catch(Exception e){
e.printStackTrace();
return "failed";
} finally{
//解锁
rLock.unlock();
}复制
文章转载自欢乐毅城,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
国产非关系型数据库 Eloqkv 初体验
JiekeXu
130次阅读
2025-04-10 23:51:35
融合Redis缓存的PostgreSQL高可用架构
梧桐
85次阅读
2025-04-08 06:35:40
Redis概要
听溪
38次阅读
2025-04-11 10:23:10
安装与配置Redis
鲁鲁
33次阅读
2025-04-11 10:26:10
Redis数据库——Cluster集群模式
编程Cookbook
28次阅读
2025-04-16 15:34:44
使用Jedis访问Redis数据库
怀念和想念
27次阅读
2025-04-11 15:08:30
Redis geo 实战:“附近的人”实现,打造社交的新维度
老王两点中
26次阅读
2025-04-11 09:02:30
Redis改协议内幕曝光!核心开发者亲述被“踢出局”,外部贡献者几乎全跑光了!
老鱼笔记
24次阅读
2025-04-17 10:41:56
Redis提供的持久化机制
luyingjun
23次阅读
2025-04-11 15:11:05
Redis
鲁鲁
21次阅读
2025-04-07 20:14:35