如何設(shè)計(jì)一個(gè)幾十萬在線用戶彈幕系統(tǒng)需求方案
1: 需求背景
現(xiàn)在無論是直播還是電視劇,我們都可以看到上面慢慢的彈幕,如果有一天公司自己要做一個(gè)這樣的滿足十幾萬用戶在線的彈幕系統(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ì)有很多無效的請(qǐng)求,而且不停的去輪訓(xùn)無疑會(huì)給服務(wù)器造成很大的壓力,因?yàn)槟憧蛻舳松?,如果現(xiàn)在有十幾萬的客戶端同時(shí)在線,那么服務(wù)器每隔一段時(shí)間就會(huì)有幾十萬次的查詢壓力。
2-2: WebSocket主動(dòng)推送
隨著現(xiàn)在IM系統(tǒng)的成熟,WebSocket也越來越被重視,WebSocket在當(dāng)服務(wù)器收到消息之后,可以主動(dòng)將消息推送給客戶端。
3: 彈幕初始架構(gòu)
在開始的時(shí)候,因?yàn)橛脩舨欢?,我們只有一臺(tái)服務(wù)器,也能滿足需求,但是試想一下,如果某一天用戶增多了,你這一臺(tái)服務(wù)器真的頂?shù)米∈畮兹f的用戶來訪問嗎???
既然這時(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,然后通過這個(gè)Session將消息推送給這個(gè)用戶,但是用戶Session都是保存在我們本地服務(wù)中的。比如這個(gè)用戶A的Session在服務(wù)器A上,用戶B在服務(wù)器B上,那么你怎么拿到用戶B的Session呢?
很多人會(huì)說,把所有用戶的Session都保存到Redis中不就可以了,其實(shí)這樣也不是不行,但是如果你現(xiàn)在有幾百萬,幾千萬的用戶Session呢?
所以我們可以使用消息中間件或者Redis的發(fā)布訂閱模式,比如使用消息中間件RocketMq,有一個(gè)用戶發(fā)送了一條彈幕,那么就發(fā)送一條消息到MQ中,所有服務(wù)都接受到這條消息之后,然后就可以拿到本地所有用戶的Session,再進(jìn)行發(fā)送。
4:彈幕架構(gòu)演進(jìn)
不知道大家有沒有想過這樣一個(gè)問題,假設(shè)我們現(xiàn)在有10臺(tái)服務(wù)器,每臺(tái)服務(wù)器有一萬人,這時(shí)候,一個(gè)人發(fā)送一條彈幕,那么每臺(tái)服務(wù)器WebSocket都要推送一萬次消息到客戶端,如果這時(shí)候有一萬人發(fā)送了彈幕呢?那么WebSocket是不是就要推送 1萬 * 1萬次數(shù)據(jù)呢。在這種高并發(fā)的情況下,WebSocket會(huì)因?yàn)榘l(fā)送的太頻繁導(dǎo)致各種各樣的問題,比如與客戶端斷開連接等。
所以第二個(gè)難點(diǎn)就在這了
現(xiàn)在我們把所有需要推送的消息都發(fā)送到MQ中,然后在MQ中將消息推送給客戶端。為什么要這么做呢?
在MQ中我們可以進(jìn)行限流,這樣WebSocket就不用頻繁的去操作了。尤其類似于彈幕這種業(yè)務(wù),也不是說要求實(shí)時(shí)的。一般我們發(fā)送一條彈幕,都會(huì)過個(gè)幾秒鐘我們自己才能看見,所以我們可以根據(jù)自己服務(wù)器的性能來決定消費(fèi)速度。
5:彈幕存儲(chǔ)
用戶發(fā)送的彈幕最終都是要進(jìn)行持久化存儲(chǔ)的,就像騰訊視頻一樣,無論你什么時(shí)候去看,那些彈幕都還在。那么彈幕存儲(chǔ)時(shí)機(jī)是什么時(shí)候呢???
一般都會(huì)選擇在用戶發(fā)送一條彈幕之后就存儲(chǔ)這條彈幕,如果用戶發(fā)送一條彈幕我們就同步的將這條數(shù)據(jù)存儲(chǔ)到MySql中,那么這時(shí)候有幾十萬的彈幕該怎么辦? 這時(shí)候數(shù)據(jù)庫的壓力就很大了。因?yàn)閺椖贿@種數(shù)據(jù)丟個(gè)幾條對(duì)我們業(yè)務(wù)沒有任何影響,所以我們可以選擇異步存儲(chǔ),比如將要保存彈幕信息發(fā)送到MQ,MQ異步的將消息存儲(chǔ)到MySql中即可
6:彈幕查詢
對(duì)于彈幕查詢,我們后續(xù)可以將數(shù)據(jù)同步到搜索引擎Elasticsearch中,后續(xù)的查詢就直接查ES就好,就不用查數(shù)據(jù)庫,避免對(duì)數(shù)據(jù)庫造成壓力。
7:總結(jié)
對(duì)于彈幕系統(tǒng)來說,難點(diǎn)就在于二個(gè),
- 第一:對(duì)于大量消息推送到客戶端
- 第二:就是消息的異步存儲(chǔ)了
以上就是如何設(shè)計(jì)一個(gè)幾十萬在線用戶彈幕系統(tǒng)方案的詳細(xì)內(nèi)容,更多關(guān)于幾十萬在線用戶彈幕系統(tǒng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
代碼著色之SyntaxHighlighter項(xiàng)目(最流行的代碼高亮)
dp.SyntaxHighlighter。它可以在網(wǎng)頁中對(duì)各種程序源代碼語法進(jìn)行加亮顯示。支持當(dāng)前流 行的各種編程語言:C#、CSS、C++、Delphi、Java、JavaScript、PHP、Python、Ruby、SQL、Visual Basic、XML / HTML等2014-04-04IDEA使用code?with?me來進(jìn)行多人遠(yuǎn)程編程的實(shí)現(xiàn)
本文主要介紹了IDEA使用code?with?me來進(jìn)行多人遠(yuǎn)程編程的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01Elasticsearch?在地理信息空間索引的探索和演進(jìn)問題分析
本文梳理了Elasticsearch對(duì)于數(shù)值索引實(shí)現(xiàn)方案的升級(jí)和優(yōu)化思考,從2015年至今數(shù)值索引的方案經(jīng)歷了多個(gè)版本的迭代,實(shí)現(xiàn)思路從最初的字符串模擬到KD-Tree,技術(shù)越來越復(fù)雜,能力越來越強(qiáng)大,應(yīng)用場景也越來越豐富,感興趣的朋友跟隨小編一起看看吧2022-06-06