Redis實現Timeline

瘋子好好活發表於2016-03-21

上回寫了使用Redis實現關注關係,這次說說使用Redis實現Timeline。

Timeline的實現一般有推模式、拉模式、推拉結合這幾種。
推模式:某人釋出內容之後推送給所有粉絲,空間換時間,瓶頸在寫入;
拉模式:粉絲從自己的關注列表中讀取內容,時間換空間,瓶頸在讀取;
推拉結合:某人釋出內容後推送給活躍粉絲,不活躍粉絲則使用拉取。

目前只討論推模式,考慮單個feed內容實體存入雜湊(hashes)、每個使用者的timeline列表存入列表(lists)。

1、釋出

釋出者釋出內容後,生成唯一feedID,以feedID為key存入hashes。
首先從釋出者的粉絲表裡獲取所有粉絲,再進行推送。

邏輯如下:

// 使用Redis INCR操作,生成唯一postID
$feedID = $redis->INCR("global:postID");
// 存入Hashes
$feedData = [
    `userID` => 1,
    `timestamp` => `1458680000`,
    `content` => `這是一條tweet`,
    `platform` => `web`,
];
$redis->HSET($feedID, $feedData);

// 寫入釋出者自己的已釋出列表
$redis->LPUSH("{$userID}:tweets", $feedID);

// 寫入釋出者自己的timeline
$redis->LPUSH("{$userID}:timeline", $feedID);

// 獲取釋出者粉絲列表
$follwerIDs = $redis->SMEMBERS("1:followers");

// 寫入
foreach ($follwerIDs as $followerID) {
    $redis->LPUSH("{$followerID}:timeline", $feedID);
}

2、讀取

某使用者登陸之後,獲取timeline Lists中的值,再從Hashes取資料進行處理。

$feedIDs = $redis->LRANGE("{$userID}:timeline", 0, 30); //取30條資料
foreach ($feedIDs as $feedID) {
    $feedData = $redis->HGETALL($feedID);
    // TODO:進一步進行處理、整合等操作。
}

3、刪除

當釋出者刪除某條訊息後,迴圈所有粉絲列表,並執行刪除操作。

// 從釋出者自己的已釋出刪除掉
$redis->LREM("{$userID}:tweets", 1, $feedID);

// 從釋出者自己的timeline刪除掉
$redis->LREM("{$userID}:timeline", 1, $feedID);

// 獲取釋出者粉絲列表
$follwerIDs = $redis->SMEMBERS("1:followers");

// 刪除
foreach ($follwerIDs as $followerID) {
    $redis->LREM("{$followerID}:timeline", 1, $feedID);
}

timeline從某種角度來說是臨時性的,如果年代久遠,可不必操作粉絲的timeline。

後記

Timeline系統說起來會很複雜,也不可能只靠Redis去實現。本文只是一個大體的思路,應對小資料量基本足夠。

部落格:http://blog.lovemydeer.com/2016/03/19/redis-timeline.html

[1]{:target=”_blank”}: https://segmentfault.com/a/1190000004612702

相關文章