案例:用Redis来存储关注关系
2023-09-14 08:58:32 时间
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实现永久存储的突破性技术(redis永久)
- 利用Redis实现高效数据统计(redis做数据统计)
- 系统建立强大的Redis博客系统(redis博客)
- 超越Redis数量上限:实现大数据存储(redis数量上限)
- 『Redis缓存:快速、可靠的数据存储方式』(什么是redis缓存)
- 如何利用Redis存储大规模数据?(redis存储大数据量)
- 云存储基于SSO和Redis云存储的校园管理系统(sso实现redis)
- 分布式缓存Redis: 实现高效的分布式缓存(redis高性能)
- 使用Redis查询数据的简单命令指南(redis 查询数据命令)
- 缓存如何快速安全删除Redis缓存(怎么删除redis)
- 开启Redis,快速构建数据库(开通redis)
- 优惠大礼用Redis领取礼券吧(领取优惠券redis)
- 订单存储应该选择Redis吗(订单要存redis吗)
- 如何快速获取Redis命名空间(获取redis下命名空间)
- 如何设置Redis主从复制?详解Redis主从设置步骤(redis 主从设置)
- 存储构建可靠的Redis数据库硬盘存储系统(支持redis的db硬盘)
- Redis打造高性能存储服务的利器(为何用redis)
- 让单机Redis处理速度更快(单机redis太慢了怎么办)
- 解决Redis数据存储如何设置实现自动启动(怎么自动启动redis库)
- 利用Redis助力共享存储发展(共享存储redis)
- 的信息探索如何查看Redis存储的信息(如何查看redis存储)
- 掌握Redis数据导出秘诀(如何将redis数据导出)
- 搭建国内Redis服务快速搭建你的集群(国内redis服务)
- 商城采用Redis存储更多优惠卷(商城优惠卷放redis)
- 存储性能优化构建Redis集群环境,提升存储性能(redis集群环境下)
- Redis实现轻松键值存储,准确巧妙排序(redis键值存储顺序)
- 利用Redis实现多级缓存(redis采用几级缓存)
- Redis如何配置日志路径(redis 配置日志路径)
- Redis读写技术深度解析(redis读写解析)
- 分析原因Redis设置无效(redis设置不进去)
- 本 Redis老版本从历史角度看进步的进程(redis老版)
- 突破最大值探讨Redis缓存的性能极限(redis缓存最大值)
- Redis解决泛型存储问题(redis泛型存储)