Redis實現Timeline

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

Timeline的實現通常有推模式、拉模式、推拉結合這幾種。
推模式:某人發佈內容以後推送給全部粉絲,空間換時間,瓶頸在寫入;
拉模式:粉絲從本身的關注列表中讀取內容,時間換空間,瓶頸在讀取;
推拉結合:某人發佈內容後推送給活躍粉絲,不活躍粉絲則使用拉取。web

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

一、發佈

發佈者發佈內容後,生成惟一feedID,以feedID爲key存入hashes。
首先從發佈者的粉絲表裏獲取全部粉絲,再進行推送。segmentfault

邏輯以下:post

// 使用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);
}

二、讀取

某用戶登錄以後,獲取timeline Lists中的值,再從Hashes取數據進行處理。code

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

三、刪除

當發佈者刪除某條消息後,循環全部粉絲列表,並執行刪除操做。orm

// 從發佈者本身的已發佈刪除掉
$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。htm

後記

Timeline系統提及來會很複雜,也不可能只靠Redis去實現。本文只是一個大致的思路,應對小數據量基本足夠。blog

博客:http://blog.lovemydeer.com/2016/03/19/redis-timeline.htmlget

[1]{:target="_blank"}: http://www.javashuo.com/article/p-romzljcm-v.html

相關文章
相關標籤/搜索