有个 coupon-service (优惠券服务)部署在 N 台机器上,该服务提供一个抢券接口对外使用。
业务逻辑大概是:
1.用户随机从优惠券表拿一条数据(查询)
2.将数据插入到用户优惠券表(更新)
3.删除优惠券表的该优惠券(删除)
现在该接口预估峰值并发请求在 5K~10K 左右,怎样在高并发情况下保证服务的可靠性和数据的一致性?目前想到的是,将所有优惠券放入 activeMQ,每个领券请求去 MQ 中 POP 数据,但是如果出现异常情况该如何回滚数据? 求大家谈谈经验。。。
1
billlee 2019-06-26 23:56:20 +08:00
要不换个思路,把抢券请求放 mq, 然后服务根据 mq 异步发券。
|
2
npe OP 293 次点击,1 条回复,这是技术论坛吗。。
|
3
mejee 2019-06-27 08:07:19 +08:00 via Android
先查再删的话应该会多个线程查到同一个记录吧? MQ 是个选择,但是好像只能按照顺序拿,不能随机拿吧。可以换个思路,往 MQ 放数据的时候可以按照随机的顺序放。至于异常情况的处理,一般 MQ 有恢复机制吧
|
4
ikaros 2019-06-27 09:14:18 +08:00
按照你这个思路出了异常把优惠券再 push 进 MQ 还回去咯
另外有个方法就是有一个中心调度优惠券的服务把数量下发到每个服务器咯,当下面服务器库存不够再请求调度服务器这样? |
5
npe OP @mejee 对,这就是并发会出现的问题,所以选择使用 MQ 来做同步消费。关于 MQ 的异常恢复我再研究研究。。
|
6
luw2007 2019-06-27 13:59:24 +08:00
优惠券不会比 12306 复杂。 优惠券提前生成,乱序放到 redis 的列表里面,或者 MQ 里面。
redis 列表可以按照用户 hash,这样可以减少一次锁。并且可以拆分到多个 redis 中,增加 qps ( 1w qps 用不到)。 拿到优惠券之后,就同步记录用户流水,并更新优惠券状态。 如果更新成功再记录流水。 如果需要同步快速返回,可以将更新优惠券状态改成异步处理,但是到账也是异步。 如果 qps 达不到要求还要减少 io。可以以 redis 数据为准,则还可以减少用户流水的记录(存在优惠券丢失的情况,更新 redis 成功,写 mysql 失败。需要业务逻辑去补充这类数据)。 |