如何設(shè)計(jì)一個(gè)幾十萬(wàn)在線用戶彈幕系統(tǒng)需求方案
1: 需求背景
現(xiàn)在無(wú)論是直播還是電視劇,我們都可以看到上面慢慢的彈幕,如果有一天公司自己要做一個(gè)這樣的滿足十幾萬(wàn)用戶在線的彈幕系統(tǒng),我們?cè)撊绾稳ピO(shè)計(jì)呢
2 技術(shù)選型
彈幕跟我們平時(shí)做的系統(tǒng)不太一樣,平時(shí)做的最多的就是客戶端發(fā)起請(qǐng)求,也就是數(shù)據(jù)都是由客戶端推送到服務(wù)端,但是彈幕是由服務(wù)端推送給客戶端的。比如我們現(xiàn)在在看直播,很多用戶都會(huì)發(fā)送彈幕,然后每個(gè)在線的用戶都可以收到這條彈幕信息。這時(shí)候我們有二種方案
2-1: 客戶端輪訓(xùn)
也就是客戶端不停的去服務(wù)端去拉取數(shù)據(jù),但是會(huì)有一個(gè)弊端,因?yàn)槲覀兠看慰措娨晞〉臅r(shí)候,看一遍一條彈幕只會(huì)顯示一次。如果不停的去輪訓(xùn),會(huì)有很多無(wú)效的請(qǐng)求,而且不停的去輪訓(xùn)無(wú)疑會(huì)給服務(wù)器造成很大的壓力,因?yàn)槟憧蛻舳松伲绻F(xiàn)在有十幾萬(wàn)的客戶端同時(shí)在線,那么服務(wù)器每隔一段時(shí)間就會(huì)有幾十萬(wàn)次的查詢壓力。
2-2: WebSocket主動(dòng)推送
隨著現(xiàn)在IM系統(tǒng)的成熟,WebSocket也越來(lái)越被重視,WebSocket在當(dāng)服務(wù)器收到消息之后,可以主動(dòng)將消息推送給客戶端。
3: 彈幕初始架構(gòu)
在開(kāi)始的時(shí)候,因?yàn)橛脩舨欢?,我們只有一臺(tái)服務(wù)器,也能滿足需求,但是試想一下,如果某一天用戶增多了,你這一臺(tái)服務(wù)器真的頂?shù)米∈畮兹f(wàn)的用戶來(lái)訪問(wèn)嗎???

既然這時(shí)候一臺(tái)服務(wù)器壓力太大,那我們就部署多臺(tái)服務(wù)器,將壓力進(jìn)行分?jǐn)?,這樣每臺(tái)服務(wù)器的壓力就不會(huì)那么大
但是這時(shí)候單臺(tái)服務(wù)器壓力是解決了,那推送消息給每一個(gè)用戶就做不到了,我們知道WebSocket在推送消息的時(shí)候,會(huì)先拿到這個(gè)用戶的Session,然后通過(guò)這個(gè)Session將消息推送給這個(gè)用戶,但是用戶Session都是保存在我們本地服務(wù)中的。比如這個(gè)用戶A的Session在服務(wù)器A上,用戶B在服務(wù)器B上,那么你怎么拿到用戶B的Session呢?
很多人會(huì)說(shuō),把所有用戶的Session都保存到Redis中不就可以了,其實(shí)這樣也不是不行,但是如果你現(xiàn)在有幾百萬(wàn),幾千萬(wàn)的用戶Session呢?
所以我們可以使用消息中間件或者Redis的發(fā)布訂閱模式,比如使用消息中間件RocketMq,有一個(gè)用戶發(fā)送了一條彈幕,那么就發(fā)送一條消息到MQ中,所有服務(wù)都接受到這條消息之后,然后就可以拿到本地所有用戶的Session,再進(jìn)行發(fā)送。

4:彈幕架構(gòu)演進(jìn)
不知道大家有沒(méi)有想過(guò)這樣一個(gè)問(wèn)題,假設(shè)我們現(xiàn)在有10臺(tái)服務(wù)器,每臺(tái)服務(wù)器有一萬(wàn)人,這時(shí)候,一個(gè)人發(fā)送一條彈幕,那么每臺(tái)服務(wù)器WebSocket都要推送一萬(wàn)次消息到客戶端,如果這時(shí)候有一萬(wàn)人發(fā)送了彈幕呢?那么WebSocket是不是就要推送 1萬(wàn) * 1萬(wàn)次數(shù)據(jù)呢。在這種高并發(fā)的情況下,WebSocket會(huì)因?yàn)榘l(fā)送的太頻繁導(dǎo)致各種各樣的問(wèn)題,比如與客戶端斷開(kāi)連接等。
所以第二個(gè)難點(diǎn)就在這了

現(xiàn)在我們把所有需要推送的消息都發(fā)送到MQ中,然后在MQ中將消息推送給客戶端。為什么要這么做呢?
在MQ中我們可以進(jìn)行限流,這樣WebSocket就不用頻繁的去操作了。尤其類似于彈幕這種業(yè)務(wù),也不是說(shuō)要求實(shí)時(shí)的。一般我們發(fā)送一條彈幕,都會(huì)過(guò)個(gè)幾秒鐘我們自己才能看見(jiàn),所以我們可以根據(jù)自己服務(wù)器的性能來(lái)決定消費(fèi)速度。
5:彈幕存儲(chǔ)
用戶發(fā)送的彈幕最終都是要進(jìn)行持久化存儲(chǔ)的,就像騰訊視頻一樣,無(wú)論你什么時(shí)候去看,那些彈幕都還在。那么彈幕存儲(chǔ)時(shí)機(jī)是什么時(shí)候呢???
一般都會(huì)選擇在用戶發(fā)送一條彈幕之后就存儲(chǔ)這條彈幕,如果用戶發(fā)送一條彈幕我們就同步的將這條數(shù)據(jù)存儲(chǔ)到MySql中,那么這時(shí)候有幾十萬(wàn)的彈幕該怎么辦? 這時(shí)候數(shù)據(jù)庫(kù)的壓力就很大了。因?yàn)閺椖贿@種數(shù)據(jù)丟個(gè)幾條對(duì)我們業(yè)務(wù)沒(méi)有任何影響,所以我們可以選擇異步存儲(chǔ),比如將要保存彈幕信息發(fā)送到MQ,MQ異步的將消息存儲(chǔ)到MySql中即可

6:彈幕查詢
對(duì)于彈幕查詢,我們后續(xù)可以將數(shù)據(jù)同步到搜索引擎Elasticsearch中,后續(xù)的查詢就直接查ES就好,就不用查數(shù)據(jù)庫(kù),避免對(duì)數(shù)據(jù)庫(kù)造成壓力。
7:總結(jié)
對(duì)于彈幕系統(tǒng)來(lái)說(shuō),難點(diǎn)就在于二個(gè),
- 第一:對(duì)于大量消息推送到客戶端
- 第二:就是消息的異步存儲(chǔ)了
以上就是如何設(shè)計(jì)一個(gè)幾十萬(wàn)在線用戶彈幕系統(tǒng)方案的詳細(xì)內(nèi)容,更多關(guān)于幾十萬(wàn)在線用戶彈幕系統(tǒng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
VScode?隱藏大量無(wú)用的文件比如在看Linux?kernel或boot時(shí)候
這篇文章主要介紹了VScode?隱藏大量無(wú)用的文件比如在看Linux?kernel或boot時(shí)候,VScode 工程創(chuàng)建先在 Ubuntu 下編譯一下 uboot,然后將編譯后的 uboot 文件夾復(fù)制到 windows 下,并創(chuàng)建VScode 工程,需要的朋友可以參考下2022-10-10
架構(gòu)師說(shuō)比起404我們更怕200錯(cuò)誤
這篇文章主要為大家介紹了架構(gòu)中404我們更怕200錯(cuò)誤的解決及分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
fiddler抓包小技巧之自動(dòng)保存抓包數(shù)據(jù)的實(shí)現(xiàn)方法分析【可根據(jù)需求過(guò)濾】
這篇文章主要介紹了fiddler抓包小技巧之自動(dòng)保存抓包數(shù)據(jù)的實(shí)現(xiàn)方法,較為詳細(xì)的分析了fiddler自動(dòng)保存抓包數(shù)據(jù)及根據(jù)需求過(guò)濾相關(guān)操作技巧,需要的朋友可以參考下2020-01-01
如何使用VSCode 運(yùn)行調(diào)試插件代碼
這篇文章主要介紹了如何使用VSCode 運(yùn)行調(diào)試插件代碼的相關(guān)資料,需要的朋友可以參考下2020-01-01
分享最新Sublime Text4 Build 4107注冊(cè)碼(密鑰)漢化及完美永久破解方法
分享一個(gè)適用最新Sublime Text4 Build 4107注冊(cè)碼(密鑰)及Sublime Text 4完美永久破解方法,需要的朋友可以參考下2021-05-05
Postman配置多環(huán)境請(qǐng)求地址的實(shí)現(xiàn)
本文主要介紹了Postman配置多環(huán)境請(qǐng)求地址的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01

