如何设计一个几十万在线用户弹幕系统需求方案
1: 需求背景
现在无论是直播还是电视剧,我们都可以观到上面慢慢的弹幕,假如有一天公司自己要做一个这样的满意十几万用户在线的弹幕系统,我们该如何往设计呢
2 技术选型
弹幕跟我们平时做的系统不太一样,平时做的最多的就是客户端发起哀求,也就是数据都是由客户端推送到服务端,但是弹幕是由服务端推送给客户端的。比如我们现在在观直播,很多用户都会发送弹幕,然后每个在线的用户都可以收到这条弹幕信息。这时候我们有二种方案
2-1: 客户端轮训
也就是客户端不停的往服务端往拉取数据,但是会有一个弊端,因为我们每次观电视剧的时候,观一遍一条弹幕只会显示一次。假如不停的往轮训,会有很多无效的哀求,而且不停的往轮训无疑会给服务器造成很大的压力,因为你客户端少,假如现在有十几万的客户端同时在线,那么服务器每隔一段时间就会有几十万次的查询压力。
2-2: WebSocket主动推送
随着现在IM系统的成熟,WebSocket也越来越被重视,WebSocket在当服务器收到消息之后,可以主动将消息推送给客户端。
3: 弹幕初始架构
在开始的时候,因为用户不多,我们只有一台服务器,也能满意需求,但是试想一下,假如某一天用户增多了,你这一台服务器真的顶得住十几万的用户来访问吗???
既然这时候一台服务器压力太大,那我们就部署多台服务器,将压力入行分摊,这样每台服务器的压力就不会那么大
但是这时候单台服务器压力是解决了,那推送消息给每一个用户就做不到了,我们知道WebSocket在推送消息的时候,会先拿到这个用户的Session,然后通过这个Session将消息推送给这个用户,但是用户Session都是保存在我们本地服务中的。比如这个用户A的Session在服务器A上,用户B在服务器B上,那么你怎么拿到用户B的Session呢?
很多人会说,把所有用户的Session都保存到Redis中不就可以了,其实这样也不是不行,但是假如你现在有几百万,几千万的用户Session呢?
所以我们可以使用消息中间件或者Redis的发布订阅模式,比如使用消息中间件RocketMq,有一个用户发送了一条弹幕,那么就发送一条消息到MQ中,所有服务都接受到这条消息之后,然后就可以拿到本地所有用户的Session,再入行发送。
4:弹幕架构演入
不知道大家有没有想过这样一个问题,假设我们现在有10台服务器,每台服务器有一万人,这时候,一个人发送一条弹幕,那么每台服务器WebSocket都要推送一万次消息到客户端,假如这时候有一万人发送了弹幕呢?那么WebSocket是不是就要推送 1万 * 1万次数据呢。在这种高并发的情况下,WebSocket会因为发送的太频繁导致各种各样的问题,比如与客户端断开连接等。
所以第二个难点就在这了
现在我们把所有需要推送的消息都发送到MQ中,然后在MQ中将消息推送给客户端。为什么要这么做呢?
在MQ中我们可以入行限流,这样WebSocket就不用频繁的往操作了。尤其类似于弹幕这种业务,也不是说要求实时的。一般我们发送一条弹幕,都会过个几秒钟我们自己才能观见,所以我们可以根据自己服务器的性能来决定消费速度。
5:弹幕存储
用户发送的弹幕最终都是要入行持久化存储的,就像腾讯视频一样,无论你什么时候往观,那些弹幕都还在。那么弹幕存储时机是什么时候呢???
一般都会选择在用户发送一条弹幕之后就存储这条弹幕,假如用户发送一条弹幕我们就同步的将这条数据存储到MySql中,那么这时候有几十万的弹幕该怎么办? 这时候数据库的压力就很大了。因为弹幕这种数据丢个几条对我们业务没有任何影响,所以我们可以选择异步存储,比如将要保存弹幕信息发送到MQ,MQ异步的将消息存储到MySql中即可
6:弹幕查询
对于弹幕查询,我们后续可以将数据同步到搜索引擎Elasticsearch中,后续的查询就直接查ES就好,就不用查数据库,避免对数据库造成压力。
7:总结
对于弹幕系统来说,难点就在于二个,
- 第一:对于大量消息推送到客户端
- 第二:就是消息的异步存储了
以上就是如何设计一个几十万在线用户弹幕系统方案的具体内容,更多关于几十万在线用户弹幕系统的资料请关注其它相关文章!