1. 程式人生 > >基於ssdb和mongodb的feed服務架構

基於ssdb和mongodb的feed服務架構

概要:
釋出動態,釋出活動,轉發動態或活動的資料都先寫入mongodb作為基礎資料儲存,每條釋出id都有全域性唯一的tid,然後再把釋出tid寫入ssdb,供feed查詢使用。
即mongodb作為feed基礎資料儲存服務,所有對feed資訊的修改針對mongodb,ssdb只作為佇列服務,供app端查詢時儘快的獲取相應的tid。

app端獲取feed資料流程說明:
app->請示服務端feed服務->服務端到ssdb中查詢某個人圈子的feed的tid->根據tid到mongodb中查詢feed所需要的資料。

為何不使用ssdb的佇列而選用ssdb的hasmap?

ssdb的佇列不支援更新或刪除佇列中的某條資料。
但通過mongodb中feed集合中的tid作為整數分號器, 然後把tid轉成前面補0的12位長的字串來表示其先後的順序來替代ssdb自有的佇列服務,
這樣即支援了隨時可以修改或刪除佇列中的某條記錄,也實現了佇列服務中的“順序”。

ssdb的hashmap名稱及對應用約定

feed_circle_使用者uid:儲存某個使用者圈子feed資料

ssdb的hashkey生成規則說明
feed_circle的hashkey的值為對應在mongodb中的tid欄位的值加上字首0,湊夠13位(萬億,最大值為9999999999999,儘量足夠用)的字串來作為hashkey。

以mongodb中feed集合某條記錄中的tid值為說明:
tid值為9890,對應ssdb中的hashkey值應為0000000009890
tid值為1870,對應ssdb中的hashkey值應為0000000001870
tid值為121979,對應ssdb中的hashkey值應為0000000121979
具體前面補0可以用php中的str_pad內建方法:str_pad,如把9890按照上面約定的規則補0的方式為:
str_pad(9890, 12, '0', STR_PAD_LEFT)

往ssdb中寫入feed資料及更新資料邏輯說明

ssdb中的feed資料直接為app端提供查詢服務,為了保證查詢時不再一一拼裝資料再返回給app端,故ssdb中儲存的feed資料必須為儘可能全的且最新的資料,為滿足此需求, 在先往mongodb寫入或更新時要隨之寫入或更新ssdb中對應的資料。

某個釋出一條動態時的示例程式碼:

$tid = Ids::generateId('feed',array('init'=> 1,'step'=> 1)); //基於mongodb生成的自增的唯一發布id
$hashkey = str_pad($tid, 13, '0', STR_PAD_LEFT);
$this->mc->set("feed_circle_max_tid_{$uid}", $tid);
//寫入我的feed佇列
$this->ssdb->hset("feed_circle_{$uid}", $hashkey, $tid);

//寫入粉絲feed佇列
$relation = new Relation();
$fanUids = $relation->getFanUids($uid);
foreach ($fanUids as $fanUid) {
    $this->ssdb->hset("feed_circle_{$fanUid}", $hashkey, $tid);
}

查詢某個人的feed列表

/*$tid為起點最大發布id,返回的資料不包括此tid,例如資料庫中feed的tid值從1000到8000,那麼當傳遞的tid值為2000時,返回的feed列表中的tid值為1999至1000中的N條資料,資料庫中tid生成的規則為自增長,後釋出的tid值大於原先發布的。當不傳遞此參考或傳遞的此引數值為0時表示取最新的feed資料*/
$limitNum = 30; //一次給app端返回的條數
$maxId = $tid ? $tid : ($this->mc->get("feed_circle_max_tid_{$uid}") + 1);
$hashkey = str_pad($maxId, 12, '0', STR_PAD_LEFT);
$res = $this->ssdb->hrscan("feed_circle_{$uid}", $hashkey, '000000000000', $limitNum);

$tids = array();
if (!empty($res)) {
    foreach ($res as $tid) {
        $tids[] = intval($tid);
    }
    $feedList = $feed->getRowsByTids($tids);
}

 
 

app端請求feed資料時服務端查詢邏輯說明

前提1:圈子中tid的最大值在memcached儲存,圈子feed最大tid的key為feed_circle_max_tid_使用者uid
前提2:服務端返回給app端的每一條動態資料都有一個正整型的tid值。

當app端使用者uid為2833的查詢feed列表最新資料時(以當前tid最大值為897689為例,不知道最小值,那麼最小值預設為000000000000):
$this->ssdb->hrscan('feed_circle_2833', '000000897689', '000000000000', 30); //一次返回30條

當app端滑屏向上滑動請求先前的資料時(此時app端需要把最小的tid值傳給伺服器端,如傳給伺服器端tid最小值為3879):
$this->ssdb->hrscan('feed_circle_2833', '000000003879', '000000000000', 30); //一次返回30條