天天看點

三體PCC大賽題目 - facebook\微網誌 like場景 資料庫設計與性能壓測

postgresql , pipelinedb , facebook , 微網誌 , 流式統計

高可用架構的一個pcc大賽,看了一下比賽規則,發現postgresql很适合做這個場景,原樣複刻,使用pg實作以及性能表現到底如何?

比賽内容介紹如下

<a href="https://github.com/archnotes/pcc">https://github.com/archnotes/pcc</a>

可以對一個對象(一條feed、文章、或者url)進行 like 操作,禁止 like 兩次,第二次 like 傳回錯誤碼

有 islike 接口,傳回參數指定的對象有沒有被目前使用者 like 過

需要看到一個對象的 like 計數

可以看到一個對象的 like 使用者清單(類似 qq 空間);

上述清單加分項:like優先顯示我的好友清單(social list)。

資料量:每天新增的 like 對象數為 1 千萬,每秒 like 計數器查詢量為 30 萬次 / 秒。

使用者數量級1億,好友數量級1~1萬,單個對象的like數量1-100萬

提供比賽資料集(純文字格式),需要參賽人員自行導入到自己資料庫

uid為uint64,1億條

uid, friend_id為uint64,隻存在雙向好友關系,1億個使用者*1000,好友關系通常是一個長尾分布,90% 100個以下,8%長尾分布300-1000,2% 1000-10000

oid,uid為uint64,2億個objects, 每個1-100w

人與人的關系為關注,或者互相關注的關系。

人與對象為喜歡或者不喜歡的關系。

三體PCC大賽題目 - facebook\微網誌 like場景 資料庫設計與性能壓測

在設計時,分明細資料和統計資料,統計資料為了更快速的查詢關系,被關注數。

明細可以記錄在日志,也可以記錄在資料庫中。統計資料(關系,計數,被like等),以流處理的方式寫入資料庫。

三體PCC大賽題目 - facebook\微網誌 like場景 資料庫設計與性能壓測

1. 人關注了哪些人,

2. 人被哪些人關注,本場景未涉及(如果需要的話,建立反向關系表)。

3. 人like了哪些對象,本場景未涉及(如果需要的話,建立反向關系表)。

4. 對象被哪些人like,

5. 對象被like了多少次

6. like某對象的使用者中,哪些是我的好友?

建立流,關注的行為将寫入流,同時寫入明細(可選)。

建立持續視圖,根據關注行為實時統計。

激活流計算

關注(like)操作函數,判斷是否已關注,如果已關注,傳回異常,否則關注。(這個也可以寫在程式中,但是需要與資料庫互動多次,差評)

函數可以根據實際需求進行調整,比如需要傳回被like後的數組,查詢一下continue view即可。

測試

1. 使用者id範圍

1-1億

2. 文章id範圍

1-2億

3. 熱點文章id範圍

總共2億文章,使用高斯分布進行like,分布在以鐘鼎為中心的2.0/xx這個區間内的文章id,覆寫了95%的出現機率。分布在1.0/xx這個區間的文章id覆寫了67%的出現機率。

橫坐标越靠近鈡的頂端的值(即文章id=1億),産生的機率越高。

xx越小,鈡越尖,也就是說熱點文章越少。

原理參考

<a href="https://github.com/digoal/blog/blob/master/201705/.../201506/20150618_01.md">《生成泊松、高斯、指數、随機分布資料 - postgresql pg_bench 》</a>

三體PCC大賽題目 - facebook\微網誌 like場景 資料庫設計與性能壓測

4. 随機使用者喜歡随機文章

5. 随機使用者喜歡熱點文章

壓測腳本,like文章,使用高斯分布産生文章id,經過長時間的壓測,文章被like的次數呈現高斯分布,鐘鼎的文章被like的次數最多。

xx設定為10.0,表示以鐘鼎為中心的20%這個區間内的文章id,覆寫了95%的出現機率。分布在10%這個區間的文章id覆寫了67%的出現機率。

xx越大,鐘鼎的文章id機率越高。

256個連接配接進行壓測,測試結果,每秒産生17.7萬次like請求。

階段性壓測後文章數

符合預期,繼續壓測。(或者我們也可以選擇指數分布進行測試)

暫時沒有進行優化的情況下,cpu使用情況如下

持續壓測like,産生2億文章的like資料,然後進入測試2。

2. 使用者好友分布

90% 100個以下,8%長尾分布300-1000, 2% 1000-10000

産生90%的使用者關系

産生8%的使用者關系

産生2%的使用者關系

最終生成1億使用者,占用123gb空間,2.7gb索引。

1. 查詢文章被誰like?

2. 查詢文章被like了多少次?

3. 查詢like某文章的使用者中,哪些是我的好友?

壓測腳本1, 查詢文章被誰like?

壓測腳本2, 查詢文章被like了多少次?

壓測腳本3, 查詢like某文章的使用者中,哪些是我的好友?

壓測結果1,查詢文章被誰like? 達到 101萬/s 并不意外。

壓測結果2,查詢文章被like了多少次? 104萬/s。

壓測結果3,查詢like某文的使用者中,哪些是我的好友? 64.8萬/s。

1. 數組越長,一條記錄占用的空間會越大,使用toast切片存儲,可以有效的提高查詢非數組字段的效率。

2. profiling,針對性的優化。

微網誌、facebook最常用的操作:

1. 關注人或者喜歡某條消息、微網誌等。

這個屬于寫操作,要求寫入快,并且要求寫入(like或關注)後立即反映出來。

2. 查詢好友清單

為了查詢快速,最快的方法是pk查詢,但是一個人可能關注很多人,如果是查詢多條記錄,很顯然會比較慢。

是以考慮使用數組存儲好友清單。

但是,使用數組存儲清單,又需要考慮寫入速度的問題。

是以使用流計算聚合是最好的,因為pg有流計算插件,可以在資料庫中完成流計算。

3. 查詢被關注的好友清單

反向好友關系,同樣要求查詢快速,使用正向關系一樣的方法。

4. 查詢文章(微網誌)被關注的次數,被關注人,被關注的人裡有哪些是我的好友。

首先被關注的次數,實際上就是個計數器。為了提高查詢速度,它必須是一個value而不是查詢時使用count(*)進行聚合。

查詢文章(微網誌)被關注的人,為了提高查詢速度,同樣考慮使用數組存儲。使用pg内置的流計算進行聚合。

被關注的人裡面有哪些是我的好友,這個問題就很簡單了,好友關系與文章(微網誌)被關注人的兩個數組求交集即可。

使用pg的流計算解決了實時寫入,實時聚合的問題。

同時由于資料實時被聚合,是以幾個查詢需求就顯得非常輕松。

測試得到的性能名額(未優化):

1. 關注微網誌(文章)

17.7萬/s,預計可以優化到30萬。

2. 查詢文章被誰like?

101.6萬/s

3. 查詢文章被like了多少次?

104.1萬/s

4. 查詢like某文章的使用者中,哪些是我的好友?

64.8萬/s

三體PCC大賽題目 - facebook\微網誌 like場景 資料庫設計與性能壓測

5. 機器:

(10w左右價位的x86,12*8tb sata盤,1塊ssd作為bcache)

資料庫内置流計算功能,是一件不錯的事情。

<a href="https://github.com/digoal/blog/blob/master/201609/20160911_01.md">《facebook linkbench 測試postgresql社交關系圖譜場景性能》</a>

<a href="https://github.com/digoal/blog/blob/master/201612/20161220_01.md">《流計算風雲再起 - postgresql攜pipelinedb力挺iot》</a>

<a href="https://github.com/digoal/blog/blob/master/201611/20161121_01.md">《postgresql on linux 最佳部署手冊》</a>