【架构设计】如何设计一个几十万在线用户弹幕系统

news/2024/12/2 20:35:48/

文章目录

  • 一、前言
  • 二、项目介绍
    • 客户端轮询
    • WebSocket主动推送
  • 三、弹幕初始架构
  • 四、弹幕架构演进
  • 五、弹幕存储
  • 六、弹幕查询
  • 七、总结

一、前言

现在无论是直播还是电视剧,我们都可以看到上面慢慢的弹幕,满足十几万用户在线的弹幕系统,我们该如何去设计呢?

二、项目介绍

弹幕跟我们平时做的系统不太一样,平时做的最多的就是客户端发起请求,也就是数据都是由客户端推送到服务端,但是弹幕是由服务端推送给客户端的。

比如我们现在在看直播,很多用户都会发送弹幕,然后每个在线的用户都可以收到这条弹幕信息。

这时候我们有二种方案

客户端轮询

也就是客户端不停的去服务端去拉取数据,但是会有一个弊端,因为我们每次看电视剧的时候,看一遍一条弹幕只会显示一次。如果不停的去轮询,会有很多无效的请求,而且不停的去轮询无疑会给服务器造成很大的压力,因为你客户端少,如果现在有十几万的客户端同时在线,那么服务器每隔一段时间就会有几十万次的查询压力。

WebSocket主动推送

随着现在IM系统的成熟,WebSocket也越来越被重视,WebSocket在当服务器收到消息之后,可以主动将消息推送给客户端。

三、弹幕初始架构

在开始的时候,因为用户不多,我们只有一台服务器,也能满足需求,但是试想一下,如果某一天用户增多了,你这一台服务器真的顶得住十几万的用户来访问吗???
在这里插入图片描述

既然这时候一台服务器压力太大,那我们就部署多台服务器,将压力进行分摊,这样每台服务器的压力就不会那么大

但是这时候单台服务器压力是解决了,那推送消息给每一个用户就做不到了,我们知道WebSocket在推送消息的时候,会先拿到这个用户的Session,然后通过这个Session将消息推送给这个用户,但是用户Session都是保存在我们本地服务中的。比如这个用户A的Session在服务器A上,用户B在服务器B上,那么你怎么拿到用户B的Session呢?

很多人会说,把所有用户的Session都保存到Redis中不就可以了,其实这样也不是不行,但是如果你现在有几百万,几千万的用户Session呢?

所以我们可以使用消息中间件或者Redis的发布订阅模式,比如使用消息中间件RocketMq,有一个用户发送了一条弹幕,那么就发送一条消息到MQ中,所有服务都接受到这条消息之后,然后就可以拿到本地所有用户的Session,再进行发送。
在这里插入图片描述

四、弹幕架构演进

不知道大家有没有想过这样一个问题,假设我们现在有10台服务器,每台服务器有一万人,这时候,一个人发送一条弹幕,那么每台服务器WebSocket都要推送一万次消息到客户端,如果这时候有一万人发送了弹幕呢?那么WebSocket是不是就要推送 1万 * 1万次数据呢。在这种高并发的情况下,WebSocket会因为发送的太频繁导致各种各样的问题,比如与客户端断开连接等。

所以第二个难点就在这了
在这里插入图片描述

现在我们把所有需要推送的消息都发送到MQ中,然后在MQ中将消息推送给客户端。为什么要这么做呢?

在MQ中我们可以进行限流,这样WebSocket就不用频繁的去操作了。尤其类似于弹幕这种业务,也不是说要求实时的。一般我们发送一条弹幕,都会过个几秒钟我们自己才能看见,所以我们可以根据自己服务器的性能来决定消费速度。

五、弹幕存储

用户发送的弹幕最终都是要进行持久化存储的,就像腾讯视频一样,无论你什么时候去看,那些弹幕都还在。那么弹幕存储时机是什么时候呢?

一般都会选择在用户发送一条弹幕之后就存储这条弹幕,如果用户发送一条弹幕我们就同步的将这条数据存储到MySql中,那么这时候有几十万的弹幕该怎么办? 这时候数据库的压力就很大了。因为弹幕这种数据丢个几条对我们业务没有任何影响,所以我们可以选择异步存储,比如将要保存弹幕信息发送到MQ,MQ异步的将消息存储到MySql中即可
在这里插入图片描述

六、弹幕查询

对于弹幕查询,我们后续可以将数据同步到搜索引擎Elasticsearch中,后续的查询就直接查ES就好,就不用查数据库,避免对数据库造成压力。

七、总结

对于弹幕系统来说,难点就在于二个,

  • 第一:对于大量消息推送到客户端,
  • 第二:就是消息的异步存储了。

思考:基于netty框架如何实现?大家可以思考!对于这个方案还有什么不足的地方,欢迎大家提出,一起进步。


http://www.ppmy.cn/news/45095.html

相关文章

装饰模式的C++实现——设计模式学习(1)

编程目的:理解装饰模式及其用法。 装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。[DP] 装饰模式是一种结构型设计模式,它允许在运行时动态地给对…

【实用】解决.gitignore文件不生效

文章目录 背景原因解决方法 背景 针对:.gitignore文件不生效,哪怕是将某个目录、文件加入到忽略规则里 原因 .gitignore只能忽略那些原来没有被追踪的文件如果某些文件已经被纳入了版本管理中,那么修改.gitignore是无效的。 解决方法 先把本…

python实现将给定列表划分为元素和大致相等的两个子列表

假设现有列表[300,150,75,38,19,9,5,2],我想把它划分为两个子列表,并要求两个列表的元素和大致相等,应该如何做? 这是一个很有意思的问题,我们期待的答案应该是: list1: [300] list2: [150,75,38,19,9,5,…

如何让心情保持平静?100多条禅修心法

静的层次和阶段 静首先是不要去争,没有任何争的心,没有任何杂念心。静有几个层次阶段: ⒈. 自己的心情相对于自己平静,是平静的第一个阶段。 ⒉. 第二个平静的阶段是:别人觉得你很静,自己也很静&#xf…

面试题整理

1、new关键字干了什么? let a new Object() let a Object() let a {} 都会创建一个新对象 new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。 function Person(name) { // 构造函数Person()this.name name;// this.prototype Obj…

Python中的@cache巧妙用法

缓存是一种空间换时间的策略,缓存的设置可以提高计算机系统的性能,这篇文章主要介绍了Python中的cache巧妙用法,需要的朋友可以参考下 Python中的cache有什么妙用? 缓存是一种空间换时间的策略,缓存的设置可以提高计算机系统的性…

游戏运营专员的职责有哪些?提高游戏收入的关键是什么?

游戏运营是将一款游戏平台推入市场,通过对平台的运作,使用户从接触、认识、再到了解实际线上的一种操作、最终成为这款游戏平台的忠实玩家的这一过程。同时通过一系列的营销手段达到提高线上人数,刺激消费增长利润的目的。 游戏运营专员的职…

安装pandas遇到No module named ‘_bz2’ 的解决方案

出现这个问题我们可以按照这篇博客去解决: https://blog.csdn.net/bf96163/article/details/128654915 如果解决不了,可以这样去做: 1.确保安装了 对应的库 // ubuntu安装命令 sudo apt-get install bzip2-devel // centos安装命令 sudo y…