日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

群聊系統是社交應用的核心功能之一,每個社交產品幾乎都有著群聊系統的身影:包括但不限于 QQ、微信、抖音、小紅書等。上述介紹的技術細節可能只是群聊系統的冰山一角,像常見的搶紅包、群內音視頻通話這些核心功能也充斥著大量的技術難點。

1. 引言

前些天所在部門出去團建,于是公司行政和 HR 拉了一個微信群,發布一些跟團和集合信息。

當我正在查看途徑路線和團建行程時,忽然一條帶著喜意的消息撲面而來,消息上赫然帶著八個大字:恭喜發財,大吉大利。

聽說你會架構設計?來,弄一個群聊系統

搶紅包!!原來是公司領導在群里發了個紅包,于是引得群員哄搶,氣氛其樂融融。

畢竟,團不團建無所謂,不上班就很快樂;搶多搶少無所謂,有錢進就很開心。

打工人果然是最容易滿足的生物!

我看著群里嬉戲打鬧的聊天,心中陷入了沉思:微信這個集齊了陌生人聊天、文件分享和搶紅包功能的群聊設計確實有點意思,如果在面試或者工作中讓我們設計一個群聊系統,需要從哪些方面來考慮呢?

 

群聊系統設計

面試官:微信作為 10 億用戶級別的全民 App,有用過吧?

我:(內心 OS,說沒用過你也不會相信啊~)當然,親愛的面試官,我經常使用微信來接收工作消息和文件,并且經常在上面處理工作內容。

面試官:(內心 OS:這小伙子工作意識很強嘛,加分!)OK,微信的群聊功能是微信里面核心的一個能力,它可以將數百個好友或陌生人放進一個群空間,如果讓你設計一個用戶量為 10 億用戶的群聊系統,你會怎么設計呢?

 

2. 系統需求

2.1 系統特點與功能需求

我:首先群聊功能是社交應用的核心能力之一,它允許用戶創建自己的社交圈子,與家人、朋友或共同興趣愛好者進行友好地交流。

以下是群聊系統常見的幾個功能:

聽說你會架構設計?來,弄一個群聊系統圖片

  • 創建群聊:用戶可以創建新的聊天群組,邀請其他好友用戶加入或與陌生人面對面建群。
  • 群組管理:群主和管理員能夠管理群成員,設置規則和權限。
  • 消息發送和接收:允許群成員發送文本、圖片、音頻、視頻等多種類型的消息,并推送給所有群成員。
  • 實時通信:消息應該能夠快速傳遞,確保實時互動。
  • 搶紅包:用戶在群聊中發送任意個數和金額的紅包,群成員可以搶到隨機金額的紅包。

 

2.2 非功能需求

除了功能需要,當我們面對 10 億微信用戶每天都可能使用建群功能的情景時,還需要處理大規模的用戶并發。

這就引出了系統的非功能需求,包括:

  • 高并發:系統需要支持大量用戶同時創建和使用群組,以確保無延遲的用戶體驗。
  • 高性能:快速消息傳遞、即時響應,是數字社交的關鍵。
  • 海量存儲:系統必須可擴展,以容納用戶生成的海量消息文本、圖片及音視頻數據。

面試官:嗯,不錯,那你可以簡要概述一下這幾個常用的功能嗎?

 

3. 核心組件

我:好的,我們首先做系統的概要設計,這里涉及到群聊系統的核心組件和基本業務的概要說明。

3.1 核心組件

群聊系統中,會涉及到如下核心組件和協議。

聽說你會架構設計?來,弄一個群聊系統圖片

  • 客戶端:接收手機或 PC 端微信群聊的消息,并實時傳輸給后臺服務器;
  • Websocket傳輸協議:支持客戶端和后臺服務端的實時交互,開銷低,實時性高,常用于微信、QQ 等 IM 系統通信系統;
  • 長連接集群:與客戶端進行 Websocket 長連接的系統集群,并將消息通過中間件轉發到應用服務器;
  • 消息處理服務器集群:提供實時消息的處理能力,包括數據存儲、查詢、與數據庫交互等;
  • 消息推送服務器集群:這是信息的中轉站,負責將消息傳遞給正確的群組成員;
  • 數據庫服務器集群:用于存儲用戶文本數據、圖片的縮略圖、音視頻元數據等;
  • 分布式文件存儲集群:存儲用戶圖片、音視頻等文件數據。

 

3.2 業務概要說明

在業務概要說明里,我們關注用戶的交互方式和數據存儲......

面試官:稍等一下,群聊系統的好友建群功能比較簡單,拉好友列表存數據就可以了!你用過面對面建群吧,可以簡要說一下如何設計面對面建群功能嗎?

我:(內心 OS,還好之前在吃飯時用過面對面建群結賬,不然就G了),好的,群聊系統除了拉好友建群外,還支持面對面建群的能力。

 

4. 面對面建群

用戶發起面對面建群后,系統支持輸入一個 4 位數的隨機碼,周圍的用戶輸入同一個隨機碼便可加入同一個群聊,面對面建群功能通常涉及數據表設計和核心業務交互流程如下。

4.1 數據庫表設計

  1. User 表:存儲用戶信息,包括用戶 ID、昵稱、頭像等。
  2. Group 表:存儲群組信息,包括群 ID、群名稱、創建者 ID、群成員個數等。
  3. GroupMember 表:關聯用戶和群組,包括用戶 ID 和群 ID。
  4. RandomCode 表:存儲面對面建群的隨機碼和關聯的群 ID。

 

4.2 核心業務交互流程

聽說你會架構設計?來,弄一個群聊系統圖片

用戶 A 在手機端應用中發起面對面建群,并輸入一個隨機碼,校驗通過后,等待周圍(50 米之內)的用戶加入。此時,系統將用戶信息以 HashMap 的方式存入緩存中,并設置過期時間為 3min。

{隨機碼,用戶列表[用戶A(ID、名稱、頭像)]}

用戶 B 在另一個手機端發起面對面建群,輸入指定的隨機碼,如果該用戶周圍有這樣的隨機碼,則進入同一個群聊等待頁面,并可以看到其它群員的頭像和昵稱信息。

此時,系統除了根據隨機碼獲取所有用戶信息,也會實時更新緩存里的用戶信息。

聽說你會架構設計?來,弄一個群聊系統

 

成員A進群

當第一個用戶點擊進入該群時,就可以加入群聊,系統將生成的隨機碼保存在 RandomCode 表中,并關聯到新創建的群 ID,更新群成員的個數。

然后,系統將用戶信息和新生成的群聊信息存儲在 Group、GroupMember 表中,并實時更新群成員個數。

 

成員B加入

然后,B 用戶帶著隨機碼加入群聊時,手機客戶端向服務器后端發送請求,驗證隨機碼是否有效。后臺服務檢查隨機碼是否存在于緩存中,如果存在,則校驗通過。

然后,根據 Group 中的成員個數,來判斷當前群成員是否滿員(目前普通用戶創建的群聊人數最多為 500 人)。

如果驗證通過,后臺將用戶 B 添加到群成員表 GroupMember 中,并返回成功響應。

面試官:如果有多個用戶同時加入,MySQL 數據庫如何保證群成員不會超過最大值呢?

我:有兩種方式可以解決。一個是通過 MySQL 的事務,將獲取 Group 群成員數和插入 GroupMember 表操作放在同一個事務里,但是這樣可能帶來鎖表的問題,性能較差。

另一種方式是采用 redis 的原子性命令incr 來記錄群聊的個數,其中 key 為群聊ID,value 為當前群成員個數。

當新增群員時,首先將該群聊的人數通過 incr 命令加一,然后獲取群成員個數。如果群員個數大于最大值,則減一后返回群成員已滿的提示。

使用 Redis 的好處是可以快速響應,并且可以利用 Redis 的原子特性避免并發問題,在電商系統中也常常使用類似的策略來防止超賣問題。

 

位置算法

同時,在面對面建群的過程中相當重要的能力是標識用戶的區域,比如 50 米以內。這個可以用到 Redis 的 GeoHash 算法,來獲取一個范圍內的所有用戶信息。

由于篇幅有限,這里不展開贅述,想了解更多位置算法相關的細節,可以看我之前的文章:聽說你會架構設計?來,弄一個公交&地鐵乘車系統。

面試官:嗯不錯,那你再講一下群聊系統里的消息發送和接收吧!

 

5. 消息發送與接收

我:當某個成員在微信群里發言,系統需要處理消息的分發、通知其他成員、以及確保消息的顯示。

在群聊系統中保存和展示用戶的圖片、視頻或音頻數據時,通常需要將元數據和文件分開存儲。

其中元數據存儲在 MySQL 集群,文件數據存儲在分布式對象存儲集群中。

 

5.1 交互流程

消息發送和接收的時序圖如下所示:

聽說你會架構設計?來,弄一個群聊系統

  1. 用戶A在群中發送一條帶有圖片、視頻或音頻的消息。
  2. 移動客戶端應用將消息內容和媒體文件上傳到服務器后端。
  3. 服務器后端接收到消息和媒體文件后,將消息內容存儲到 Message 表中,同時將媒體文件存儲到分布式文件存儲集群中。在 Message 表里,不僅記錄了媒體文件的 MediAID,以便關聯消息和媒體;還記錄了縮略圖、視頻封面圖等等。
  4. 服務器后端會向所有群成員廣播這條消息。移動客戶端應用接收到消息后,會根據消息類型(文本、圖片、視頻、音頻)加載對應的展示方式。
  5. 當用戶點擊查看圖片、視頻或音頻縮略圖時,客戶端應用會根據 MediaID 到對象存儲集群中獲取對應的媒體文件路徑,并將其展示給用戶。

 

5.2 消息存儲和展示

除了上述建群功能中提到的用戶表和群組表以外,存儲元數據還需要以下表結構:

  1. Message表: 用于存儲消息,每個消息都有一個唯一的 MessageID,消息類型(文本、圖片、視頻、音頻),消息內容(文字、圖片縮略圖、視頻封面圖等),發送者 UserID、接收群 GroupID、發送時間等字段。
  2. Media表: 存儲用戶上傳的圖片、視頻、音頻等媒體數據。每個媒體文件都有一個唯一的 MediaID,文件路徑、上傳者 UserID、上傳時間等字段。
  3. MessageState表: 用于存儲用戶消息狀態,包括 MessageID、用戶 ID、是否已讀等。在消息推送時,通過這張表計算未讀數,統一推送給用戶,并在離線用戶的手機上展示一個小數字代表消息未讀數。

面試官:我們時常看到群聊有 n 個未讀消息,這個是怎么設計的呢?

我:MessageState 表記錄了用戶的未讀消息數,想要獲取用戶的消息未讀數時,只需要客戶端調用一下接口查詢即可獲取,這個接口將每個群的未讀個數加起來,統一返回給客戶端,然后借助手機的 SDK 推送功能加載到用戶手機上。

面試官:就這么簡單嗎,可以優化一下不?

我:(內心 OS,性能確實很差,就等著你問呢)是的,我們需要優化一下,首先 MySQL 查詢 select count 類型的語句時,都會觸發全表掃描,所以每次加載消息未讀數都很慢。

為了查詢性能考慮,我們可以將用戶的消息數量存入 Redis,并實時記錄一個未讀數值。并且,當未讀數大于 99 時,就將未讀數值置為 100 且不再增加。

當推送用戶消息時,只要未讀數為 100,就將推送消息數設置為 99+,以此來提升存儲的性能和交互的效率。

面試官:嗯,目前幾乎所有的消息推送功能都是這么設計的。那你再說一下 10 億用戶的群聊系統應該如何在高并發,海量數據下保證高性能和高可用吧!

我:我想到了幾個點,比如采用集群部署、消息隊列、多線程、緩存等。

 

集群部署:可擴展

在群聊系統中,我們用到了分布式可擴展的思想,無論是長連接服務、消息推送服務,還是數據庫以及分布式文件存儲服務,都是集群部署。

一方面防止單體故障,另一方面可以根據業務來進行彈性伸縮,提升了系統的高可用性。

 

消息隊列:異步、削峰

在消息推送時,由于消息量和用戶量很多,所以我們將消息放到消息隊列(比如 Kafka)中異步進行消費和推送,來進行流量削峰,防止數據太多將服務打崩。

 

多線程

在消息寫入和消費時,可以多線程操作,一方面節省了硬件開銷,不至于部署太多機器。另一方面提升了效率,畢竟多個流水線工作肯定比單打獨斗更快。

 

其它優化

緩存前面已經說到了,除了建群時記錄 code,加群時記錄群成員數,我們還可以緩存群聊里最近一段時間的消息,防止每個用戶都去 DB 拉取一遍數據,這提升了消息查閱的效率。

除此之外,為了節省成本,可以記錄流量的高峰時間段,根據時間段來定時擴縮節點(當然,這只是為了成本考慮,在實際業務中這點開銷不算什么大問題)。

 

6. 小結

后續

面試官:嗯不錯,實際上的架構中也沒有節省這些資源,而是把重心放在了用戶體驗上。(看了看表)OK,那今天的面試就到這,你有什么想問的嗎?

我:(內心 OS,有點慌,但是不能表現出來)由于時間有限,之前對系統高并發、高性能的設計,以及對海量數據的處理淺嘗輒止,這在系統設計的面試中占比如何?

面試官:整體想得比較全,但是還不夠細節。當然,也可能是時間不充分的原因,已經還不錯了!

我:(內心 OS,借你吉言)再想問一下,如果我把這些寫出來,會有讀者給我點贊、分享、加入在看嗎?

面試官:……

 

結語

群聊系統是社交應用的核心功能之一,每個社交產品幾乎都有著群聊系統的身影:包括但不限于 QQ、微信、抖音、小紅書等。

上述介紹的技術細節可能只是群聊系統的冰山一角,像常見的搶紅包、群內音視頻通話這些核心功能也充斥著大量的技術難點。

但正是有了這些功能,才讓我們使用的 App 變得更加有趣。而這,可能也是技術和架構的魅力所在吧~

分享到:
標簽:架構 設計
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定