1. 程式人生 > >關係鏈的特點之讀擴散和寫擴散

關係鏈的特點之讀擴散和寫擴散

之前在網上看到關於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流程:

訊息釋出流程:

  1. 更新自己的outbox
  2. 載入followers列表
  3. 更新followers inbox

獲取首頁流程:

  1. 檢查inbox cache是否可用
  2. 獲取關注列表
  3. 聚合內容,獲得訊息索引
  4. 根據索引,返回最終聚合的訊息內容

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