请教秒杀抢购架构设计问题

2022-09-07 10:04:00 +08:00
 franklinre
需求:用户可以抢购某个商品,提交信息后跳转到指定页面( http:\\host\productId\userId )等待刷新,后台任务队列处理完成后,刷新出抢购的订单信息。
这样可以等待 order_table 出现相应的 productId 和 userId 的记录出现时能正确刷新出订单信息。
但是,如果 order_table 已经有该 productId 和 userId 的记录或者允许多次抢购,order_table 会出现多条 productId 和 userId 的记录,该怎么确定指定的订单信息呢?
我暂定是前端生成一个 uuid ,跳转到: http:\\host\productId\userId\uuid 等待刷新,uuid 存进该条记录到 order_table 。
各位老哥,你们也是类似这样设计的吗?

另外,我看到很多文章设计抢购系统是在 redis 放进库存数量,抢购成功扣库存,类似的设计。
我想,能不能生成预备订单数据,库存 100 个,就先生成 100 个预备订单,抢购时就查找有无预备订单,有的话就把用户信息放进该预备订单,就表示抢购成功。
问:在每次订单只允许抢购一个商品的前提下,是否方法二的可靠性更强?
3390 次点击
所在节点    问与答
30 条回复
wangchonglie
2022-09-07 17:42:35 +08:00
@lmshl #4 mark 一下
micean
2022-09-07 17:58:32 +08:00
@lmshl

意义不大,实际业务场景会涉及到很多,比如限定单个用户购买数量
lmshl
2022-09-07 18:37:23 +08:00
@micean 这可太简单了
如果仅允许一次下单,直接前过滤,TPS 丝毫不受影响
如果允许多次下单,但总购买数量不能超过 n 个,那无非就是在软件事务内存里多加一个 if/else branch ,TPS 下降可能都低于可测量误差了
micean
2022-09-08 10:17:32 +08:00
@lmshl

举例“限定单个用户购买数量”,一是架构里要涉及商品以外的数据加入到事务内存中增加了项目维护复杂度,二是看集群内存如何保证强一致性。单机跑性能意义真的不大。
lmshl
2022-09-08 10:58:35 +08:00
@micean STM ( Software transactional memory )软件事务内存,https://hackage.haskell.org/package/stm
lmshl
2022-09-08 11:01:09 +08:00
@micean 如果你了解 STM 的话就不会这么说了,软件事务远比分布式事务更容易实现,也更容易做到高并发高吞吐量,几行代码能描述清楚的规则,犯不着上分布式事务,上了分布式事务你不得设计回滚么?

而且我的事务以持久化视为事务提交并返回客户端,已经把系统最重要的部分模拟出来了,且保证正确性。
micean
2022-09-08 11:54:49 +08:00
@lmshl

也没有说分布式事务(基本也是避免使用分布式事务)。你的性能我并没有异议,stm 没毛病。但是场景更像网络游戏而不是电商。
现实是不可能只用一台服务器去承载所有业务(只用一台服务器的电商业务量相信也用不上你的架构),既然是集群的话,必然就要考虑一致性的问题,秒杀的压力并不在于最终事务,而是在于查询过滤的效率,前面小哥也证明了加锁减库存也不差。
lmshl
2022-09-08 13:57:04 +08:00
@micean 我列举单机数据的意思是,“我只用单机(甚至单核)就可以做的比别人集群更快”
而不是我只能用单机,实际上我是用的框架是 akka-cluster-sharding ,是一套水平伸缩集群,意味着并发抢购多件商品的时候,性能是随着节点增加而近乎线性增长的。

而且,你说场景更像网络游戏的话,akka-cluster-sharding 的一大优势应用场景就是 MMORPG ,腾讯和暴雪都在用 akka 做百万同服同时在线。

加锁减库存的问题在于,锁掉整个商品的长时间事务,这个商品的交易会被串行化导致吞吐量急剧下降。
如果采用预扣除算法,又会要求所有其他组件都要设计回滚操作,增加了整个架构的成本。
micean
2022-09-08 17:16:40 +08:00
@lmshl

一个商品只能在一个 shard 上对不对?如果用户提交多个商品并带有跨店满减优惠、代金券,是不是要设计回滚
lmshl
2022-09-08 17:55:22 +08:00
@micean 没见过有在秒杀业务上做加法的,业务做减法才是常态吧。

如果硬要在秒杀系统上加跨商品结算的话,我选择 saga pattern ,可能每单结算时间会长一点,但不会降低每个商品交易吞吐量,总吞吐量影响也不大。

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

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

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

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

© 2021 V2EX