• 分布式锁相关


    超卖问题的解决

    现象

    • 一件商品,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: 失效时间,出现异常情况,锁可以过期失效。 

    这个时间怎么设置,程序执行超过这个时间了怎么办

    1.Watchdog用来给key延时,redission有这个功能。自动续期

    延时时使用 :lua脚本(见下方)

     

    释放锁:

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

    使用LUA脚本,去校验。

    Redisson客户端

    https://redisson.org/

    还有springboot的配置方法等

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

    redis官网有介绍:

    防止释放其他线程的锁。

    加锁实现:

     

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

     解锁脚本(lua)

    private static final String RELEASE_LOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; //

    延时脚本

    private static final String POSTPONE_LOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('expire', KEYS[1], ARGV[2]) else return '0' end";

    3.zookeeper分布式锁

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

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

    zookeeper官网有介绍

    zk观察器

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

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

    锁原理

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

    zk的Curator客户端

    直接调用即可

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

     

  • 相关阅读:
    ASP.NET Zero--10.一个例子(3)商品分类管理-新建
    ASP.NET Zero--9.一个例子(2)商品分类管理-列表
    ASP.NET Zero--8.一个例子(1)菜单添加
    ASP.NET Zero--7.控制器加权限
    ASP.NET Zero--6.菜单加权限
    ASP.NET Zero--5.配置权限
    ASP.NET Zero--4.不使用谷歌字体,提升加载速度
    ASP.NET Zero--2.如何启动
    C# mongoDB Driver 使用对象方式最完善查询语法大全
    ef 数据库连接字符串加密
  • 原文地址:https://www.cnblogs.com/jiangym/p/15877382.html
Copyright © 2020-2023  润新知