免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5389 | 回复: 1

[Redis] 案例:用Redis来存储关注关系 [复制链接]

论坛徽章:
0
发表于 2012-02-16 19:13 |显示全部楼层
案例:用Redis来存储关注关系






Redis提供了丰富的数据类型,比起关系型数据库或者简单的Key-Value存储(比如Memcached)来,Redis的数据模型与实际应用的数据模型更相近。比如下面说到的好友关系的存储,原作者使用了Redis的 Sets(集合)数据结构。



具体存储方式如下:对于每一个用户,其关注关系存储两份列表,一份为此用户关注的人的UID列表,另一份为此用户粉丝的UID列表,这两个列表都使用Sets(集合)。比如对于用户ID为123的用户,graph:user:123:following 保存的是其关注人的列表,graph:user:1:followed_by 保存的是关注他的人的列表。

下面是一个PHP代码的关注关系类,包括了常规的关注关系操作查询等方法,具体可看注释:
  1. <?

  2. /*
  3. * This example would probably work best if you're using
  4. * an MVC framework, but it can be used standalone as well.
  5. *
  6. * This example also assumes you are using Predis, the excellent
  7. * PHP Redis library available here:
  8. * https://github.com/nrk/predis
  9. */
  10. class UserNode {
  11.         // The user's ID, probably loaded from MySQL
  12.         private $id;

  13.         // The redis server configuration
  14.         private $redis_config = array(
  15.                 array('host' => 'localhost', 'port' => 6379 )
  16.         );

  17.         // Stores the redis connection resource so that
  18.         // we only need to connect to Redis once
  19.         private $redis;

  20.         public function __construct($userID) {
  21.                 $this->id = $userID;
  22.         }

  23.         private function redis() {
  24.                 if (!$this->redis) {
  25.                         $this->redis = new Predis\Client($redis_config);
  26.                 }

  27.                 return $this->redis;
  28.         }

  29.         /*
  30.          * Makes this user follow the user with the given ID.
  31.          * In order to stay efficient, we need to make a two-way
  32.          * directed graph. This means when we follow a user, we also
  33.          * say that that user is followed by this user, making a forward
  34.          * and backword directed graph.
  35.          */
  36.         public function follow($user) {
  37.                 $this->redis()->sadd("graph:user:{$this->id}:following", $user);
  38.                 $this->redis()->sadd("graph:user:$user:followed_by", $this->id);
  39.         }

  40.         /*
  41.          * Makes this user unfollow the user with the given ID.
  42.          * First we check to make sure that we are actually following
  43.          * the user we want to unfollow, then we remove both the forward
  44.          * and backward references.
  45.          */
  46.         public function unfollow($user) {
  47.                 if ($this->is_following()) {
  48.                         $this->redis()->srem("graph:user:{$this->id}:following", $user);
  49.                         $this->redis()->srem("graph:user:$user:followed_by", $this->id);
  50.                 }
  51.         }

  52.         /*
  53.          * Returns an array of user ID's that this user follows.
  54.          */
  55.         public function following() {
  56.                 return $this->redis()->smembers("graph:user:{$this->id}:following");
  57.         }

  58.         /*
  59.          * Returns an array of user ID's that this user is followed by.
  60.          */
  61.          public function followed_by() {
  62.                  return $this->redis()->smembers("graph:user:{$this->id}:followed_by");
  63.          }

  64.         /*
  65.          * Test to see if this user is following the given user or not.
  66.          * Returns a boolean.
  67.          */
  68.         public function is_following($user) {
  69.                 return $this->redis()->sismember("graph:user:{$this->id}:following", $user);
  70.         }

  71.         /*
  72.          * Test to see if this user is followed by the given user.
  73.          * Returns a boolean.
  74.          */
  75.         public function is_followed_by($user) {
  76.                 return $this->redis()->sismember("graph:user:{$this->id}:followed_by", $user);
  77.         }

  78.         /*
  79.          * Tests to see if the relationship between this user and the given user is mutual.
  80.          */
  81.         public function is_mutual($user) {
  82.                 return ($this->is_following($user) && $this->is_followed_by($user));
  83.         }

  84.         /*
  85.          * Returns the number of users that this user is following.
  86.          */
  87.         public function follow_count() {
  88.                 return $this->redis()->scard("graph:user:{$this->id}:following");
  89.         }

  90.         /*
  91.          * Retuns the number of users that follow this user.
  92.          */
  93.         public function follower_count() {
  94.                 return $this->redis()->scard("graph:user:{$this->id}:followed_by");
  95.         }

  96.         /*
  97.          * Finds all users that the given users follow in common.
  98.          * Returns an array of user IDs
  99.          */
  100.         public function common_following($users) {
  101.                 $redis = $this->redis();
  102.                 $users[] = $this->id;

  103.                 $keys = array();
  104.                 foreach ($users as $user) {
  105.                         $keys[] = "graph:user:{$user}:following";
  106.                 }

  107.                 return call_user_func_array(array($redis, "sinter"), $keys);
  108.         }

  109.         /*
  110.          * Finds all users that all of the given users are followed by in common.
  111.          * Returns an array of user IDs
  112.          */
  113.         public function common_followed_by($users) {
  114.                 $redis = $this->redis();
  115.                 $users[] = $this->id;

  116.                 $keys = array();
  117.                 foreach ($users as $user) {
  118.                         $keys[] = "graph:user:{$user}:followed_by";
  119.                 }

  120.                 return call_user_func_array(array($redis, "sinter"), $keys);
  121.         }

  122. }
复制代码
下面是使用这个类来操作关注关系的例子:

  1. <?
  2. // create two user nodes, assume for this example
  3. // they're users with no social graph entries.
  4. $user1 = UserNode(1);
  5. $user2 = UserNode(2);

  6. $user1->follows(); // array()

  7. // add some followers
  8. $user1->follow(2);
  9. $user1->follow(3);

  10. // now check the follow list
  11. $user1->follows(); // array(2, 3)

  12. // now we can also do:
  13. $user2->followed_by(); // array(1)

  14. // if we do this...
  15. $user2->follow(3);

  16. // then we can do this to see which people users #1 and #2 follow in common
  17. $user1->common_following(2); // array(3
复制代码
)来源:blog.meltingice.net

论坛徽章:
0
发表于 2012-02-17 22:39 |显示全部楼层
谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP