微博後台架構**——讀擴散pull
、寫擴散
push
、混合模式
(push+pull)
——相關
cache(redis
,memcache)
之前在網上看到關於twitter
、sina
1、讀擴散還是寫擴散?
inbox: 收件箱,你收到的訊息,即你所關注的人發布的訊息。
outbox: 發件箱,你發布的訊息。
寫擴散(push)
該方式為每個使用者維護乙個訂閱列表,記錄該使用者訂閱的訊息索引(一般為訊息id
、型別、發表時間等一些元資料)。每當使用者發布訊息時,都會去更新其
follower
的訂閱列表。
優點:讀很輕。初始化時僅需要讀取自己的inbox
即可。缺點:寫很重。每發布乙個訊息,會導致大量的寫操作。
注:一般來說,使用者發布訊息,並不會更新所有followers
followers
即可。讀擴散(pull)
該方式為每個使用者維護乙個傳送列表,記錄該使用者所有發表過的訊息索引。
優點:寫很輕,節省空間。使用者每發布一條訊息,僅需更新自己的outbox
。缺點:讀操作很重,計算量大。假設你收聽了1k
使用者,則初始化時,需要從
1k個使用者的
outbox
拉取訊息,然後計算獲得最新的
n條訊息。
混合模式(push+pull)
該方式既為讀寫擴散的結合,根據使用者followers
的數量來決定是讀擴散還是寫擴散。例如
followers
大於1k
的,則使用讀擴散,否則使用寫擴散。
從目前現在網上的一些資料來看,twitter
2、關於
cache
對於乙個千萬級甚至億級使用者的大型**來說,合理使用cache
至關重要。
乙個使用者的核心資料由如下幾個部分組成:inbox
,outbox
,關係鏈,訊息內容。
· timyang
的ppt
redis
的list
或set
實現。·
outbox:快取一定數量(例如
200)條最近發表的訊息。
· 關係鏈:following
相對於followers
來說,快取容易些,
follower
1600
萬。·
訊息內容:按內容年齡快取;一般需要多份支援容災;需要快取xml
,json
,rss
,atom
等多種格式的快取以供
api使用。
以twitter
為例,其將
cache
分為四類:
vector cache
,row cache
,page cache
,fragment cache
,均使用
memcached
實現。其中:
· vector cache主要快取使用者的
inbox
以及outbox
索引,其命中率高達
99%;
· row cache主要快取使用者關係鏈資料,以及
tweets
內容,命中率為
95%;
· fragment cache快取
tweet
的xml
,json
,rss
,atom
四種格式資料,以供
api使用,命中率為
95%;
· page cache主要原來快取那些高人氣使用者的個人主頁,命中率僅為
40%。
下圖為twittercache
架構圖:
twitter為啥要為
api通道設定
fragment cache
和page cahce
呢?其原因是
的80%
流量來自
api。
流程:訊息發布流程: 1
更新自己的outbox
2 載入followers
列表3
更新followers inbox
獲取首頁流程: 4
檢查inbox cache
是否可用
5 獲取關注列表 6
聚合內容,獲得訊息索引 7
根據索引,返回最終聚合的訊息內容
3、關於儲存
目前twitter
mysql
ssd+
大檔案儲存(每次寫操作都是
操作,寫操作可以先用記憶體快取,達到適當大小合併,儘量減少隨機寫)。其他細節因不清楚或不方便透露,不做細述。
4、關於洪峰處理。
一般用非同步佇列處理方式。訊息佇列產品有:kestrel
使用scala
實現),
rabbitmq
(使用erlang
實現),
memcacheq
。twitter 09年時,使用者的平均
followers
數量為126
個。按照每秒
400訊息發布數算,那每秒就需要推送
126*400=50400
條訊息出去。為了削 峰,
自己用scala
實現了乙個分布式訊息佇列
kestrel
,其**僅為
1200
行,執行在
3臺機器上,其使用
memcached
協議, 其
server
memcacheq
。
讀寫優先問題
如下 mutex wr 1 mutex countmutex 1 intcount 0 首先編寫write的大概框架 void write read的大概框架如下,其中為了保證讀與讀之間不互斥,而讀與寫之間互斥 主要通過記錄當前讀者的個數 void read 以上的編寫需要注意讀者何時取得資源與何時...
讀寫亂碼問題
為什麼會產生亂碼問題?1.編碼和解碼規則不一致 2.這個字元編碼本身就不支援某種語言 為了避免產生亂碼問題我們最好在不同環節使用相同的編碼和解碼規則,建議使用預設編碼也可以去指定編碼.可以使用下邊的方法更改 編碼 string byte string中有對應的方法 byte getbytes 使用平...
讀寫者問題
只要求讀檔案的程序稱為reader程序,其他程序稱為writer程序。允許多個程序同時讀乙個共享物件,但不允許乙個writer程序和其他reader程序同時或writer程序同時訪問乙個共享物件。簡單來說,讀寫者問題是保證乙個writer程序必須與其他程序互斥的訪問共享物件的同步問題。三句話來說,就...