高并发下golang的锁怎么加呢

发布于 2022-09-11 22:07:55 字数 519 浏览 41 评论 0

一个简单的场景: 领券
1.先获取券信息, 判断状态, 张数, 判断用户是否领过券, 如果领过券,看券的类型, 是一天一次,还是活动一次,
2.我这边做了操作, 缓存了券的剩余可领取张数, 然后先把可领取张数减1
3.然后判断剩余张数是否为0, 如果为0, 券的状态就变成已结束, 然后开始mysql事务, 修改券剩余张数 和 用户券表里面插入记录
4.失败回滚 redis里的可领券张数+1

问题: 这边的锁要怎么加呢, 全局加个锁?

我一开始的做法: redis里的券剩余数量减那边加了个锁(因为是先获取再减操作, 没有使用直接减判断剩余的数量), 确保了不会有超过限制张数的人进来, 但是如果只在这边加锁, 假设只剩下最后两张的时候, 先后顺序无法 控制, 在数据库事务那边无法保证执行是否成功,
假设倒数第二张失败, 剩余可领数量1, 券状态正常
最后一张成功, 剩余数量0, 券状态结束
那么如果并发情况下, 最后一张成功, 最后一张失败, 情况就是券结束状态, 可领取张数1, 这种情况时有问题的, 那么锁应该怎么加呢? 全局加个锁?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

圈圈圆圆圈圈 2022-09-18 22:07:55

首先,你通过缓存来控制瞬间进入的量,然后通过mysql 的事务来处理。如果失败<事务回滚,redis +1 > 是不会造成影响的。

满天都是小星星 2022-09-18 22:07:55

领券的时候redis先用incr执行减1操作, incr本身是原子性的不存在并发问题, incr返回的结果如果小于0说明券已经发完了, 执行incr加1,然后直接返回即可, 如果大于等于0执行mysql事务,事务执行失败, incr执行+1, 这张券发放失败, 然后返回就好了,如果正常执行就按正常发放返回. 整个操作相当于一个乐观锁, 默认可以正常发放, 后续操作校验有问题的时候执行回滚.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文