Redis提供了豐富的資料類型,比起關係型資料庫或者簡單的Key-Value儲存(比如Memcached)來,Redis的資料模型與實際應用的資料模型更相近。比如下面說到的好友關係的儲存,原作者使用了Redis的 Sets(集合)資料結構。
具體儲存方式如下:對於每一個使用者,其關注關係儲存兩份列表,一份為此使用者關注的人的UID列表,另一份為此使用者粉絲的UID列表,這兩個列表都使用Sets(集合)。比如對於使用者ID為123的使用者,graph:user:123:following 儲存的是其關注人的列表,graph:user:1:followed_by 儲存的是關注他的人的列表。
下面是一個PHP代碼的關注關係類,包括了常規的關注關係操作查詢等方法,具體可看注釋:
<?/* * This example would probably work best if you're using * an MVC framework, but it can be used standalone as well. * * This example also assumes you are using Predis, the excellent * PHP Redis library available here: * https://github.com/nrk/predis */class UserNode {// The user's ID, probably loaded from MySQLprivate $id;// The redis server configurationprivate $redis_config = array(array('host' => 'localhost', 'port' => 6379 ));// Stores the redis connection resource so that// we only need to connect to Redis onceprivate $redis;public function __construct($userID) {$this->id = $userID;}private function redis() {if (!$this->redis) {$this->redis = new Predis\Client($redis_config);}return $this->redis;}/* * Makes this user follow the user with the given ID. * In order to stay efficient, we need to make a two-way * directed graph. This means when we follow a user, we also * say that that user is followed by this user, making a forward * and backword directed graph. */public function follow($user) {$this->redis()->sadd("graph:user:{$this->id}:following", $user);$this->redis()->sadd("graph:user:$user:followed_by", $this->id);}/* * Makes this user unfollow the user with the given ID. * First we check to make sure that we are actually following * the user we want to unfollow, then we remove both the forward * and backward references. */public function unfollow($user) {if ($this->is_following()) {$this->redis()->srem("graph:user:{$this->id}:following", $user);$this->redis()->srem("graph:user:$user:followed_by", $this->id);}}/* * Returns an array of user ID's that this user follows. */public function following() {return $this->redis()->smembers("graph:user:{$this->id}:following");}/* * Returns an array of user ID's that this user is followed by. */ public function followed_by() { return $this->redis()->smembers("graph:user:{$this->id}:followed_by"); }/* * Test to see if this user is following the given user or not. * Returns a boolean. */public function is_following($user) {return $this->redis()->sismember("graph:user:{$this->id}:following", $user);}/* * Test to see if this user is followed by the given user. * Returns a boolean. */public function is_followed_by($user) {return $this->redis()->sismember("graph:user:{$this->id}:followed_by", $user);}/* * Tests to see if the relationship between this user and the given user is mutual. */public function is_mutual($user) {return ($this->is_following($user) && $this->is_followed_by($user));}/* * Returns the number of users that this user is following. */public function follow_count() {return $this->redis()->scard("graph:user:{$this->id}:following");}/* * Retuns the number of users that follow this user. */public function follower_count() {return $this->redis()->scard("graph:user:{$this->id}:followed_by");}/* * Finds all users that the given users follow in common. * Returns an array of user IDs */public function common_following($users) {$redis = $this->redis();$users[] = $this->id;$keys = array();foreach ($users as $user) {$keys[] = "graph:user:{$user}:following";}return call_user_func_array(array($redis, "sinter"), $keys);}/* * Finds all users that all of the given users are followed by in common. * Returns an array of user IDs */public function common_followed_by($users) {$redis = $this->redis();$users[] = $this->id;$keys = array();foreach ($users as $user) {$keys[] = "graph:user:{$user}:followed_by";}return call_user_func_array(array($redis, "sinter"), $keys);}}
下面是使用這個類來操作關注關係的例子:
<?// create two user nodes, assume for this example// they're users with no social graph entries.$user1 = UserNode(1);$user2 = UserNode(2);$user1->follows(); // array()// add some followers$user1->follow(2);$user1->follow(3);// now check the follow list$user1->follows(); // array(2, 3)// now we can also do:$user2->followed_by(); // array(1)// if we do this...$user2->follow(3);// then we can do this to see which people users #1 and #2 follow in common$user1->common_following(2); // array(3)
來源:blog.meltingice.net