關係鏈的特點之讀擴散和寫擴散
之前在網上看到關於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,關係鏈,訊息內容。
- inbox:主要快取訊息索引,僅為線上使用者快取,從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呢?其原因是Twitter的80%流量來自API。
下面以新浪微薄介紹一下Cache流程:
訊息釋出流程:
- 更新自己的outbox
- 載入followers列表
- 更新followers inbox
獲取首頁流程:
- 檢查inbox cache是否可用
- 獲取關注列表
- 聚合內容,獲得訊息索引
- 根據索引,返回最終聚合的訊息內容
3、關於儲存
目前Twitter和新浪的落地儲存,都是使用MySQL。而騰訊微薄則使用採用SSD+大檔案儲存(每次寫操作都是append操作,寫操作可以先用記憶體快取,達到適當大小合併,儘量減少隨機寫)。其他細節因不清楚或不方便透露,不做細述。
4、關於洪峰處理。
一般用非同步佇列處理方式。訊息佇列產品有:Kestrel(twitter使用Scala實現),RabbitMQ(使用Erlang實現),MemcacheQ。
Twitter 09年時,使用者的平均followers數量為126個。按照每秒400訊息釋出數算,那每秒就需要推送126*400=50400條訊息出去。為了削 峰,Twitter自己用Scala實現了一個分散式訊息佇列Kestrel,其程式碼僅為1200行,執行在3臺機器上,其使用memcached協議, 其Server之間無共享狀態,且全記憶體。新浪使用的是MemcacheQ。
原文地址:http://blog.163.com/[email protected]/blog/static/1322296552013430114959121/
相關推薦
關係鏈的特點之讀擴散和寫擴散
之前在網上看到關於Twitter、Sina以及騰訊微薄的一些實現技術,這個簡單做個摘要。 1、讀擴散還是寫擴散? inbox: 收件箱,你收到的訊息,即你所關注的人釋出的訊息。 outbox: 發件箱,你釋出的訊息。 寫擴散(Push) 該方式為每個使用者維護一個訂閱列表,記錄該使用者訂閱的訊息索引
Java讀檔案和寫檔案
import java.io.*; public class FileTest { String path = "C:\\Users\\Desktop\\test.txt"; File f = new File(path); private void writeFile() throw
深入Mysql鎖機制(二)讀鎖和寫鎖
深入Mysql鎖機制(二)讀鎖和寫鎖 這篇文章主要來介紹一下MySQL資料庫中的表級鎖。 本文提到的讀鎖和寫鎖都是MySQL資料庫的MyISAM引擎支援的表鎖的。而對於行級鎖的共享讀鎖和互斥寫鎖請閱讀MySQL中的共享鎖與排他鎖。我習慣在描述表鎖的時候按照讀寫來區分,在表
MySQL中的讀鎖和寫鎖
在資料庫的鎖機制中介紹過,資料的鎖主要用來保證資料的一致性的,資料庫的鎖從鎖定的粒度上可以分為表級鎖、行級鎖和頁級鎖。在我的部落格中重點介紹過MySQL資料庫的行級鎖。這篇文章主要來介紹一下MySQL資料庫中的表級鎖。 本文提到的讀鎖和寫鎖都是MySQL資料庫的My
C語言檔案操作——讀一行和寫一行
檔案讀寫其實說簡單也簡單,會用即可,說複雜也複雜,作業系統檔案系統有很多東西需要學習。在此簡單介紹一種寫日誌與讀日誌的方法——寫一行&讀一行。 1.寫一行程式碼: #include <stdio.h> void writeLogLin
hadoop 讀流程和寫流程
hadoop HDFD讀流程 hadoop HDFD寫流程 package com.lhj.hadoop; import java.io.BufferedReader; import java.io.IOException; import java.io.InputSt
redis原子性讀寫操作之LUA指令碼和watch機制
最近在開發電商平臺的子系統——儲值卡系統,系統核心業務涉及到金額消費以及庫存控制,因此為了解決建立在記憶體上高併發情況下的事務控制,使用了spring封裝的RedisTemplate執行lua指令碼進行原子性操作,確保金額消費,庫存按順序處理,解決資源爭搶。 1.使用lua指令碼 Redis 使用單個 L
算法總結之 刪除鏈表的中間節點和a/b處的節點(鏈表中間節點的重要思想)
math 取整 算法 blog 總結 rem nod == while 給定鏈表的表頭節點head,實現刪除鏈表的中間節點的函數 推展: 給定鏈表的頭節點,整數a 和 整數 b,實現刪除a/b處節點的函數 先來分析原問題, 長度1 直接返回 長度2 將頭節點刪
算法總結之 反轉單向和雙向鏈表
while turn double logs pub pan != package port 分別實現反轉單向和雙向鏈表的函數 看代碼: package TT; public class Test88 { public class Node{
線程同步之讀寫鎖(鎖操作的補充)
允許 資源 加鎖 函數 申請 tex bject def 讀取 輕量級的讀寫鎖(Slim Reader-Writer locks):讀寫鎖實際是一種特殊的自旋鎖,它把對共享資源的訪問者劃分成讀者和寫者,讀者只對共享資源進行讀訪問,寫者則需要對共享資源進行寫操作。這種鎖相對於
多線程編程之讀寫鎖
|| 概念 release 線程編程 相關 修改 reader lin 實現 在《多線程編程之Linux環境下的多線程(二)》一文中提到了Linux環境下的多線程同步機制之一的讀寫鎖。本文再詳細寫一下讀寫鎖的概念和原理。 一、什麽是讀寫鎖 讀寫鎖(也叫共享-獨占鎖)
讀和寫
gpo can pen pre cpp stdout true class pos freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); /* 正常代碼
文件讀和寫的操作及區別
pythonPython對文件操作:write和writelines的區別1 write()需要傳入一個字符串或者變量做為參數,否則會報錯2 writelines()既可以傳入字符串又可以傳入一個字符序列,並將該字符序列寫入文件3 註意必須傳入的是字符序列,不能是數字序列(卡在這裏搞了半天)read() #一
網易cetus之讀寫分離
cetus 中間件 讀寫分離 一、 簡介 Cetus是由C語言開發的關系型數據庫MySQL的中間件,主要提供了一個全面的數據庫訪問代理功能。Cetus連接方式與MySQL基本兼容,應用程序幾乎不用修改即可通過Cetus訪問數據庫,實現了數據庫層的水平擴展和高可用。Cetus由網易樂得專家技術團隊
8.spark core之讀寫數據
鍵值對 逗號 .data air lines man inf return ear spark支持多種數據源,從總體來分分為兩大部分:文件系統和數據庫。 文件系統 ??文件系統主要有本地文件系統、Amazon S3、HDFS等。 ??文件系統中存儲的文件有多種存儲格式。sp
Python open 讀和寫
bject 進行 pen text txt 測試 blog erro dcb # -*- coding: utf-8 -*- # 測試文件名為: # text.txt # 測試文件內容為: # abcdefg # 每次操作後將文件復原 # r # 以只讀方式打開文件,文
12.spark sql之讀寫數據
rcfile serializa fig jdbc連接 nco .sh nat 字段 jdb 簡介 ??Spark SQL支持多種結構化數據源,輕松從各種數據源中讀取Row對象。這些數據源包括Parquet、JSON、Hive表及關系型數據庫等。 ??當只使用一部分字段時,
C++從零開始區塊鏈:區塊鏈業務模組之建立交易和區塊
建立交易簡單,直接給結構體賦值就行 Transactions BlockChain::CreateTransactions(const std::string &sender, const std::string &recipient, float amount)
C++從零開始區塊鏈:P2P模組之節點註冊和監聽
ThreadPool是一個執行緒池,具體實現就不貼了,隨便找個執行緒池實現就行,也可以戳這裡檢視程式完整程式碼。 P2PNode::P2PNode(const char *if_name) { m_sock = socket(AF_INET, SOCK_DGRAM, 0);//I
MYSQL之讀寫分離搭建方案
讀寫分離實現:360 Atlas(代理層實現,無需修改應用程式程式碼) 實現步驟 # 安裝 shell> rpm -i Atlas-2.2.1.el6.x86_64.rpm # 解除安裝 shell> rpm -e Atlas-2.2