Redis3官方文档(6)
——使用Redis实现Twitter(上)
本文讲述使用PHP以及Redis来设计和实现一个简单的微博。编程社区传统上认为,在开发web应用程序时,作为特殊目的的键值存储数据库不能用于替换关系型数据库。本文将向你展示Redis在键值层之上的数据结构是实现各种应用程序的有效数据模型。
在继续之前,你可以花点时间体验一下在线演示(http://retwis.redis.io,译者注),看看我们究竟要做什么。长话短说:这是个练手,但是已经足够复杂到让你学习如何创建一个更复杂的程序的基础。
注意:这篇文章的原始版本写于2009年Redis发布时。当时还不清楚Redis的数据模型适合整个程序。5年以后的今天,已经有许多应用程序使用Redis作为他们的主要存储,所以今天这篇文章的目的就是作为新学者的教程。你讲学习如何使用Redis设计一个简单的数据层,如何应用不同的数据结构。
我们的微博系统,叫做Retwis,结构简单,具有很高的性能,只需少许努力能够分布于任意数量的web和Redis服务器。你可以在这里找到源代。
我使用PHP来做这个例子,是因为每个人都能看懂。使用Ruby,Python,Erlang等等语言也能得到同样(或更好)的结果。也有一些其他的实现(但是不是所有的实现都使用和当前版本教程同样的数据层,所以请使用PHP官方实现会更好)。
- Retwis-RB是由Daniel Lucraft使用Ruby和Sinatra实现的版本!当然包含了全部的源代码,以及文章底部一个指向Git仓库的链接。本文剩下的部分定位为PHP,但是Ruby程序员也可以查看Redis-RB的代码,因为他们从概念上非常相似。
- Retwis-J是由Costin Leau使用Spring Data Framework和Java实现的版本。代码可以在GitHub上找到,springsource.org上有更全面的文档介绍。
此处省略一万字。。。
(原文此处是对Redis数据类型的介绍,可以参考本系列文章的第2篇和第3篇,译者注)
前提条件(Prerequisites)
如果你还没有下载Retwis源码请先下载。包含一些PHP文件和Predis的一份拷贝(例子中我们使用的客户端库)。
另外你想要做的一件事是一个运行的Redis服务器。下载源码,使用make构建,使用./redis-server运行,你就可以开始了。只是玩玩或者运行我们的Retwis的话,不需要配置。
数据设计(Layout)
当使用关系型数据库时,必须先设计数据库模式,这样我们先需要知道表,索引等数据库确定的东西。Redis没有表,那我们需要设计什么呢?我们需要确定需要什么键来表示我们的对象,以及这些键需要存储什么值。
让我们从用户开始。我们需要用户名、用户id,密码,用户粉丝(following),关注列表等等来表示用户。第一个问题是,我们如果标识一个用户?像在关系型数据库,一个好的解决方案是用不同的号码来标识不同的用户,所以我们可以关联一个唯一ID给每个用户。对这个用户的引用通过其ID。产生唯一ID非常简单,使用我们的原子INCR操作。当我们创建一个新用户我们就可以(假设用户名为antirez):
INCR next_user_id => 1000
HMSET user:1000 username antirez password p1pp0
注意:在真实程序中你应该使用哈希的密码,为了简化我们直接存储密码明文。
我们使用next_user_id键为每一位新用户提供唯一ID。然后我们使用唯一ID来命名存储用户数据的哈希结构的键。记住,这是使用键值存储的通用设计模式!除了字段已经被定义了以外,我们还需要更多东西来完整定义一个用户。例如,有时通过用户名获得用户ID,于是我们每次添加一个用户,我们也需要操作用户的键,使用用户名作为字段,用ID作为值的哈希。
HSET users antirez 1000
这一开始看起来有点奇怪,但是记住,我们只能采取直接访问数据的方式,而没有第二层索引。没法告诉Redis根据一个指定值返回其键。这也是我们的优势。强制我们使用按照主键来访问一切的新的范式来组织数据,此处主键是关系型数据库中的术语。
粉丝(followers),关注(following),和帖子(updates)
我们的系统还有一个核心需求。一个用户可能有很多关注他的用户,我们称他们为其粉丝。一个用户也可能会关注其他用户,我们称他们为其关注者。我们有一个为此量身打造的数据结构,就是集合。独一无二的集合元素,常量时间测试存在性,是两个非常有趣的特性。然而,记录一个用户开始关注另一个用户的时间怎么办?在我们加强版的微博系统里面。我们使用有序集合而不是一个简单的集合,用粉丝或者粉儿的用户ID作为元素,用用户关系创建时的unix时间作为分数。
让我们来定义我们的键:
followers:1000 => Sorted Set of uids of all the followers users
following:1000 => Sorted Set of uids of all the following users
我们添加一个粉丝:
ZADD followers:1000 1401267618 1234 => Add user 1234 with time 1401267618
另外一件重要的事情我们需要一个用户首页的位置来展示用户的更新。我们需要按照时间顺序来访问这些数据,从最近的到最老的,为此最好的数据结构就是列表。基本上每一个更新都会被LPUSH到用户更新键,多亏了LRANGE,我们能实现分页等等。注意,我们可以互换地使用更新(updates)和帖子(posts)这两个词,因为某种意义上说,更新其实就是小型帖子。
posts:1000 => a List of post ids - every new post is LPUSHed here.
这个列表基本上就是用户的时间轴。我们会加入他自己帖子ID,以及其关注者创建的帖子。基本上我们实现了一个写分列。
身份验证(Authentication)
好了,我们或多或少已经有了关于用户的一切,除了身份验证。我们会用一种简单而又健壮的方式处理身份验证:我们不想使用PHP的会话机制,我们的系统要为轻松地分布式部署于很多web服务器上而准备,所以我们会保存全部状态到Redis数据库中。所有我们要做的就是要设置一个猜不出来的字符串作为认证用户的cookie,以及一个持有该字符串的客户端的用户ID的一个键。
我们需要两件事情来使得这个可以工作得健壮。第一,当前认证秘钥(不可猜测的字符串)是用户对象的一部分,所以当创建用户时,我们需要在哈希中设置一个认证字段:
HSET user:1000 auth fea5e81ac8ca77622bed1c2132a021f9
另外,我们需要映射认证秘钥到用户ID,所以我们也需要一个认证键,使用哈希来映射秘钥和用户ID。
HSET auths fea5e81ac8ca77622bed1c2132a021f9 1000
为了认证一个用户,我们只需要简单几步(请查看Retwis项目中的login.php源代码):
- 从登陆表单获取用户名和密码。
- 检查用户名是否存在于users哈希中。
- 如果存在,我们获取其ID(例如1000)。
- 检查user:1000的密码是否匹配,否则返回错误消息。
- 认证完毕,设置"fea5e81ac8ca77622bed1c2132a021f9"(user:1000的auth字段)作为认证cookie。
这是真实的代码:
include("retwis.php");
# Form sanity checks
if (!gt("username") || !gt("password"))
goback("You need to enter both username and password to login.");
# The form is ok, check if the username is available
$username = gt("username");
$password = gt("password");
$r = redisLink();
$userid = $r->hget("users",$username);
if (!$userid)
goback("Wrong username or password");
$realpassword = $r->hget("user:$userid","password");
if ($realpassword != $password)
goback("Wrong useranme or password");
# Username / password OK, set the cookie and redirect to index.php
$authsecret = $r->hget("user:$userid","auth");
setcookie("auth",$authsecret,time()+3600*24*365);
header("Location: index.php");
这些发生在每次用户登录时,但是我们还需要一个isLoggedIn函数来检查用户是否已经通过身份认证。以下是isLoggedIn函数的逻辑步骤:
- 从用户获取auth cookie。如果没有cookie则用户没有登录。我们称这个cookie值为<authcookie>。
- 检查<authcookie>是否存在于auths哈希字段中,以及其值(即用户ID,本例中是1000)。
- 为了系统更加健壮,验证user:1000的auth字段是否匹配。
- 用户验证完成,我们从$User全局变量中加载一些信息。
代码也许比上面的描述更简单:
function isLoggedIn() {
global $User, $_COOKIE;
if (isset($User)) return true;
if (isset($_COOKIE['auth'])) {
$r = redisLink();
$authcookie = $_COOKIE['auth'];
if ($userid = $r->hget("auths",$authcookie)) {
if ($r->hget("user:$userid","auth") != $authcookie) return false;
loadUserInfo($userid);
return true;
}
}
return false;
}
function loadUserInfo($userid) {
global $User;
$r = redisLink();
$User['id'] = $userid;
$User['username'] = $r->hget("user:$userid","username");
return true;
}
===============================================================================
大家好,我是阮威。华中科技大学,计算机软件专业硕士。毕业后加入腾讯,先后在腾讯电子商务部和无线游戏产品部工作,现供职于欢聚时代基础产品部。IT男,至今。对技术有强烈的热情,对技术以外的事物热情更高。
我的座右铭是“呼喊移动人的移动连接,践行自由人的自由联合”。欢迎大家收听我的公众账号。
分享到:
相关推荐
**Redis官方文档详解** Redis,全称Remote Dictionary Server,是一个开源的、支持网络的、键值存储系统。它通常被用作数据库、缓存和消息代理。Redis以其高性能、丰富的数据结构以及简单易用的API而闻名。此文档将...
通过使用 `phpredis`,开发者可以轻松地在 PHP 中实现缓存、队列管理以及其他内存级别的数据存储功能。 #### 二、安装与配置 - **下载地址**: `https://github.com/owlient/phpredis` - **支持版本**: 支持 Redis ...
- **在集群上运行 Redis 存储库**:支持在 Redis 集群环境中使用存储库功能。 #### 八、其他 - **附录 A:Schema**:提供了核心 Schema 的详细描述,帮助开发者更好地理解数据结构和存储方式。 - **附录 B:命令...
redis说明文档使用说明redis说明文档使用说明redis说明文档使用说明redis说明文档使用说明redis说明文档使用说明redis说明文档使用说明
Redis支持的数据类型有字符串(Strings)、哈希(Hashes)、列表(Lists)、集合(Sets)和有序集合(Sorted Sets),这些数据结构的使用极大地丰富了应用程序的实现方式。 字符串是Redis最基础的数据类型,可以...
Redis 的官方文档非常详尽,包含了从基础概念到高级特性的详细介绍。下面将根据提供的部分内容,对Redis中的关键知识点进行解析。 #### 三、键空间通知(keyspace notification) 键空间通知是Redis为客户端提供的...
从网上抓取的redis文档,中文版本!!提供给在没有网络下的朋友查询参考使用!!
需要注意的是,文档中提到“官方文档都没”和“一部分不支持哨兵模式的连接”,这意味着对于rediscala库可能缺乏完整的官方文档支持,用户在使用过程中可能会遇到困难,尤其是当需要配置支持哨兵模式的连接时。...
- 下载最新版本的Redis源代码,通常从官方网站redis.io下载。 - 解压并进入源代码目录。 - 使用`make`命令编译源码。 - 执行`sudo make install`将Redis服务器安装到系统路径。 - 将Redis配置文件`redis.conf`复制到...
Redis 中文文档 Redis 是一个开源的、基于内存的数据结构存储系统,提供了字符串、哈希表、列表、集合、有序集合等多种...本文档为 Redis 的中文文档,全面介绍了 Redis 的各个方面,帮助开发者快速理解和使用 Redis。
这份“redis官方文档中文版”提供了全面的Redis使用指南和技术详解,对于理解和掌握Redis的各项功能和最佳实践至关重要。 文档通常会从以下几个方面进行详细介绍: 1. **Redis简介**:Redis是一个开源(BSD许可)...
Redis Stream本来是计划放在4.0这个大版本中发布(原计划4.2),但是由于确实是个比较重磅的feature,对内核的改动也比较大,目前已经提升到Redis 5.0发布,根据作者Twitter的消息,不出意外,18年上半年我们可以看到...
`redis_cmd.chm`是一个帮助文件,包含了Redis命令的详细信息,而`redis中文API.docx`则可能是PHP Redis扩展的中文API文档,用于指导PHP开发者如何使用这个扩展来调用Redis的各种功能。 1. **Redis命令**: `redis_...
Redis 中文文档 Redis 是一种开源的、基于内存的数据存储系统,可以用作数据库、缓存和消息队列等。以下是 Redis 中文文档的详细知识点: 键空间通知(Key Space Notification) 键空间通知使得客户端可以通过...
在本文档中,我们将详细介绍如何使用Prometheus 2.35.0监控Redis实例,以及如何配置报警机制。 首先,Prometheus 支持两种方式来添加监控目标: 1. 静态配置:这种方式需要手动在Prometheus配置文件中添加每个要...
Redis 是一个开源的、高性能...总之,这份Redis官方中文说明文档是学习Redis不可或缺的资料,无论你是初学者还是经验丰富的开发者,都能从中受益。通过阅读和实践,你将能够熟练地运用Redis来构建高效、可扩展的应用。
包含翻译后的API文档:flink-connector-redis_2.10-1.1.5-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache.flink:flink-connector-redis_2.10:1.1.5; 标签:apache、flink、connector、redis、中文文档...
redis帮助文档之geo