上回寫了[使用Redis實現關註關係][1],這次說說使用Redis實現Timeline。 Timeline的實現一般有推模式、拉模式、推拉結合這幾種。 推模式:某人發佈內容之後推送給所有粉絲,空間換時間,瓶頸在寫入; 拉模式:粉絲從自己的關註列表中讀取內容,時間換空間,瓶頸在讀取; 推拉結合:某人 ...
上回寫了使用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