代金券锁券优化方式

32 天前
 felo

有一个用券逻辑,券有金额/剩余金额属性。并发场景有很多请求使用同一张券,我用到了 select for update 的方式进行锁券,当一个请求消耗完券之后,update 记录(券剩余金额),然后会释放锁,下一个请求再继续用券。

但现在同一张券,券金额比较大且并发场景的情况下,某些请求耗时会比较长,因为等待锁释放

请教下,这里有什么优化点么,合并请求之类的改动太大,需要上游配合

1822 次点击
所在节点    程序员
32 条回复
felo
32 天前
@esee 对,我个人倾向也是不想用别的组件,链路越复杂问题越多。看了大家回复我感觉可以用乐观锁代替 select for update ,但乐观锁失败之后的重试处理以及如何保证请求顺序还得再看看
xuelu520
32 天前
你对券的基础理解是不是错了?
看你说的是所有人共用一张券,实际你得每个人都发一张券或领一张,然后对券进行核销
felo
32 天前
@xuelu520 看我的附言哈,不同的业务场景。券怎么用要看业务逻辑,我没说过所有人共用一张。
esee
32 天前
@felo 可是你的场景就是高并发的情况,感觉乐观锁并不适合,如果冲突会产生大量重试,数据库负担会加重,select for update 感觉就够了
felo
32 天前
@esee 嗯理解,锁券到更新金额中间只有一个写用券记录,这个我后置试试
admin7785
32 天前
看起来有点像预算池的场景:比如:发了 100 张券,总共 100 元的预算,每个人都能用,先到先得,预算用完即止。
ucando
31 天前
有点不是太理解需求,如果是后付费,是不是可以理解成用户有多个需要扣费的业务,然后在某一个时间点需要自动扣费?以我的理解这部分并不需要并行处理,因为不是用户通过多个客户端同时操作进行的,直接照#13 楼的处理方式就行了。如果需要返回余额,还可以使用 returning fldBalance 来获取最新的余额,select 都省了
INCerry
31 天前
用 actor 模式,每个券都单线程处理
asAnotherJack
31 天前
现在慢是因为有大事务吗,如果是的话可以考虑把大事务拆成多个小事务,再弄个状态机进行处理,比如分成多个步骤,扣减优惠券、扣减余额、其他业务逻辑 abc…,完成一个操作后就更新为另一个状态,通过状态流转,一步一步操作,某一步出错时区分错误类型决定是重试还是回滚之前的操作进入失败状态。这样每一个操作都耗时不长,不会因为操作优惠券的一个锁拖慢其他步骤。另外注意做好幂等,尤其是失败回滚时,不要退费退多了
realpg
30 天前
@yankebupt #10
MQ 真的不适合用来做涉钱的账务操作
没故障时候什么都好
有故障就火葬场,甚至监狱
yankebupt
30 天前
@realpg 所以说得动数据结构么。
都不能包在一个 Transcation 里,一定得加个状态等钱扣完,扣了才继续……
有点脱裤子放屁,但是没办法,人家要并发
realpg
30 天前
@yankebupt #31
处理过程唯一话后设计好可以利用 MQ 但是不能分解步骤放到不可靠的 MQ 里面 大部分用 MQ 的都是设计不到位

涉及金钱最好是多账本完全一致才能操作 然后确保处理队列的唯一性 各种异常要充分照顾到并且能自动化处理

如果系统或者数据库是分布式的 就更麻烦 这个真的不太建议自己能力不足单纯靠问的去设计架构

如果评估自己能力不足设计这个架构,就简单化成单处理逻辑

你这种业务 基本就是阿里云的通用储值卡 完全一摸一样的逻辑

跟京东 E 卡也有点区别 因为 E 卡是主动使用 顶天多人登陆账号同时使用

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

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

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

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

© 2021 V2EX