zoukankan      html  css  js  c++  java
  • 案例:用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 PredisClient($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)
    
  • 相关阅读:
    0309. Best Time to Buy and Sell Stock with Cooldown (M)
    0621. Task Scheduler (M)
    0106. Construct Binary Tree from Inorder and Postorder Traversal (M)
    0258. Add Digits (E)
    0154. Find Minimum in Rotated Sorted Array II (H)
    0797. All Paths From Source to Target (M)
    0260. Single Number III (M)
    0072. Edit Distance (H)
    0103. Binary Tree Zigzag Level Order Traversal (M)
    0312. Burst Balloons (H)
  • 原文地址:https://www.cnblogs.com/Alight/p/5256717.html
Copyright © 2011-2022 走看看