Thinking PostgreSQL PL/Proxy Used in weibo(微博) Case

最近和網絡的同事聊組播的技術,對於IP電視來說,這個技術可以大大降低網絡的開銷。
突然想到微博其實也是很耗帶寬的一種東西,之前也沒去了解過,我的理解是微博就類似留言,留言上帶上了撰寫人,標籤,是否公開,接收人,發送時間等屬性。
如 , 
普通的一條微博,有了撰寫人,那麼關注撰寫人的用戶在登錄微博時就需要看到這部分微博信息。
另外,也可以定點給某人或者某些人發送信息,那麼就有了接收人的屬性。

如果用戶量很大,活躍用戶比較多的情況下,信息量也是巨大的。特別是明星用戶。關注或被關注的人比較多的情況下。信息推送都會帶來比較大的流量。

組播就值得借鑑了,如在10毫秒內發起的請求,如果有相同的,只請求一次。

另外,爲了獲得好的擴展性,數據庫設計的時候要充分考慮數據暴增帶來的問題。
如下:
Thinking PostgreSQL PL/Proxy Used in weibo Case - 德哥@Digoal - The Heart,The World.
 
發微博爲了提高響應速度可以考慮異步消息,記錄撰寫人的USERID,私信接收人的USERID,如果是回覆的話記錄子msgid等屬性。
MQ異步寫入到索引庫和消息數據庫。

熱索引主要用來存儲收微博時需要用到的索引,如根據關注者的USERID(s)來檢索msgid,根據自己的USERID來檢索MSGID(私信),根據標籤來檢索MSGID。

索引庫和消息數據庫都可以使用PostgreSQL數據庫,使用PL/Proxy可以不用擔心數據庫的擴展能力(讀用流複製擴展(毫秒延時),寫用bit&分庫擴展)。
PostgreSQL的pgfincore插件能實現數據文件塊級別的內存映射,並能記錄下數據塊的位置,重啓之後通過位置信息進行預加載數據或索引數據至內存,非常靈活。(靈活性超越ORACLE的buffer pool keep)
寫能力的提高除了分庫之外,單庫寫能力的提高也可以使用異步事務提交, 分組提交等。

持久數據(歷史數據), 每日/小時從熱數據庫同步。熱庫定期刪除時間比較OLD的數據。

收微博的時候,到關係庫取出關注者的userid(s),根據關注者的USERID檢索索引庫,按時間倒序取出MSGID。然後根據msgid(s)去數據庫取出數據。

收取私信的時候,根據自己的USERID到索引庫檢索MSGID,按時間倒序取出MSGID。然後根據msgid(s)去數據庫取出數據。

如圖 : 
Thinking PostgreSQL PL/Proxy Used in weibo Case - 德哥@Digoal - The Heart,The World.

熱數據和熱索引在這裏只的是時間比較接近當前時間的數據,怎麼理解呢?
因爲微博裏面的信息量非常大,推送給用戶的時候是按照時間倒序顯示的。所以時間約新鮮,數據越熱。被回覆和轉發的概率越大。
而時間比較久遠的數據,相對來說不太會被查詢或修改。

Thinking PostgreSQL PL/Proxy Used in weibo Case - 德哥@Digoal - The Heart,The World.
分庫規則:
1. 索引庫分庫因子: userid(int8) bit& 操作, attr(int4) bit&操作.庫的個數爲2^n次方。當然plproxy允許重複條目。所以最粗的時候服務器不需要完全按照實際分庫的個數來配置,可以後期幾乎平滑的擴展。
2. 數據庫分庫因子: msgid(int8) bit& 操作, 庫的個數爲2^n次方。當然plproxy允許重複條目。所以最粗的時候服務器不需要完全按照實際分庫的個數來配置,可以後期幾乎平滑的擴展。
3. 關係庫分庫因子: userid(int8) bit& 操作。當然plproxy允許重複條目。所以最粗的時候服務器不需要完全按照實際分庫的個數來配置,可以後期幾乎平滑的擴展。

CACHE:
pgmemcached, 通過這個PostgreSQL插件,CACHE操作可以更加靈活的和數據庫緊密結合起來(通過PG函數增刪改查memcache的內容)。
Thinking PostgreSQL PL/Proxy Used in weibo(微博) Case - 德哥@Digoal - The Heart,The World.
 

關係庫:
正向數據結構 : userid(int8),attention_userid(int8) 。(是否需要限制關注上限,關注的人越多,每次獲取關注人信息的數據量越龐大)
反向數據結構 : userid(int8),attentioned_userid(int8) 。(明星用戶可能被百萬甚至千萬人關注)

其他:
按USERID來分庫 ,在數據庫的擴展性方面比較靈活。
當然還要考慮msgid取出的時候需要merge後排序,這個比較麻煩。

按時間來分庫比較麻煩的是,熱點將集中在最近的庫。
按時間,然後在下面再按用戶ID來分,或許也是一種選擇。

【能力預估】
假設 1臺8核72G內存,500G硬盤服務器, 1.5W rw tps. 
        緩存服務器, 15W rw tps.
用戶1億,平均關注100用戶。正向關係100億,反向關係100億。
10%活躍用戶。平均每人每天發微博10條。一天1億條新增微博信息。
關係庫預計投入:100/8=12.5 臺, 對外提供18W rw tps
反向關係庫預計投入:100/8=12.5 臺, 對外提供18W rw tps
(每一維度)熱索引庫預計投入:2/8=1 臺, 對外提供1.5W r/w tps (可能不能滿足rTPS要求,通過複製或者pgmemcache解決)
熱數據庫預計投入:2/1=2 臺, 對外提供3W r/w tps (可能不能滿足rwTPS要求,r通過複製或者pgmemcache解決,w增加分區服務器或者MQ異步消息解決)
(每一維度)歷史索引庫預計投入:視存儲量
數據庫預計投入:視存儲量
緩存服務器預計投入:視實際請求量
hot standby服務器預計投入:視實際請求量

【壓力測試】

有待完善.