讨论下 卡密下发 保证不重发 除了不用 redis 还有啥方案

2022-01-05 14:48:13 +08:00
 lipaa

业务背景:公司采购了一批爱奇艺会员卡密,导入到了 mysql 现在的做法是有用户购买就获取最后一张未使用的, 更新时判断状态(可能已被使用 会失败),如果失败就自旋重试 redis 的方案已经启弃用了 感觉难以保证一致性... 各大 v 友还有啥方案 麻了

5183 次点击
所在节点    程序员
54 条回复
lipaa
2022-01-05 14:49:01 +08:00
失败就自旋重试 感觉也不好 所以..
Rwing
2022-01-05 15:00:12 +08:00
加锁。。。。
murmur
2022-01-05 15:00:54 +08:00
并发有多大,你们那点销量需要很严格的锁机制么
murmur
2022-01-05 15:01:45 +08:00
最后一张未使用的是什么意思,我感觉这需求就有问题,连 ATM 都知道取钱和存钱是两个箱子

用户买了这卡,那就死活不退,这口子开不得
lipaa
2022-01-05 15:05:11 +08:00
@murmur 按主键排序取第一条未被使用的啊 需求没问题 很正常的需求
yushiro
2022-01-05 15:07:05 +08:00
这种需求能有多大的并发量啊?取卡密的时候上个锁不行?
murmur
2022-01-05 15:07:47 +08:00
@lipaa 哦,那我理解错了,我还是想问并发,因为你再严格的锁也会遇到用户撕逼,我就跟你死磕你卖我的卡不能用,你不处理么

所以是不是可以考虑宽松锁剩下的客服处理
abcbuzhiming
2022-01-05 15:09:49 +08:00
技术上保证不重发,那就只能加锁变成序列化。除此之外,看看有没有人能在业务模型上提出个新方案来
Canon1014
2022-01-05 15:11:12 +08:00
并发不是特别大加个乐观锁就够了吧
WildCat
2022-01-05 15:12:05 +08:00
很经典的系统设计问题?

分段加锁?

https://zhuanlan.zhihu.com/p/104515829
h82258652
2022-01-05 15:13:44 +08:00
加锁
数据库获取一张未使用的
将这张标记为已使用
释放锁

并发不高就这么搞吧

并发高那也只能排队了,这业务就是个库存问题
murmur
2022-01-05 15:14:12 +08:00
@abcbuzhiming 模型就更简单了,直接排队领卡号,锁这部分更好设计,就跟淘宝一样,你买了卡,不是立刻收货,过段时间别人会把卡号通过消息给你发过来,或者直接代充

那后面的模型更简单了,不需要确认收货,撕逼都省了
wei745359223
2022-01-05 15:16:09 +08:00
两张表
卡密表
ID,CODE

发卡表
ID,USER_ID

两个表 ID 都是自增,往发卡表里插入数据,返回的 ID 在卡密表里找到就占用。
jadec0der
2022-01-05 15:17:04 +08:00
更新时判断状态会失败,是指…乐观锁?
EileenJ
2022-01-05 15:43:06 +08:00
pg 里用 skip locked 应该可以实现,mysql 不知道有没有类似的功能
lipaa
2022-01-05 15:46:04 +08:00
@Rwing 是的
lipaa
2022-01-05 15:46:15 +08:00
@jadec0der 是的
Chinsung
2022-01-05 16:13:37 +08:00
上个分布式锁就行了吧,觉得 redis 不可靠就上 zk 。
你自旋的方案也没什么问题,但是锁肯定更好一些。
自旋的方案如果想吞吐高点,可以给卡密表分下区,然后再建张表记录表记录每个区里剩几张,在一个事务里更新。
比如卡密表 10 条记录分区,那记录表就记录 10 (范围)-9 (剩余数量)。然后请求进来就先找一个剩余数量大于 0 的分区去尝试更新。
如果你卡密数量无限,不怕超发,其实楼上兄弟那个双表自增主键的方案也挺好的
abigeater
2022-01-05 16:14:36 +08:00
用户点击领取向一个表写入一条记录 并返回 ID 给用户
然后提供一个接口给前端 通过 Id 获取卡密 让前端轮询调用直到有卡密返回
再起一个定时任务之类的 队列方式从卡密表拿一条就给领取表填一条

是不是就解决了。。
philchang1995
2022-01-05 16:26:13 +08:00
@abigeater 通过 id 获取卡密这个操作是如何实现的?类似 13 楼说的那个双表自增主键的方式么?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/826349

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX