美拍:大中型 SNS 系統設計漫談 | UPYUN Open Talk NO.4

圖片描述

洪小軍 美拍架構平臺負責人前端

業務系統架構演化

1、計數器服務mysql

談到業務系統的架構,首先要說計數器服務,雖然看起來是個小功能,若是將計數器整個歷程和深層次的東西掌握清楚,會發現不少東西是相通的。經過簡單的業務,挖掘背後的技術,是一個很好的學習過程。redis

SNS最重要的就是社交關係,以及用戶信息。在美拍你能夠看到美拍評論,有評論數、點贊數,微博有評論數、轉發數、點贊數,這些都須要經過計數器來完成。sql

圖片描述

一、實現計數器最粗暴的方式:數據庫直接count

一些產品在開始上線的時候,會用很是粗暴的方式——在數據庫中把數據count出來。數據庫

計數器服務在SNS系統中屬於TOP級別的訪問大戶,甚至是TOP1,這個簡單粗暴的方式天然會面臨一些問題:由於沒有獨立的計數器,每次都須要從數據庫count,會出現大量慢查詢、慢請求問題。後端

二、大部分公司經常使用的方案:獨立的計數器表

上面粗暴的計數器方式,沒有獨立的計數器,每次都要從數據庫count。而今大部分公司或系統會獨立維護計數器,創建計數器表,包括ID表和純計數表,每次變動都須要update,與此同時前面還有一個memacached,用來扛大量熱的請求。這個方案在前期沒有什麼問題,但發。展到一段階段,會出現不少接口響應時間過長的問題。緩存

回到SNS系統的特色,數據庫中會有大量的update/select操做。好比美拍,某一個明星發了一條信息,瞬間會有不少評論、點贊,計數表會頻繁的update。另一種狀況是,大量的信息是沒有被評論和轉發。SNS系統只要存放這些評論和轉發數等於0的數據,就會有大量的select,這就須要緩存的容量足夠大,將全部的數據裝進去。性能優化

SNS系統還有一個特色,就是長尾特性很明顯,數據分佈上有一條很長的尾巴。好比最近三個月佔90%,好比第四、五、6個月,佔比是很均衡的,這就是長尾的特色,這對緩存提出很大的挑戰。假設你可能要保證緩存命中率90%,可能要花5G內存,若是到95%,就須要10G,若是要到99%,可能就要100G或200G,這就對容量提出很高的要求。架構

可進行的優化:併發

數據庫合併寫入,即程序段合併寫入請求,有起到必定效果,可是不會太明顯。
緩存金擴容儘量存放更多數據,但因爲SNS系統的長尾效應仍是很難達到很是高的命中率。

三、必定規模公司採用的方案:Redis內存存儲

3.1 架設在內存基礎上的架構

圖片描述

內存緩存,從請求的訪問策略來看,從緩存讀取,cache不到,再從mysql讀取;命中率取決於它的容量。若是是內存存儲,命中率是100%。對於容量要求,不少地方會說存儲須要的容量比緩存大不少,但在具體的產品中並不徹底是這樣。好比,在計數器服務中,採用存儲的方式,50%的美拍是沒有評論的,存儲只須要存50%有被評論過的就足夠了。可是採用內存緩存的方式,是沒有這個策略的,可能須要存不少沒有被評論過的信息。

Redis 內存存儲:

圖片描述

Redis是全內存存儲,在SNS系統計數器中只需存存放全部計數器>0的數據 ,具備高速的讀取性能,保證接口的響應時間可控,這也是大多數公司採用的方案,也比較可控。

3.2 長尾數據
隨着時間增加,會出現大量的長尾數據,尤爲是SNS系統,就像微博發展四、5年前的數據特別多,所有寫入內存成本過高。長尾訪問,不須要用內存這麼高的成本去支撐。

長尾問題解決方案:
1)作冷熱數據分離,將最近個月的數據放在內存,更早的宕到SSD上,成本比較低,這是一個折中方案;
2)經過修改redis,實現更緊湊的存儲。

2、FEED服務

FEED業務指的是,好友的消息列表,美拍上的好友動態,微博就是首頁的列表。FEED經常使用推、拉兩種模式。

推模式:

推模式寫入消息的成本會比較高,至關於發一條美拍須要推給全部關注我美拍的人。推的數量取決於有多少人關注我。相反獲取信息的成本很是低,只需簡單的SELECT就能夠取出來,推模式是基於空間去換時間的策略。

在這種狀況下,須要考慮3個問題:
1)容量是否會成爲瓶頸;
2)推送量大的狀況下,會出現延遲問題;
3)加關注/減關注這類變動通知的成本很是高。

拉模式:

拉模式是和推模式相反的方式,輕量寫入。獲取消息,先將關注的列表取出來,再將關注的每一個人反的美拍列表取出來,最終合併。這是用時間換空間,拉取須要不少計算,會影響到接口的響應時間,須要大量的計算,須要獲取大量的資源,這樣會形成需求的帶寬增多。

所以,在好友多、粉絲少的狀況下,推的模式最好。好友少和粉絲多的狀況,比較適合拉的方式。

如今的SNS系統大多都是好友多,粉絲又多。在這種狀況下,一些業界公司採用了推拉結合的方法,好比Twitter。普通用戶(粉絲數少的用戶)採用推的方式,大V採用拉的方式。

在發佈信息的時候會經過粉絲數及其餘策略包括是否在線等情況作推拉的判斷。微博,公開性的微博都是基於拉的方式,私密性的功能,都是基於推的方式。

FEED服務中的重點:

FEED服務中數據庫和緩存是兩個很重要的點。
在業務快速發展的階段,須要頻繁的增長新的產品屬性,每一個屬性都須要在線變動,這樣會對在線用戶產生影響,同時也很增長成本。
經常使用的解決方法:索引和內容分離,各司其職。索引保證高效的查找,全部的查找都在索引裏完成。索引可能會有不一樣級別、維度的索引。內容使用KV結構(V爲二進制數據),便於數據變動。在這裏內容須要儘量緊湊的存儲。

數據庫定位:

數據庫只是做爲存儲,不該該有任何邏輯,由於系統追求的是高性能的讀取訪問。最多有V條件,不該有任何業務邏輯,業務邏輯應該放到程序端處理。

數據庫面臨很大的寫壓力,經常使用的是分庫分表的方式,但會出現兩個問題,大部分數據庫都有自身的IP,跟其餘的表關聯,分庫分表就不能用智能IP,可能會形成IP衝突。

分庫分表策略:

最多見的就是,每一個庫裏都有N張表,基於HASF分表。但到必定階段會出現一些問題:

1)特殊用戶查詢性能很高,這種用戶可能有幾百萬甚至上千萬的記錄,一旦穿透到數據庫,性能會很糟糕。
2)到必定規模後,會考慮進行硬件的升級,若是將全部的歷史數據存放SSD,很浪費。

爲解決這個問題,不少公司採用了基於時間分片的方案。最好的方法是創建一個索引表,在索引表裏存放每月用戶有多少條數據。

3、緩存:雪崩

說道緩存,先補充一個雪崩的概念。

假設系統有4,5個節點,每一個緩存節點命中率是90%,也就是每一個節點要承擔接近20%的訪問量,若是這個時候有1個節點壞了,這個請求會所有打到memacache,整個系統極可能就直接宕掉。這就是所謂的雪崩。

解決方案:

一、在這個階段,程序端作兩節緩存,使得請求在某個節點壞掉了的時候,不會直接到memache,而後請求另一個節點。
二、隨着業務增加,須要擴充。解決方法:
1)擴充節點到20個,但可能出現multiget hole問題,在這種狀況下,致使性能降低。
2)搭建多集羣。

系統設計的基本原則

CAP原則:一致性、可用性、可擴展性
在SNS場景中,每每上面的三個點,只能選擇其中兩個,須要必定的折中。最主要的是擴展性和可用性。固然不是說一致性不重要,能夠採用最終一致的方法作補充。

前期:快速搭建系統上線。

中期:重點解決可擴展性問題。
經過硬件升級、單機性能優化,提升單機性能,以及採用SACLE分佈式支持,能夠解決擴展性問題。
SNS系統高可擴展性須要關注如下幾個點:

一、支持高併發讀取,首先第一點就是支持大量級的接口調用。其次還須要保證很低的響應時間。

二、支持峯值的寫入。最重要的一點是先後端分離,前端處於永遠可寫的狀態。(用戶成功發佈內容後,顯示成功,實際並無徹底成功,後面的事情交給後端去作)
三、作好分佈式部署,包括一個機房內部多集羣,最好是有條件作到多機房。多機房部署,要保證每一個機房之間有可靠的消息同步,要避免跨機房讀調用。
(多機房如何將主要資源同步:SYSQL可採用master方式,Redis有條件的可採用master/salve方式)

中後期:不少系統須要解決可用性問題。 可用性問題比前面的問題都更加有挑戰。 一、避免單點故障。 二、保證響應時間。

相關文章
相關標籤/搜索