ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

分布式锁相关

2022-02-10 12:03:19  阅读:173  来源: 互联网

标签:库存 数据库 加锁 线程 相关 节点 分布式


超卖问题的解决

现象

  • 一件商品,AB同时下单,扣减库存出了问题。A读到库存是1,B读到库存是1;AB同时更新数据库,更新为0,数据库中虽然是0了,但是产生了两笔订单。
    • 解决办法:下沉到数据库扣减库存:
      •   通过UPDATE语句,更新增量,通过UPDATE计算库存,用到了UPDATE行锁,其他的UPDATE不可以更新,需要等待。
  • 并发校验库存,造成库存冲突的假象,扣成负数;

1.传入库存增量,库存会扣成负数

更新库存,通过update

 

 

 2.库存扣为负数

解决办法:

1.更新完库存之后,读取库存,若<0则抛出异常,回滚事务。

这样做没有加分布式锁,且数据库压力较大。且性能不高。

2.统一加锁,使之成为原子操作。

 

分布式锁

1.基于数据库的悲观锁

select ** for update 加锁,只能加一次,加锁期间其他线程不能获取。

具体实现:

 

 

 

 

 

优缺点:

简单方便,易于理解。并发量大的时候,对数据库压力大。锁的库与业务的数据库需要分开。

2.redis分布式锁:

SET resource_name my_random_value NX PX 3000

NX :因为redis是单线程的,并行请求变串行执行,只有一个能设置成功,设置成功则获得锁

PX: 失效时间,出现异常情况,锁可以过期失效。 这个时间怎么设置,程序执行超过这个时间了怎么办

释放锁:

使用redis的delete命令,正常释放的时候需要校验随机数是否相同,相同才能释放。

使用LUA脚本,去校验。

Redisson客户端

https://redisson.org/

 

 

还有springboot的配置方法等

https://github.com/redisson/redisson/tree/master/redisson-spring-boot-starter

 

redis官网有介绍:

 

防止释放其他线程的锁。

 

加锁实现:

 

 

 释放锁,使用lua脚本,加在finally里:

 

 

3.zookeeper分布式锁

存储机构类似树,有持久节点和瞬时节点

瞬时节点有序,没有子节点,会话结束会消失。

zookeeper官网有介绍

zk观察器

  • getData()
  • getChildren()
  • exists()

观察器只能观察一次,节点有变化发送给客户端

锁原理

  • 十个线程创建是个节点,瞬时节点,序号最小的线程获得锁。
  • 每个线程监听前一个序号节点;
  • 线程执行完,删除自己的节点;
  • 下一个序号线程收到通知,开始执行;

zk的Curator客户端

直接调用即可

官网: https://curator.apache.org/

 

 

标签:库存,数据库,加锁,线程,相关,节点,分布式
来源: https://www.cnblogs.com/jiangym/p/15877382.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有