一则面试题,如果 10 万人同时打赏某快手主播,对支付系统来说,瓶颈在哪里,该怎么解决呢,组件是 mysql, redis 等, 假如打赏的钱加到主播余额而不是去银行那边进行交易

2020-06-08 10:37:34 +08:00
 jdz
11100 次点击
所在节点    程序员
58 条回复
chenzj3126
2020-06-08 13:29:55 +08:00
10W 用户,在内部分队列,然后发布到 redis 不同的队列中,多个消费者消费,更新的时候需要加锁
no1xsyzy
2020-06-08 13:42:44 +08:00
@firefox12 #19 交易消息掉了感觉问题不大,最多打赏失败了想打赏没打上,或者提示失败实际成功罢了。
liuxu
2020-06-08 13:52:19 +08:00
100k 交易事务,基本上前后端都得集群,瓶颈在数据库事务上,上数据库集群吧,任何交易一定要 100%准确,包括交易日志千万不能有丢失风险,能交易成功的就不要让他失败,加点钱加硬件,一笔交易硬件的钱稳稳的赚回来
passerbytiny
2020-06-08 14:14:18 +08:00
这是主观题,请不要网上提问式的寻找答案,因为没有标准答案。

这也是一个随便想起来的题,问题描述本来就有问题。后面“假如”那段,已经把前面问题的答案暴露了。答案是:瓶颈是去银行那边进行交易,尤其是加钱那一块。这很好解释:出钱账户是 N,加钱账户是 1,从 N 个出入到 1 里面,1 那里最容易瓶颈。解决方案因实际情况而宜,我不想费事打字,但是可以肯定 那个“假如”的方案是行不通的,因为 N 至 1 的情况仍然存在(当然也不是一无是出,它可以解决“银行系统垃圾”的瓶颈)而且监管机构也不会同意。
jaakali
2020-06-08 14:19:37 +08:00
感觉这里的支付因应该是虚拟商品(虽然也是钱买的)打赏吧,都在快手用户的账户里,用户-主播+?
NoobPhper
2020-06-08 14:23:53 +08:00
哪个 sb 问的 哈哈哈哈
jaakali
2020-06-08 14:34:22 +08:00
好吧,我错了,题主问的是 2 个问题
hbolive
2020-06-08 14:37:31 +08:00
先把打赏记录 insert 再说,insert 开销很小,10W 根本不在话下,然后再根据打赏记录,把金额同步到主播账户。。
zouqiang
2020-06-08 14:45:31 +08:00
热点账户问题,扣减后异步加
wangdashuai
2020-06-08 14:56:08 +08:00
@binux 这个思路好。
tingfang
2020-06-08 15:15:17 +08:00
记流水,主播账户异步慢慢加。
LennieChoi
2020-06-08 15:25:17 +08:00
这题是不是想考分布式锁啊,redis 做个分布式锁,10w 并发负载均衡进来后,请求落到不同节点,然后用分布式锁控制每一笔打赏入库 mysql,但这样的话 10w 条消化掉会很慢吧,属于要同步消化掉 10w 条。在这个基础上有啥优化的空间呢?(纯属顺着题意想的,正常的话做个订单系统,做 kafka 消费应该没啥瓶颈。但顺着这个题意有啥好的优化吗)
xiangyuecn
2020-06-08 15:43:22 +08:00
“10 万人同时打赏”,是不是意味着至少会有 100 万+的人同时在刷屏?意味着至少 1000 万人挤在一个直播间观看直播?告辞,我要有这能耐,我还拘泥于 mysql redis ?








他娘的,这个 10 万人同时打赏,瞬时并发可以赶上双十一的支付了的吧😂 就算你扛住了,牵涉到的第三方能不能抗住也是个问题🐶 面试官想套路我造原子弹的核心机密?
LennieChoi
2020-06-08 15:59:19 +08:00
@LennieChoi 想的片面了,都在讲怎么给主播加余额这事,但是在这之前还有一步,打赏者需要实时扣余额,判断够不够打赏,这块我觉得直接 mysql 事物操作,数据库会有压力,是不是可以在某一个人第一次打赏的时候将他自己的余额等关键信息从数据库读到 redis(或许做个过期),然后接下来的打赏中直接改写 redis 判断够不够扣,产生打赏订单后,最终消费订单时同时处理给主播加余额和给打赏者扣余额,这样的话为了分摊读 redis 的压力,redis 做个分片?
coolmenu
2020-06-08 16:04:15 +08:00
屏幕打出卡号,让用户自己网银转账!
我们这是把压力化解到前端,最时髦的做法啦
ljzxloaf
2020-06-08 16:21:43 +08:00
1. redis 做缓存,只用来展示不做业务强依赖,group commit 降低 redis 压力;
2. 可靠消息保证分布式事务,也能起到削峰填谷的作用,收到消息再慢慢更新 db 。
3. redis 根据需求周期性同步 db 数据,保证数据相对准确。就像点赞、分享这类统计数据,不需要实时,但也不能太离谱
BlackBerry999
2020-06-08 16:53:18 +08:00
@xiangyuecn 被你猜中了!
ISSSSSSS
2020-06-08 16:55:14 +08:00
这个问题挺有意思的也是一个比较真实的场景。
按照题目来分析,那么打赏主播总共分四步。
1 用户创建打赏订单。
1.1 同时存储 10w 条数据。数据库吞吐量的问题。如果是 mysql 的话可能需要分库分表。
1.2 唯一主键问题。比如生成不重复的订单编号。同样也可以用分片的原理,比如给服务本身设定一个不重复的订单前缀等等。
总结:这个问题的本身就是利用分片可以解决大部分问题。
2 用户支付打赏订单。
2.1 支付回调信息处理。总的来说解决了问题 1,这个就不算啥问题。
3 根据打赏订单创造主播余额充值订单。
3.1 问题同 1 。
4 充值订单完成后更新余额。
4.1 大量请求更新同一个数据的字段。可以考虑批量更新法,比如更新的金额在内存或 redis 累计,积累到一定时间,再更新至数据库中。
4.2 推荐使用乐观锁。比如通过版本号去更新余额,解决并发更新一条数据的问题。这笔直接使用 for update 效率要高一些,而且与 4.1 搭配更是完美,因为更新不成功,内存中的数字就一直累积下去,也挺好。
ISSSSSSS
2020-06-08 16:58:15 +08:00
@ISSSSSSS 补充一下,如果条件限定在 mysql,那么就可以考虑 mysql 多主多从多数据源。重写数据访问中间件,直接按照用户 id 规则去访问不同的数据源。
lewis89
2020-06-08 17:00:31 +08:00
@ISSSSSSS #38 热点数据写 redis 然后回写 db 是一个不错的思路

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

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

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

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

© 2021 V2EX