高并发下golang的锁怎么加呢
一个简单的场景: 领券
1.先获取券信息, 判断状态, 张数, 判断用户是否领过券, 如果领过券,看券的类型, 是一天一次,还是活动一次,
2.我这边做了操作, 缓存了券的剩余可领取张数, 然后先把可领取张数减1
3.然后判断剩余张数是否为0, 如果为0, 券的状态就变成已结束, 然后开始mysql事务, 修改券剩余张数 和 用户券表里面插入记录
4.失败回滚 redis里的可领券张数+1
问题: 这边的锁要怎么加呢, 全局加个锁?
我一开始的做法: redis里的券剩余数量减那边加了个锁(因为是先获取再减操作, 没有使用直接减判断剩余的数量), 确保了不会有超过限制张数的人进来, 但是如果只在这边加锁, 假设只剩下最后两张的时候, 先后顺序无法 控制, 在数据库事务那边无法保证执行是否成功,
假设倒数第二张失败, 剩余可领数量1, 券状态正常
最后一张成功, 剩余数量0, 券状态结束
那么如果并发情况下, 最后一张成功, 最后一张失败, 情况就是券结束状态, 可领取张数1, 这种情况时有问题的, 那么锁应该怎么加呢? 全局加个锁?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,你通过缓存来控制瞬间进入的量,然后通过mysql 的事务来处理。如果失败<事务回滚,redis +1 > 是不会造成影响的。
领券的时候redis先用incr执行减1操作, incr本身是原子性的不存在并发问题, incr返回的结果如果小于0说明券已经发完了, 执行incr加1,然后直接返回即可, 如果大于等于0执行mysql事务,事务执行失败, incr执行+1, 这张券发放失败, 然后返回就好了,如果正常执行就按正常发放返回. 整个操作相当于一个乐观锁, 默认可以正常发放, 后续操作校验有问题的时候执行回滚.