聽說你會架構設計?來,弄一個交友系統(tǒng)
1. 引言
大家好,我是小?,一個流浪江湖多年的 985 非科班程序員,曾混跡于國企、互聯(lián)網(wǎng)大廠和創(chuàng)業(yè)公司的后臺開發(fā)攻城獅。
1.1 尋找電影般的浪漫
“嘀嗒嘀嗒”,“嘀嗒嘀嗒”,當夜幕降臨,你還在代碼的海洋中與 BUG 進行著“持久戰(zhàn)”。
突然,你意識到,生活中不應只有鍵盤和屏幕,于是像個待充電的超人一樣,決定給自己來點人際交流的活力補給。右手揮舞鼠標,左手掏出手機,邊關閉 IDE 邊滑動 App。
這個時候,尋找知己的老難題又閃現(xiàn)在腦海:要不要先檢查一遍今日代碼、再做一次單元測試,還是直接跳入“尋緣池”?(真實情況可能是,今天跳入哪個尋緣池 ?? )
圖片
好不容易做出了一個勇敢的決定——關閉電腦,從椅子一躍而起。你拿出手機,點開了熟悉的交友 App。
然后,個人資料頁面在屏幕上亮了起來,這可是你走出虛擬世界的敲門磚。
你快速瀏覽著,現(xiàn)實世界中其他的編程愛好者、攝影迷、文藝青年...,都在這個小小的舞臺中綻放著個性的光芒。
不需排隊買飲料,不再擔心交友聚會上的尷尬沉默。你滑過一個又一個感興趣的頭像,終于,停留在某個共鳴的話題上,準備展開一次思想的交鋒。
1.2 技術支撐下的交友系統(tǒng)
就像前文所述,人們想要跳出孤獨的循環(huán),唯一需要的是一臺手機,一個友好的交互界面。
那這個誘人的交友系統(tǒng)是如何誕生的呢?它背后的算法和架構又是如何支撐起你我情感交流的橋梁呢?
今天,讓我們一同撩開這個現(xiàn)代愛情駭客的神秘面紗,深度解碼交友系統(tǒng)的設計與實現(xiàn)。
在這篇文章中,小?將分享常見交友軟件的系統(tǒng)設計,探索它是如何在短短幾年內從 idea 到蓬勃發(fā)展再到?jīng)]落的(不是,瞎說什么大實話!
2. 需求分析
2.1 Small Chat
在一個宇宙般無垠的數(shù)字海洋中,浮現(xiàn)了名為 Small Chat 的愛情小島。
圖片
這座島不是用巖石建成,而是由一群單身狗(咳咳,我是指單身男女)手機里的一個個 App 打造而成。說起這個 App,它簡直是孤獨心靈的救星,一個紙杯電話 2.0 版,或者說是一扇帶你邂逅愛情奇遇的神奇窗戶。
2.2 功能需求
圖片
打開這款叫做 Small Chat 的 App,就如啟動太空艇的第一步,用戶得先登錄自己的小小太空艇——上傳星球生活照,裝飾個人艙室(自我介紹)。
此時,這位宇航員您可以種下自己的位置信標,并根據(jù)個人偏好裝配指南 needle(推薦算法)。
算法這個家伙和那位算命先生有點像,據(jù)說它會依據(jù)用戶的星際坐標和你那閃閃發(fā)亮的個人信息(據(jù)說,每個程序員都認為自己是全村最靚的仔),匹配茫茫宇宙中的其他太空艇,它們都和你泊在相鄰的星域。
現(xiàn)在,你就可以在手機熒光屏上批量欣賞這些來自銀河系各個角落的宇航員的艙室(就是 Ta 們的照片和資料)。
要是心中一動,想要走得更近一些,用戶還可以大膽地向右滑動這張星際許可證——就像在說:“嘿,boy/girl,你在宇宙中并不孤單”!
當然,如果兩個孤獨的太空艇都向右轉了舵,哦,這不就意味著星際之船即將交匯了嗎?這個時候,系統(tǒng)就會像個熱心的宇航局一樣,發(fā)來一條信息:“恭喜,你們已經(jīng)成功配對!”
這時,愛情的宇宙軌道就開啟了哦!
于是,兩位宇航員就可以開始在私人頻道上暢所欲言,探索彼此的宇宙,看看是否能點燃繁星。
2.3 非功能需求
現(xiàn)在,讓我們來分析一下 Small Chat 星球的潛在居民數(shù)量。
我們估算在這片浩渺的銀河系中,有超過 1 億顆孤單的心正在尋找彼此的引力波。因此,我們從 1 億個星際交流頻道出發(fā),為 Small Chat 的后臺系統(tǒng)做設計。
想象一下,那是一個可以讓 1 億顆心交織在一起的宇宙網(wǎng)絡??!
這不僅是技術的挑戰(zhàn),也是對愛情信號強度的考驗。而這,就是我們今天要介紹的 Small Chat ——不只是一個交友 App,而是銀河系統(tǒng)中一個關于愛情的奇妙設計。
3. 概要設計
在數(shù)字化的銀河系中, Small Chat 是一個獨特的星球,擁有著精妙絕倫的生態(tài)系統(tǒng)。
3.1 整體架構
不妨把它想象為一座由微服務構成的未來城市,這里的每一個角落都通過智能網(wǎng)關保護著,就像是銀河巡警,確保通道暢通無阻。
這座未來城市的每個街區(qū)都是一個專門的小微服務工廠:用戶工廠、鄰近算法工廠、配對工廠、聊天工廠、還有那個精確匹配你可能邂逅愛情坐標的推薦工廠。
圖片
在 Small Chat 的系統(tǒng)架構中,我們采取了被廣泛認可的微服務架構設計。
首先,用戶通過一個集中的網(wǎng)關服務來接入不同的微服務,你可以將其視為一個高效的調度中心,既能保安全,又能提高效率。
然后,用戶的所有請求首先被發(fā)送到這個網(wǎng)絡門衛(wèi)——也就是網(wǎng)關服務器。這個網(wǎng)關服務器的任務范圍相當廣泛,它既要做好流量的管制工作,保護系統(tǒng)免受過多請求的壓垮,也要時刻警惕潛在的網(wǎng)絡攻擊,同時對用戶的身份和權限進行校驗。
此外,網(wǎng)關服務器還起到了一個'中介'的角色,把用戶的請求引導到相應的微服務,并將返回的數(shù)據(jù)整合后再展現(xiàn)給用戶。
根據(jù)預估的用戶級,這個網(wǎng)關服務器需要能夠應對每天高達千萬甚至億萬次的訪問量。
3.2 業(yè)務系統(tǒng)
然后是微服務的各個具體組件,用戶系統(tǒng)是負責管理和存儲用戶個人信息的模塊,包括用戶的登錄認證,所有的用戶都必須通過這個服務來驗證身份才能使用系統(tǒng)的其他功能。
為了處理龐大的數(shù)據(jù)量,這里用到了分片技術的 MySQL 數(shù)據(jù)庫系統(tǒng),并將它們放在一個集群里面,方便彈性伸縮。
分布式對象存儲集群主要存儲了用戶上傳的圖片、音視頻信息,以及聊天時用到的表情包圖片或者其它文件信息,文件的元數(shù)據(jù)放置在 DB 存儲。
圖片
此外,為了更高效地提供圖片,我們通過 CDN 服務緩存了用戶訪問頻率較高的熱門圖片,以加速圖片加載速度。
至于配對系統(tǒng),它則是負責用戶互相"右劃"表示喜歡后進行配對的模塊,如果兩個人互相"右劃"了對方,這個服務就會將這對用戶加入到對方的通訊錄中。
最后,推薦系統(tǒng)的責任是將可能相互感興趣的用戶推薦給對方,這需要結合用戶的行為、興趣愛好和前述的"配對"情況來進行智能推薦。
同時,考慮到地理位置的親近性因素,這個服務時常會與算法團隊密切合作,確保推薦的對象在地理上也方便用戶進行真實的社交互動。
通過這些微服務的配合, Small Chat 的平臺可以以模塊化的方式靈活地擴展功能,同時保證了用戶數(shù)據(jù)處理的效率和安全。
4. 詳細設計
4.1 高并發(fā)挑戰(zhàn)
對于交友系統(tǒng)來說,高并發(fā)處理是確保用戶體驗和系統(tǒng)穩(wěn)定性的首要技術挑戰(zhàn)。對于一個可能有著幾千萬用戶同時在線的系統(tǒng)來說,維護系統(tǒng)穩(wěn)定性需要注意以下幾點。
1. 水平擴展與負載均衡
圖片
- 首先,采用無狀態(tài)的設計模式,讓系統(tǒng)后端服務能夠在多個處理單元之間進行水平擴展。這意味著任何一個單元都可以獨立處理請求,而不依賴于特定的上下文信息。
- 部署負載均衡器,將流量分發(fā)到多個后端服務器。負載均衡器可以是硬件負載均衡器,也可以是如 Nginx 這樣的軟件解決方案,其利用算法(如 輪詢、最小連接數(shù)、一致性哈希 等)智能地將用戶請求分配到處理能力最佳的服務器節(jié)點。
- 實現(xiàn)自動擴縮容機制,監(jiān)控系統(tǒng)的負載情況,當流量急劇上升,超過預置閾值時,自動擴展服務器實例;當流量下降時,適當減少實例以節(jié)約成本。
2. 數(shù)據(jù)庫優(yōu)化和緩存策略
圖片
- 數(shù)據(jù)庫分區(qū)和分片,將數(shù)據(jù)分布到多個數(shù)據(jù)庫中,每個數(shù)據(jù)庫只負責處理一部分數(shù)據(jù),數(shù)據(jù)庫之間可通過分布式事務進行數(shù)據(jù)一致性控制。
不了解 DB 分庫分表的同學可以看我之前的這篇文章:MySQL高可用,分庫分表你學廢了嗎
- 使用讀寫分離模型,通過主從復制的方式攤開讀操作的壓力。寫操作只在主數(shù)據(jù)庫上進行,而讀操作則可以在多個從數(shù)據(jù)庫上進行,這樣可以大幅提高數(shù)據(jù)庫的讀取性能。
- 引入緩存系統(tǒng),如 Redis 或 Memcached,將頻繁讀取的數(shù)據(jù),如用戶的基礎信息、用戶的交互動態(tài)緩存起來。對于交友系統(tǒng)來說,用戶的動態(tài)信息、瞬時狀態(tài)等可以緩存,減少數(shù)據(jù)庫的請求次數(shù)。
3. 消息隊列和異步處理
- 引入消息隊列,比如 Kafka 或 RabbitMQ,用來解耦應用服務和后端處理。這允許系統(tǒng)在面對突發(fā)流量時把請求排隊,而不是直接在數(shù)據(jù)庫或服務層上造成壓力,從而提高整體系統(tǒng)的彈性和響應能力。比如,用戶聊天時可以把消息通知放到隊列中排隊處理。
- 異步執(zhí)行耗時操作,比如用戶的 匹配運算、數(shù)據(jù)分析 等可以放在后臺服務中異步執(zhí)行,用戶不需要同步等待這些操作完成。特別是用戶匹配機制,可以放到并發(fā)量小的時段統(tǒng)一進行。
需要要注意的是,以上策略需要遵循微服務架構的原則,將系統(tǒng)拆分為多個松耦合、易于擴展的小型服務,每個服務可以單獨部署,獨立擴展。
通過這些架構層面的優(yōu)化,即便 Small Chat 面臨幾千萬到上億級別的用戶并發(fā)請求,也能保持服務的高可用性和穩(wěn)定性。
4.2 空間鄰近算法
如何根據(jù)用戶的地理位置尋找距其一定范圍內的其他用戶,也是交友系統(tǒng)中必不可少的一個考慮點。
空間鄰近算法是為了解決 給定一個點,找出距離其最近的點 這一問題的算法。在不同的應用背景下,會有不同的考量因素,如精度、效率、存儲需求和實施的難易程度等,以下是一些常見的空間鄰近算法。
1. 常見的空間鄰近算法:
1)網(wǎng)格(Grid)算法
這種算法是將地理空間簡單劃分成網(wǎng)格,可以認為網(wǎng)格內的點是鄰近的。
為提高鄰近好友查詢效率,我們的系統(tǒng)可以按照一定規(guī)則把每位用戶歸類到一個特定的網(wǎng)格,并在他們的用戶信息里標記對應的網(wǎng)格ID(gridID),將位置信息存入 MySQL 中。
這樣,當需要查找用戶附近的人時,我們可以將 3*3 的網(wǎng)格視為相近用戶,這樣僅需搜索目標用戶所在的那個網(wǎng)格以及其相鄰的八個網(wǎng)格內的用戶即可。
但是,即便如此,每當面對 DB 的高頻訪問時,這類查詢仍然可能會帶來負擔:一方面是太慢,另一方面是不精確,邊界處理也比較復雜。
為了進一步優(yōu)化,我們決定把所有網(wǎng)格及其中的用戶信息都存儲在內存中,這樣就可以避免頻繁的 DB 操作。對于鄰近用戶的查詢,通過內存中的數(shù)據(jù)進行計算即可。
首先,我們可以把所有用戶的經(jīng)緯度信息加載到內存中,實現(xiàn)這一解決方案的關鍵在于選擇合適的網(wǎng)格尺寸,并能快速確定用戶所在的網(wǎng)格及其周邊網(wǎng)格信息。
實踐中,通常會用到 四叉樹網(wǎng)格 和 GeoHash 算法 來優(yōu)化這一過程。
2)四叉樹(Quadtree)網(wǎng)格算法
四叉樹網(wǎng)格算法類似網(wǎng)格方法,但是網(wǎng)格的大小是動態(tài)分配的。
圖片
它底層使用了四叉樹結構自適應地調整網(wǎng)格大小,以處理用戶密度不同的區(qū)域,這種算法對不均勻分布的數(shù)據(jù)集表現(xiàn)更好。
具體來說,在人口密集區(qū),它通過細分網(wǎng)格來減少每個網(wǎng)格的用戶量(比如深圳南山、北京海淀);而在人疏少地,網(wǎng)格則相應擴大(比如一些用戶數(shù)較少的平原地區(qū))。
這種方法保證了每個網(wǎng)格的用戶數(shù)不超過設定閾值(例如 500 人),當查詢附近用戶時,算法從四叉樹的根節(jié)點開始逐級向下,直至抵達包含目標用戶的葉子節(jié)點。為了進一步查找鄰近網(wǎng)格用戶,可通過將所有葉子節(jié)點連成一個雙向鏈表來實現(xiàn)(類型 B+ 樹的網(wǎng)狀結構)。
盡管該算法適應了很多場景,但編程實施較復雜且若網(wǎng)格大小設置不當,會影響搜索性能,接下來我們再看 Geohash 算法。
3)Geohash 算法
Geohash 算法是一種將二維空間坐標編碼為一維字符串的方法,它可以有效地表示地理位置信息。
圖片
在交友系統(tǒng)中,Geohash 可以用來索引用戶的位置,以便快速查詢附近的用戶。結合 Redis 這樣的內存數(shù)據(jù)存儲,使用 GeoHash 應對大規(guī)模地理位置處理成為可能。
1. 用戶位置編碼
當用戶提供自己的位置信息,通常是經(jīng)度和緯度,系統(tǒng)會使用 GeoHash 算法將這些坐標轉換為一個字符串。GeoHash 將地圖劃分為網(wǎng)格,每次劃分會將網(wǎng)格細分為更小的區(qū)域,經(jīng)緯度坐標每一次細分都相應地在 GeoHash 字符串上增加一個字符。
2. 存儲用戶位置
得到 GeoHash 字符串后,可以使用 Redis 自帶的地理空間索引 GeoSpatial index(Redis3.2 之后支持),直接使用 GEOADD 命令添加用戶的地理位置信息。
3. 查詢附近的用戶
當需要查找一個用戶的附近用戶時,系統(tǒng)可以做如下操作:
- 首先,獲取查詢用戶的 GeoHash 字符串;
- 使用 Redis 的 GEOSEARCH 或類似的命令,通過指定中心點(即查詢用戶的位置)和搜索半徑,查詢附近的用戶;
- Redis 會返回在該區(qū)域內的所有用戶 ID 和它們的位置信息。
4. 結果排序和范圍限制
Redis 的 GEOSEARCH 命令返回的結果已經(jīng)根據(jù)距離中心點的遠近排序,查找到的用戶可以進一步按實際距離排序。
如果系統(tǒng)需要對結果進行限制,如只顯示前10個最近的用戶,可以在查詢時指定或者在查詢后處理。
2. 如何選擇
在交友系統(tǒng)中,由于地理位置是不斷變化的,咱們需要一個可以處理動態(tài)數(shù)據(jù)集的算法。并且,為了在大規(guī)模用戶中工作,需要考慮算法的效率和擴展性。
GeoHash 由于其簡單性和易于與其他存儲解決方案結合使用(如 Redis),在許多現(xiàn)代的定位系統(tǒng)(如 T3 出行、滴滴打車)中非常受歡迎。
所以在 Small Chat 中,我們也使用 GeoHash 算法來處理位置信息以及附近用戶的匹配機制。
4.3 推薦算法
推薦算法在交友平臺中至關重要,它直接影響用戶的體驗和平臺的留存率。
在 Small Chat 中,我們綜合考慮用戶的互動、地理位置等因素來給用戶打分,并最終生成一個排名(rank)值,用以推薦其他匹配的用戶。
1. 用戶特征與行為因素
用戶的每一項行為都可能成為加分項,比如:
- 活躍度加分:用戶登錄頻率、交互次數(shù)等,表示用戶對平臺的參與度。
- 完善度加分:用戶資料的完整性,包括真實身份認證、興趣愛好、自我介紹等。
- 正面互動加分:其他用戶對該用戶的正面評價,如點贊、喜歡、私信等響應。
- 新鮮度加分:新注冊用戶或長時間未登錄后重新快樂用戶可能會有一定加分,這點,在很多 moba 手游的匹配機制里得以充分體現(xiàn),比如 王者榮耀、和平精英 等。
2. 地理位置因素
- 地理鄰近加分:距離用戶較近的其他用戶會獲得額外加分。這可以通過 GeoHash 位置算法計算得出。
3. 算法打分機制
設置一個打分系統(tǒng),每個因素根據(jù)其重要性分配權重,比如:
- 活躍度權重:25%
- 資料完善度權重:20%
- 正面互動權重:30%
- 距離權重:25%
用戶得分計算公式可表示為:
UserScore = {活躍度分} * 25% + {最大資料完善度分} * 20% + {最大正面互動分} * 30% + {最大距離分} * 25%
4. 推薦列表的生成
得到每個用戶的得分后,為目標用戶生成推薦列表的過程如下:
- 用戶相似性計算:首先,通過用戶的行為和資料完善度找到傾向上相似的用戶。
- 位置篩選:其次,利用位置信息篩選出距離合適的候選人。
- 綜合得分排序:根據(jù)上述的得分機制對所有篩選后的用戶計算得分,得到每個用戶的排名值。
- 推薦列表生成:最后,根據(jù)得分從高到低排列用戶,生成推薦列表。
為了優(yōu)化響應,我們可以將一定范圍的 Rank 列表保存到 Redis 的 Sorted Set 里。其中 key 為用戶 Id, score 字段為推薦度分數(shù),field 列為被推薦的用戶 Id。
5. Rank值的更新
Rank 值不是靜態(tài)的,它應隨著用戶行為的變化動態(tài)更新。比如,用戶的活躍度可以是逐日遞減的,而一次新的正面互動則能帶來即時的得分提升。
在實踐中,可以通過設定定時任務,如每日或每周更新一次用戶得分。對于即時性較強的操作(如互動行為),可以觸發(fā)即時的得分更新流程。
5. 小結
以上,我們對現(xiàn)代交友系統(tǒng)的一些常見技術難點做了一個大致的剖析,從用戶對浪漫邂逅的渴望出發(fā),到細致的技術構建。
Small Chat 系統(tǒng)不僅讓屏幕前的很多單身貴族與各種可能的緣分相遇,更在龐大訪問壓力下,展示了其穩(wěn)定的架構。通過微服務、負載均衡、數(shù)據(jù)庫優(yōu)化、緩存、異步處理和空間鄰近算法的使用,讓一個可擴展、高效且個性化的交友應用得以呈現(xiàn)。