互金平台使用redis分布式锁的场景分析

本文介绍了一种利用Redis实现的分布式锁方案来解决高并发环境下库存管理中的超卖问题。通过详细步骤说明如何在多个Tomcat服务器间进行库存扣减操作,并确保数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用场景:
1、服务器采用分布式集群(多个tomcat)和公用的redis
2、业务场景:多个用户同时下单的高并发情况下,为了保证库存一致,避免超卖的情况,可以考虑在减库存的操作当中进行加锁操作
3、尝试加锁,如果加锁失败则等待一段时间重试;如果加锁成功,则拿当前购买金额和redis中的库存金额进行比较
4、如果大于库存金额,则提示用户当前库存金额不足,请重新下单
5、如果小于库存金额,则进行减库存操作
6、完成4/5操作后立即释放锁,并执行下面的业务操作(更新数据库库存,更新账户信息,记录流水,记录客户订单)
7、异常情况:
(1)业务处理失败,数据回滚,则返回用户下单失败,并还原库存(同时对库存操作进行加锁,保持数据一致)
(2)获取锁的线程超时,则抛出异常,返回给客户端下单超时
8、在生成产品时候,同时在redis中存储该产品的库存




使用redis实现的分布式锁:
首先设置每个获取锁的线程的超时时间,如果超过时间没有获取到锁则抛出超时异常;(锁等待超时,防止线程饥饿,永远没有入锁执行代码的机会 )
如果在时间范围则一直尝试获取锁;执行下列操作:
 1、通过jedis.setnx(key,value)命令,设置锁的有效时间(防止死锁)
key存放的该产品的唯一标识
value存放的当前时间+超时时间
(注:set if Not eXist 保证多个线程同一时间请求时,只有一个线程能获得锁;类似zookeeper的新增一个节点)
2、result 成功获得锁返回 1,否则 返回0
3、其它没有获得锁的线程,不断进行重试:
(1)判断锁是否正常释放
通过setnx(key,value)命令判断返回值是否为1
(2)判断锁是否已经超时
①通过get(key)获取到当前存储的超时时间curTime
②判断当前时间是否超时,如果超时进行步骤③,未超时则
③如果超时,则通过jedis的getset(key)命令,获取到当前key的旧值oldTime,并重新设置新的值即超时时间;
④并判断oldTIME和curTime是否相等,如果相等
则当前线程获得锁
⑤没有获得锁,等待一段时间后,继续执行第(1)步操作
⑥获取到锁,执行业务逻辑,finally释放锁
⑦释放锁,使用jedis.del(key),并把锁的标志置为false


(注:getset(key)是同步的,确保只有一个线程能获取到最原始的超时时间)


注意:里边牵涉到两个超时时间
1、锁等待超时,防止线程饥饿,永远没有入锁执行代码的机会
2、锁的超时时间,防止异常情况导致一个线程一直占有锁操作

具体代码实现参考:http://www.cnblogs.com/0201zcr/p/5942748.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值