基於ssdb和mongodb的feed服務架構
阿新 • • 發佈:2019-01-06
概要:
釋出動態,釋出活動,轉發動態或活動的資料都先寫入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資料及更新資料邏輯說明
前提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條
釋出動態,釋出活動,轉發動態或活動的資料都先寫入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條