代金券锁券优化方式

31 天前
 felo

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

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

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

1820 次点击
所在节点    程序员
32 条回复
yankebupt
31 天前
我完全不懂,但是按金额切分券,分别锁,闲时再合并?
felo
31 天前
@yankebupt 可能没说清
1. 券可以用多次
2. 用券请求是并发的
所以会出现一张券要被并发使用多次的情况。因为要修改剩余金额,所以需要给券加锁,但加了锁之后,等待锁释放的请求又会慢一些
yiqiao
31 天前
券不是发放到个人账户上然后消费吗? OP 问的是发的券超库存了吗?
InDom
31 天前
券余额也是余额, 所以你要问的是并发余额怎么减.

问题是单用户会有并发么?
如果是全局有一个“该券能用多少次、最多全局抵多少钱”.

那就是减库存问题了.

最好的就是落到缓存,然后用队列按顺序处理.
yankebupt
31 天前
当用户从页面点选那张优惠券还没有提交时,立刻把券切成两张,并锁住相应金额的那张,如果用户提交,就更新,如果不更新页面关闭了,把两张券再合起来......
yankebupt
31 天前
或者你也可以提供一个功能让用户自己切然后一张一张用(很丑陋,但代码最少
byehair
31 天前
1 、内存队列(或者 MQ ),排队对单券扣减,减少无畏的 CPU 消耗、加解锁消耗
2 、使用 Redis 的 decrby 进行扣减,通过内存扣减提升性能
3 、如果是多次的金额相同,还可以使用券预置拆分策略,减少锁竞争
lcy630409
31 天前
就是类似京东的 e 卡 说是卷 就是一个单独的存储余额
clysto
31 天前
用 redis 缓存剩余金额,直接在 redis 中 decrby 可行吗?
yankebupt
31 天前
楼上说的 MQ 比较靠谱。如果还没屎山堆到动不了数据结构,可以考虑
esee
31 天前
你 update 剩余金额一定要放在处理完业务逻辑的事务的最后么,可不可以加锁后就 update 金额 释放锁,然后去处理其他业务逻辑,如果处理出错,订单失败,则回滚剩余金额。。这样慢不了多少。。
felo
31 天前
@byehair 感谢,我思考下
yinmin
31 天前
创建事务,直接跑 sql:
update tblStoredValueCard set fldBalance=fldBalance-@value where fldCardID=@id and fldBalance>=@value
然后获取变更记录数,如果变更记录为 0 条就回滚,如果>0 就写其它表,然后 commit trans
lyxxxh2
31 天前
赞同 11 楼。

读写锁 -> 读取数据库为变量 -> 修改 -> 解锁。 # 也就这部分会影响到其他用户
time.sleep(.5)# 业务逻辑
except Exception as e:
加读写锁,回滚。 (怕其他请求读取为变量,所以读也锁)

ps: 似乎有点不对,"a 请求"回滚,"b 请求"的内存变量又不会改。 (不过很难发生)
yinmin
31 天前
@felo 接#13 ,没有显性锁,使用 update 的数据一致性的特性,对并发影响最小吧。
yinmin
31 天前
“显性锁+事务处理”会扼制脏记录特性,可能会严重影响数据库性能
felo
31 天前
@esee 业务逻辑现在也不是很复杂,就是锁了之后写了用券记录,更新金额。写用券记录后置也是准备优化的点
felo
31 天前
@yinmin 感谢我也看下
esee
31 天前
@felo 个人感觉首先在处理逻辑上优化会比较好,像我刚刚说的加锁后立刻 update 后释放延迟不了多少,贸然引入第三方组件比如消息队列会增加业务复杂度,久而久之就变屎山了,尤其是系统本来就没用到消息队列的情况下。。。
yinmin
31 天前
@felo 一个事务会有多条 sql 交互,应用服务器与数据库服务器交互 1 次至少 1-2ms ,如果一个事务有 5 次 sql 交互,总耗时 6-10ms ,加锁的情况下 100 次事务处理就累积耗时 1 秒+,感知明显。优化方式是用数据库的存储过程,减少应用服务器与数据库服务器的网络延时。

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

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

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

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

© 2021 V2EX