直播評論系統是電商系統一個經常使用的功能,即在發佈新品的時候,爲了吸引用戶參與和營造互動氣氛,讓參與的每一個人均可以發消息,發完後每一個人均可以即時看到新消息,原型和 http://live.oneplusbbs.com/ 差很少。前端
假如要求在線用戶數是20W,你會如何設計系統呢?sql
任何系統設計都不能離開用例設計,脫離業務講技術都是耍流氓,咱們先分析功能需求:後端
一、發表消息spa
假設消息最長內容爲1K,能夠有圖片。 設計
二、接收消息3d
要求用戶不低於2秒能收到最新消息。 blog
這裏最基本的功能,而後咱們分析下一些非功能性需求: 接口
一、發表消息 圖片
A、要可以限制一些廣告或政治敏感內容,這塊看公司的基礎服務是否完善,若是有相應的功能,能夠接入相關服務,不過要注意此服務也要擴容;沒有的建議接入第三方相關服務;資源
B、要防刷屏,即防止某個用戶單位時間發送太多的評論,因此要作下頻率限制;
C、圖片的保存,咱們能夠算一下帶寬,若是一張圖片大小是5K,同時在線20W人,則一條消息須要約1G的帶寬,建議將圖片放入CDN;
另外還要注意回源的問題,即一張圖片第一次訪問的時候會有大量的回源,最好是作預取的處理,即在發表評論的時候就主動推送到CDN上。
二、接收消息
20W人在線,假如1秒鐘會發送1000條消息,每條消息平均長度是500字節,則須要100G的帶寬,這估計也不是我等私有云機房所能承受的。
因此這塊建議採用購買第三方服務來實現,若是實在是要本身實現,至少這塊得放入公有云上,而且作好帶寬的預估及限流手段,防止機房帶寬被打爆。
三、存儲的設計
首先要考慮的是要不要存本地,若是不用備份,能夠直接發送給第三方就不用本地保存。
若是須要本地保存, 20W在線用戶,若是有5%的人同時發消息,則有1W的TPS,因此寫Mysql是不大現實的。能夠考慮寫入到Redis中,Redis List類型結構適合此類場景。
消息重複接收問題
消息推送系統很難保證消息不會重複,因此前端接收新消息時須要和已經接到的消息ID進行對比,如存在則過濾掉;推送給第三方時每條消息都要加上消息ID,消息ID可用UUID生成,簡單實用。
*亂序和延遲問題*
對於亂序的狀況,保證消息展現時按時間倒序排列的。
若是新收到一條消息,多是5分鐘前發送的,前端展現時須要判斷是否小於當前屏幕的最先消息的發送時間,若是是就能夠忽略這條消息了。
系統的可用性設計
1、若是第三方消息推送服務掛了,怎麼辦?
能夠有幾個方案:
一、多選一家消息推送服務商;
二、兜底方案,若是全部第三方服務都掛了,可讓前端使用輪詢方案,但輪詢的間隔須要後端接口給出,能夠在後臺配置,根據壓力大小作調整。
2、如何保證消息不丟
要注意Redis的持久化設置,AOF模式下有1秒刷盤的策略,極端狀況下,可能會丟失1秒的消息;固然了若是要作到徹底不丟失消息則能夠配置每次都刷盤,這須要結合業務狀況去平衡。
總結
還有不少細節這裏沒有展現,如監控,怎樣知道用戶收到消息的延遲不超過2秒;降級,哪些是非核心功能,但可能會消耗不少資源的,像發送圖片,若是回源壓力比較大的狀況也是能夠關閉的。