如何设计一个几十万在线用户弹幕系统需求方案
目录
- 1: 需求背景
- 2 技术选型
- 2-1: 客户端轮训
- 2-2: WebSocket主动推送
- 3: 弹幕初始架构
- 4:弹幕架构演进
- 5:弹幕存储
- 6:弹幕查询
- 7:总结
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:总结
对于弹幕系统来说,难点就在于二个,
- 第一:对于大量消息推送到客户端
- 第二:就是消息的异步存储了
以上就是如何设计一个几十万在线用户弹幕系统方案的详细内容,更多关于几十万在线用户弹幕系统的资料请关注我们其它相关文章!
相关推荐
-
vue中如何使用vue-baberrage生成弹幕
目录 如何使用vue-baberrage生成弹幕 vue弹幕实现及优化 总结 如何使用vue-baberrage生成弹幕 vue-baberrage这个插件本身有好多属性使用后不生效,不知道是不是自己使用的问题 T_T 安装弹幕插件: npm install vue-baberrage --save 创建vue组件,在组件中引用vue-baberrage: import Vue from 'vue'; import { vueBaberrage, MESSAGE_TYPE } from
-
JS前端千万级弹幕数据循环优化示例
目录 引言 1.如何删除数组中的元素 2.10000,000条消息如何优化? 场景 常规思路: 产生的问题 优化策略 代码实现 效果展示 小结 游标法代替splice 二分查找 完结 引言 最近做了直播相关的业务,然后对于大数据相关的优化做了一下复盘. 为了了解我是怎么做这个优化的,我们先从如何按照特定的条件删除一个数组说起. 1.如何删除数组中的元素 场景:有一个数组,需要删除满足条件的数组. 示例: const arr = [1,2,3,4,5,6,7,8] 删除小于5的元素,删除后的元素为
-
JS实现弹幕小案例
本文实例为大家分享了JS实现弹幕小案例的具体代码,供大家参考,具体内容如下 效果图: 步骤分析: 1.收集用户输入内容,根据内容创建一个标签--span,追加到某个容器中 2.为元素设置位置 left:右侧--大容器外面 top:上半区 3.通过样式设置来实现元素的动画,也可以通过定时器的方式实现动画 4.细节 文本颜色随机 span动画结束之后应该进行自动的清除 html代码: <div class="boxDom" id="boxDom">
-
JavaScript CSS解析B站的弹幕可以不挡人物原理及技巧
目录 正文 demo Experimental: 这是一个实验中的功能 正文 那天在B站看视频的时候偶然发现当字幕遇到人物的时候就被裁切了,不会挡住人物,觉得很神奇,于是决定一探究竟. 高端的效果,往往只需要采用最朴素的实现方式,忙碌了两个小时,陈师傅打开了F12,豁然开朗.一张图片+一个属性,直接搞定. demo 为了印证我的想法,我决定自己写一个demo <!DOCTYPE html> <html lang="en"> <head> <m
-
asp实现一个统计当前在线用户的解决方案
一个统计当前在线用户的解决方案 在做一个在线交流的网站时,有个问题很令我头疼,就是关于实时统计在线用户的问题,客户要求:统计当前在线人数.游客人数.会员人数.在线用户列表,包括游客.会员和管理员(如果是游客,则自动生成游客的ID,如果是会员,则显示会员姓名).因为它要求有实时性,则首先我将用global.asa解决的想法pass掉. 问题的关键是如何判断用户已经离开,和当用户离开时如何执行一个文件或一个函数. 经过和网上一些朋友的探讨,终于解决了这个问题. 解决的原理为:编写一个通用页面,所谓的
-
用Python设计一个经典小游戏
本文主要介绍如何用Python设计一个经典小游戏:猜大小. 在这个游戏中,将用到前面我介绍过的所有内容:变量的使用.参数传递.函数设计.条件控制和循环等,做个整体的总结和复习. 游戏规则: 初始本金是1000元,默认赔率是1倍,赢了,获得一倍金额,输了,扣除1倍金额. 玩家选择下注,押大或押小: 输入下注金额: 摇3个骰子,11≤骰子总数≤18为大,3≤骰子总数≤10为小: 如果赢了,获得1倍金额,输了,扣除1倍金额,本金为0时,游戏结束. 程序运行结果是这样的: 现在,我们来梳理下思路. 我们
-
使用ASP记录在线用户的数量的代码
网络的访问量是每一个做网站的网友们都非常关心的问题.如何得知有多少个人正在访问你的网站呢?如何将每天的访问量记录下来? 下面就是一个解决方案. 当有用户开始访问网站时,服务器端的Global.asa将会被访问.将会给用户开启一个Session.可以给每一个用户设置自己的个人用户信息.这里就不多进行解释了.在Global.asa中有当Application启动和Session启动时的消息响应函数.可以敲入如下的代码. 复制代码 代码如下: < SCRIPT LANGUAGE="VBScri
-
java web监听器统计在线用户及人数
在线用户使用HttpSessionListener监听器统计 每当一个session会话建立 在线用户人数+1 每当一个session会话销毁 在线用户人数-1 使用ServletRequestListener监听器统计用户信息 每当一个request建立 将当前用户放入集合 每当session会话销毁 将当前用户移出集合 我使用的是Servlet3.0 监听器直接使用注解@webListener即可 不用在web.xml中布局 在web.xml中配置session-timeout标签
-
redis通过位图法记录在线用户的状态详解
前言 在进入今天的主题前,先简单地解释下Redis中的位图到底是什么.Redis官方文档对于位图的介绍如下: 位图不是一个真实的数据类型,而是定义在字符串类型上的面向位的操作的集合.由于字符串类型是二进制安全的二进制大对象,并且最大长度是 512MB,适合于设置 2^32个不同的位. 位操作分为两组:常量时间单个位的操作,像设置一个位为 1 或者 0,或者获取该位的值.对一组位的操作,例如计算指定范围位的置位数量. 位图的最大优势是有时是一种非常显著的节省空间来存储信息的方式.例如,在一个系统中
-
SpringBoot使用Redis的zset统计在线用户信息
统计在线用户的数量,是应用很常见的需求了.如果需要精准的统计到用户是在线,离线状态,我想只有客户端和服务器通过保持一个TCP长连接来实现.如果应用本身并非一个IM应用的话,这种方式成本极高. 现在的应用都趋向于使用心跳包来标识用户是否在线.用户登录后,每隔一段时间,往服务器推送一个消息,表示当前用户在线.服务器则可以定义一个时间差,例如:5分钟内收到过客户端心跳消息,视为在线用户. 在线用户统计的实现 基于数据库实现 最简单的办法,就是在用户表,添加一个最后心跳包的日期时间字段 last_act
-
基于Java设计一个短链接生成系统
目录 引言 短链接的原理 短链接怎么设计的 引言 相信大家在生活中,特别是最近的双十一活动期间,会收到很多短信,而那些短信都有两个特征,第一个是几乎都是垃圾短信,这个特点此处可以忽略不计,第二个特点是链接很短,比如下面这个: 我们知道,短信有些是有字数限制的,直接放一个带满各种参数的链接,不合适,另外一点是,不想暴露参数.好处无非以下: 太长的链接容易被限制长度 短链接看着简洁,长链接看着容易懵 安全,不想暴露参数 可以统一链接转换,当然也可以实现统计点击次数等操作 那背后的原理是什么呢?怎么实
-
基于PHP实现一个简单的在线聊天功能
目录 前端页面 数据库 实现思路 1.showPage() 2.newChat() 3.getChatText() 4.getChatTemp() 5.pushChat() 总结 要实现功能,首先要做前端,经过对比其他网站的在线聊天功能,发现除了基本的聊天功能以外,还要注意以下几点. 一次只能和一个人聊天,但是可以随意切换其他人. 如果用户是从"发送消息" 入口进来的,那么当前马上就切换到对应的聊天窗口,而且如果之前有过聊天记录,应该把聊天记录也展示出来. 如果是从"我的消息
-
SpringSession通过Redis统计在线用户数量的实现代码
最近遇到一个比较紧急的任务,要求统计在线用户,目的是配合性能测评,要求证明自己系统的在线用户能够达标,不过系统因为历史原因,并没有这个功能,所以只能去springSession官网和网上搜资料,想到通过统计redis里缓存的数据 因为系统原先的逻辑是使用Spring Session加上Redis做的会话共享实现的单点登录,登录之后会在session设置一个key值表示用户已经登录过,同时重写HttpServletRequestWrapper 设置remoteUser数据值 class Remot
-
杀掉oracle在线用户脚本分享
杀掉oracle在线用户,在oracle所在服务器上使用root用户执行该脚本参数说明$1为该oracle用户 复制代码 代码如下: #!/bin/shfunction _oracleplus(){su - oracle -c "$oraclehome/bin/sqlplus /nolog" <<EOFconnect / as sysdba;$1exitEOF}echo "start select $1 session!!!"selectUS="
随机推荐
- vue2+el-menu实现路由跳转及当前项的设置方法实例
- IIS 7.5 设置允许下载exe文件的解决方法
- Swift教程之基本运算符详解
- bootstrap Table服务端处理分页(后台是.net)
- PHP6新特性分析
- PHP使用正则表达式清除超链接文本
- Jsp中如何让图片在div中居中
- docker上安装使用mysql镜像
- JQuery表格内容过滤的实现方法
- 关于2014年五一劳动节放假安排的通知
- php中实现xml与mysql数据相互转换的方法
- 详解MongoDB for C#基础入门
- layui选项卡效果实现代码
- JS判断页面是否出现滚动条的方法
- 利用Node.js编写跨平台的spawn语句详解
- JS中confirm,alert,prompt函数使用区别分析
- 详解如何在Spring Boot项目使用参数校验
- C语言实现的猴子分桃问题算法解决方案
- Android DatePicker和DatePickerDialog基本用法示例
- Java的RxJava库操作符的用法及实例讲解
其他
- python 向现有csv追加写入列
- layui 代理后台管理系统
- 部署springboot项目获取resource目录相对路径
- sqlserver substr不是内部函数
- python读取图片信息
- ajax 筛选字符串
- 微信小程序实现下拉菜单切换过度效果
- 解决在vue中axios请求超时的问题
- c 结构体转json
- go.mod 解决依赖冲突
- django filter动态添加条件
- 系统公告微信小程序代码
- 易语言的dll按键精灵调用
- r语言如何导入csv文件
- anaconda 修改依赖
- r数据框合并suffixes
- NGINX拦截固定的url请求
- go 获取RFC3339 时间
- nginx解决静态资源跨域
- java 获取今天整时时间戳