上回寫了使用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