用Redis來儲存關注關係

來源:互聯網
上載者:User

用Redis來儲存關注關係

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 MySQL

  private $id;

  // The redis server configuration

  private $redis_config = array(

      array('host' => 'localhost', 'port' => 6379 )

  );

  // Stores the redis connection resource so that

  // we only need to connect to Redis once

  private $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)

下面關於Redis的文章您也可能喜歡,不妨參考下:

Ubuntu 14.04下Redis安裝及簡單測試

Redis主從複製基本配置

Redis叢集明細文檔

Ubuntu 12.10下安裝Redis(圖文詳解)+ Jedis串連Redis

Redis系列-安裝部署維護篇

CentOS 6.3安裝Redis

Redis安裝部署學習筆記

Redis設定檔redis.conf 詳解

Redis 的詳細介紹:請點這裡
Redis 的:請點這裡

本文永久更新連結地址:

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.