Redis入门指南(第2版)(txt+pdf+epub+mobi电子书下载)


发布时间:2020-07-20 05:57:35

点击下载

作者:李子骅

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Redis入门指南(第2版)

Redis入门指南(第2版)试读:

前言

Redis如今已经成为Web开发社区中最火热的内存数据库之一,而它的诞生距现在不过才4年。随着Web 2.0的蓬勃发展,网站数据快速增长,对高性能读写的需求也越来越多,再加上半结构化的数据比重逐渐变大,人们对早已被铺天盖地地运用着的关系数据库能否适应现今的存储需求产生了疑问。而Redis的迅猛发展,为这个领域注入了全新的思维。

Redis 凭借其全面的功能得到越来越多的公司的青睐,从初创企业到新浪微博这样拥有着几百台Redis服务器的大公司,都能看到Redis的身影。Redis也是一个名副其实的多面手,无论是存储、队列还是缓存系统,都有它的用武之地。

本书将从Redis的历史讲起,结合基础与实践,带领读者一步步进入Redis的世界。

第2版说明

在本书第1版截稿的时候,加入了Lua脚本功能的Redis 2.6版刚刚发布,此时的Redis 正在逐渐地被国内的开发者所熟知。如今整整两年过去了,Redis也即将发布新的里程碑版本3.0版。在这两年中,Redis 增加了许多优秀的功能,同时也被越来越多的公司所采用与信赖。在写这段文字时,恰好Redis 的作者Salvatore Sanfilippo转述了别人的一句话:“如果把Redis 官网的‘谁在使用 Redis’页面改名为‘谁没在使用 Redis’,那么这个页面的内容一定会精简不少。”虽然是一句玩笑话,但是也从侧面体现出这两年里Redis的飞速发展。而继续编写《Redis入门指南》第2版的最大动力也是希望将Redis发展的成果及时地与广大读者分享,同时也借此感谢大家对本书第1版的积极反馈。

目标读者

本书假定读者是Redis的新手,甚至可能连Redis是什么都没听说过。本书将会详细地介绍Redis是什么以及为什么要使用Redis,旨在能让读者从零开始逐步晋升为一个优秀的Redis开发者。

本书还包含了很多Redis实践方面的知识,对于有经验的Redis开发者,大可以直接跳过已经掌握的内容,只阅读感兴趣的部分。每章的引言都简要介绍了本章要讲解的内容,供读者参考。

本书并不需要读者有任何Redis的背景知识,不过如果读者有Web后端开发经验或Linux系统使用经验,阅读本书将会更加得心应手。

组织结构

第1章介绍了Redis的历史与特性,主要回答两个初学者最关心的问题,即Redis是什么和为什么要使用Redis。

第2章讲解了如何安装和运行Redis。如果你身旁的计算机没有运行Redis,那么一定不要错过这一章,因为本书后面的部分都需要读者最好能一边阅读一边实践,以提高学习效率。本章中还会介绍Redis命令行客户端的使用方法等基础知识,这些都是实践前需要掌握的知识。

第3章介绍了Redis的数据类型。本章讲解的不仅是每个数据类型的介绍和命令的格式,还会着重讲解每个数据类型分别在实践中如何使用。整个第3章会带领读者从零开始,一步步地使用 Redis 构建一个博客系统,旨在帮助读者在学习完本章的内容之后可以直接在自己的项目中上手实践Redis。

第4章引入了一些Redis的进阶知识,比如事务和消息系统等。同样本章还会继续以博客系统为例子,以实践驱动学习。

第5章介绍了如何在各个编程语言中使用 Redis,这些语言包括PHP、Ruby、Python和Node.js。其中讲解每种语言时最后都会以一个有趣的例子作为演示,即使你不了解某些语言,阅读这些例子也能让你收获颇丰。

第6章展示了Redis脚本的强大功能。本章会向读者讲解如何借助脚本来扩展Redis,并且会对脚本一些需要注意的地方(如沙盒、随机结果等)进行着重介绍。

第7章会介绍Redis持久化的知识。Redis持久化包含RDB和AOF两种方式,对持久化的支持是Redis之所以可以用作数据库的必要条件。

第8章详细说明了多个Redis实例的维护方法,包括使用复制实现读写分离、借助哨兵来自动完成故障恢复以及通过集群来实现数据分片。

第9章介绍了Redis安全和协议相关的内容,并向会推荐几个第三方的Redis管理工具。

附录A收录了Redis命令的不同属性,以及属性的特征。

附录B收录了Redis部分配置参数的章节索引。

附录C收录了Redis使用的CRC16实现代码。

排版约定

本书排版使用字体遵从以下约定。

● 等宽字:表示在命令行中输入的命令以及返回结果、程序代码、Redis 的命令(包括命令语句和命令定义)。

● 等宽斜体字(或夹在其中的中文楷体字):表示命令或程序代码中由读者自行替换的参数或变量。

● 等宽粗体字:表示命令行中用户的输入内容、伪代码中的Redis 命令。

● 命令行的输入和输出以如下格式显示:

$ redis-cli PING

PONG

● Redis命令行客户端的输入和输出以如下格式显示:

redis> SET foo bar

OK

● 程序代码以如下格式显示:

var redis = require("redis");

var client = redis.createClient();

//将两个对象 JSON 序列化后存入数据库中

client.mset(

'user:1', JSON.stringify(bob),

'user:2', JSON.stringify(jeff)

);

代码约定

本书的部分章节采用了伪代码来讲解,这种伪代码类似Ruby和PHP,例如:

def hsetnx($key, $field, $value)

$isExists = HEXISTS $key, $field

if $isExists is 0

HSET $key, $field, $value

return 1

else

return 0

其中变量使用$符号标识,Redis命令使用的粗体表示并省略了括号以便于阅读。在命令调用和print等语句中没有$符号的字符串会被当作字符串字面值。

附加文件

本书第5章中每一节都包含了一个完整的程序,通常来讲读者最好自己输入这些代码来加深理解,当然如果要先看到程序的运行结果再开始学习也不失为一个好办法。

这些程序代码都存放在GitHub上(https://github.com/luin/redis-book-assets),可以在GitHub上查看与下载。

致谢

在本书写作的过程中,得到了很多朋友的帮助。请允许我在这里占用少许篇幅,向他们致以诚挚的谢意。

感谢人民邮电出版社的杨海玲老师对本书的支持,没有她的悉心指导,本书就无法顺利完成。

感谢刘亚晨、李欣越、寇祖阳和余尧,他们承担了许多额外的工作,使得我可以全身心地投入到写作中。

感谢所有浏览本书初稿并提出意见和建议的人们:张沈鹏、陈硕实、刘其帅、扈煊、李其超、朱冲宇、王诗吟、黄山月、刘昕、韩重远、李申申、杨海朝、田琪等。感谢你们的支持。

另外还要感谢“宋老师”,是的,就是书中的主人公之一。几年前,我刚创业时,办公场所是和某个教育机构合租的,宋老师是该机构的一名英语老师,同时他也是国内一个知名的嘻哈乐团成员之一。他平日风趣的谈吐带给了我们很多欢乐,伴随我们走过了艰苦的创业初期,而我接触Redis,也正是从这段时间开始的。

最后,感谢我的父母和女朋友马梦妍,你们是我生命中最重要的人,感谢你们的理解和支持。

第1章 简介

Redis是一个开源的、高性能的、基于键值对的缓存与存储系统,通过提供多种键值数据类型来适应不同场景下的缓存与存储需求。同时 Redis 的诸多高层级功能使其可以胜任消息队列、任务队列等不同的角色。

本章将分别介绍Redis的历史和特性,以使读者能够快速地对Redis有一个全面的了解。

1.1 历史与发展

[1]

2008年,意大利的一家创业公司Merzia 推出了一款基于[2]MySQL的网站实时统计系统LLOOGG ,然而没过多久该公司的创始人Salvatore Sanfilippo 便开始对MySQL的性能感到失望,于是他决定亲自为LLOOGG量身定做一个数据库,并于2009年开发完成,这个数据库就是Redis。不过Salvatore Sanfilippo 并不满足只将Redis 用于LLOOGG 这一款产品,而是希望让更多的人使用它,于是在同一年Salvatore Sanfilippo将Redis开源发布,并开始和Redis的另一名主要的代码贡献者Pieter Noordhuis 一起继续着Redis 的开发,直到今天。

Salvatore Sanfilippo自己也没有想到,短短的几年时间,Redis就拥有了庞大的用户群体。Hacker News在2012年发布了一份数据库的[3]使用情况调查 ,结果显示有近12%的公司在使用Redis。国内如新浪微博、街旁和知乎,国外如GitHub、Stack Overflow、Flickr、暴雪和Instagram,都是Redis的用户。

VMware公司从2010年开始赞助Redis的开发,Salvatore Sanfilippo和Pieter Noordhuis也分别于同年的3月和5月加入VMware,全职开发Redis。[4]

Redis的代码托管在GitHub上,开发十分活跃 。2015年4月2日,Redis发布了3.0.0的正式版本。

1.2 特性

作为一款个人开发的系统,Redis究竟有什么魅力吸引了如此多的用户呢?1.2.1 存储结构

有过脚本语言编程经验的读者对字典(或称映射、关联数组)数据结构一定很熟悉,如代码 dict["key"] = "value"中 dict 是一个字典结构变量,字符串"key"是键名,而"value"是键值,在字典中我们可以获取或设置键名对应的键值,也可以删除一个键。

Redis是REmote DIctionary Server(远程字典服务器)的缩写,它以字典结构存储数据,并允许其他应用通过TCP协议读写字典中的内容。同大多数脚本语言中的字典一样,Redis字典中的键值除了可以是字符串,还可以是其他数据类型。到目前为止 Redis 支持的键值数据类型如下:

● 字符串类型

● 散列类型

● 列表类型

● 集合类型

● 有序集合类型

这种字典形式的存储结构与常见的 MySQL等关系数据库的二维表形式的存储结构有很大的差异。举个例子,如下所示,我们在程序中使用post变量存储了一篇文章的数据(包括标题、正文、阅读量和标签):

post["title"] = "Hello World!"

post["content"] = "Blablabla..."

post["views"] = 0

post["tags"] = ["PHP", "Ruby", "Node.js"]

现在我们希望将这篇文章的数据存储在数据库中,并且要求可以通过标签检索出文章。如果使用关系数据库存储,一般会将其中的标题、正文和阅读量存储在一个表中,而将标签存储在另一个表中,然[5]后使用第三个表连接文章和标签表 。需要查询时还得将3个表进行连接,不是很直观。而 Redis 字典结构的存储方式和对多种键值数据类型的支持使得开发者可以将程序中的数据直接映射到 Redis 中,数据在 Redis 中的存储形式和其在程序中的存储方式非常相近。使用 Redis 的另一个优势是其对不同的数据类型提供了非常方便的操作方式,如使用集合类型存储文章标签,Redis可以对标签进行如交集、并集这样的集合运算操作。3.5节会专门介绍如何借助集合运算轻易地实现“找出所有同时属于A标签和B标签且不属于C标签”这样关系数据库实现起来性能不高且较为繁琐的操作。1.2.2 内存存储与持久化

Redis 数据库中的所有数据都存储在内存中。由于内存的读写速度远快于硬盘,因此Redis在性能上对比其他基于硬盘存储的数据库有非常明显的优势,在一台普通的笔记本电脑上,Redis可以在一秒内读写超过10万个键值。

将数据存储在内存中也有问题,比如程序退出后内存中的数据会丢失。不过Redis提供了对持久化的支持,即可以将内存中的数据异步写入到硬盘中,同时不影响继续提供服务。1.2.3 功能丰富

Redis 虽然是作为数据库开发的,但由于其提供了丰富的功能,越来越多的人将其用作缓存、队列系统等。Redis可谓是名副其实的多面手。

Redis 可以为每个键设置生存时间(Time To Live,TTL),生存时间到期后键会自动被删除。这一功能配合出色的性能让Redis可以作为缓存系统来使用,而且由于Redis支持持久化和丰富的数据类型,使其成为了另一个非常流行的缓存系统Memcached的有力竞争者。

讨论 关于 Redis 和 Memcached 优劣的讨论一直是一个热门的话题。在性能上 Redis是单线程模型,而Memcached支持多线程,所以在多核服务器上后者的性能理论上相对更高一些。然而,前面已经介绍过,Redis的性能已经足够优异,在绝大部分场合下其性能都不会成为瓶颈,所以在使用时更应该关心的是二者在功能上的区别。随着Redis 3.0 的推出,标志着Memcached几乎所有功能都成为了Redis的子集。同时,Redis对集群的支持使得Memcached原有的第三方集群工具不再成为优势。因此,在新项目中使用Redis代替Memcached将会是非常好的选择。

作为缓存系统,Redis 还可以限定数据占用的最大内存空间,在数据达到空间限制后可以按照一定的规则自动淘汰不需要的键。

除此之外,Redis 的列表类型键可以用来实现队列,并且支持阻塞式读取,可以很容易地实现一个高性能的优先级队列。同时在更高层面上,Redis 还支持“发布/订阅”的消息模式,可以基于此构建聊

[6]天室 等系统。1.2.4 简单稳定

即使功能再丰富,如果使用起来太复杂也很难吸引人。Redis 直观的存储结构使得通过程序与Redis交互十分简单。在Redis中使用命令来读写数据,命令语句之于Redis就相当于SQL语言之于关系数据库。例如在关系数据库中要获取posts表内id为1的记录的title字段的值可以使用如下SQL语句实现:

SELECT title FROM posts WHERE id = 1 LIMIT 1

相对应的,在Redis中要读取键名为post:1的散列类型键的title字段的值,可以使用如下命令语句实现:

HGET post:1 title

其中HGET就是一个命令。Redis提供了100多个命令(如图1-1所示),听起来很多,但是常用的却只有十几个,并且每个命令都很容易记忆。读完第3章你就会发现Redis的命令比SQL语言要简单很多。图1-1 Redis 官网提供了详细的命令文档

Redis提供了几十种不同编程语言的客户端库,这些库都很好地封装了Redis的命令,使得在程序中与 Redis 进行交互变得更容易。有些库还提供了可以将编程语言中的数据类型直接以相应的形式存储到Redis中(如将数组直接以列表类型存入Redis)的简单方法,使用起来非常方便。

Redis使用C语言开发,代码量只有3万多行。这降低了用户通过修改Redis源代码来使之更适合自己项目需要的门槛。对于希望“榨干”数据库性能的开发者而言,这无疑是一个很大的吸引力。

Redis 是开源的,所以事实上 Redis 的开发者并不止 Salvatore Sanfilippo 和 Pieter Noordhuis。截至目前,有将近100名开发者为Redis贡献了代码。良好的开发氛围和严谨的版本发布机制使得 Redis 的稳定版本非常可靠,如此多的公司在项目中使用了 Redis 也可以印证这一点。

注 释

[1]. http://merzia.com

[2]. http://lloogg.com

[3]. http://news.ycombinator.com/item?id=4833188

[4]. https://github.com/antirez/redis

[5]. 这是一种符合第三范式的设计。事实上还可以使用其他方式来实现标签系统,参阅(http://tagging.pui.ch/post/370277 45720/ tags-database-schemas)以了解更多相关资料。

[6]. Redis 的贡献者之一 Pieter Noordhuis 提供了一个使用该模式开发的聊天室的例子,见https://gist.github.com/348262。

第2章 准备

“纸上得来终觉浅,绝知此事要躬行。”——陆游《冬夜读书示子聿》

学习 Redis 最好的办法就是动手尝试它。在介绍 Redis 最核心的内容之前,本章先来介绍一下如何安装和运行Redis,以及Redis的基础知识,使读者可以在之后的章节中一边学习一边实践。

2.1 安装Redis

安装Redis是开始Redis学习之旅的第一步。在安装Redis前需要了解Redis的版本规则以选择最适合自己的版本,Redis约定次版本号(即第一个小数点后的数字)为偶数的版本是稳定版(如2.8版、3.0版),奇数版本是非稳定版(如2.7版、2.9版),生产环境下一般需要使用稳定版本。本书的内容以 3.0 版为目标编写,同时绝大部分内容也适用于 2.6版和2.8版。对于只在最新版才有的特性(如Cluster集群),本书会做特别说明。2.1.1 在POSIX系统中安装

Redis兼容大部分POSIX系统,包括Linux、OS X和BSD 等,在这些系统中推荐直接下载Redis源代码编译安装以获得最新的稳定版本。Redis最新稳定版本的源代码可以从地址http://download.redis.io/redis-stable.tar.gz下载。

下载安装包后解压即可使用make命令完成编译,完整的命令如下:

wget http://download.redis.io/redis-stable.tar.gz

tar xzf redis-stable.tar.gz

cd redis-stable

make

Redis没有其他外部依赖,安装过程很简单。编译后在Redis源代码目录的src文件夹中可以找到若干个可执行程序,最好在编译后直接执行 make install命令来将这些可执行程序复制到/usr/local/bin目录中以便以后执行程序时可以不用输入完整的路径。

在实际运行Redis前推荐使用 make test命令测试Redis是否编译正确,尤其是在编译一个不稳定版本的Redis时。

提示 除了手工编译外,还可以使用操作系统中的软件包管理器来安装Redis,但目前大多数软件包管理器中的Redis的版本都较古老。考虑到 Redis 的每次升级都提供了对以往版本的问题修复和性能提升,使用最新版本的 Redis 往往可以提供更加稳定的体验。如果希望享受包管理器带来的便利,在安装前请确认您使用的软件包管理器中Redis 的版本并了解该版本与最新版之间的差异。http://redis.io/topics/problems 中列举了一些在以往版本中存在的已知问题。2.1.2 在OS X系统中安装

OS X 下的软件包管理工具Homebrew 和MacPorts 均提供了较新版本的Redis 包,所以我们可以直接使用它们来安装Redis,省去了像其他POSIX系统那样需要手动编译的麻烦。下面以使用Homwbrew安装Redis为例。

1.安装Homebrew

在终端下输入 ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)"即可安装Homebrew。

如果之前安装过 Homebrew,请执行 brew update 来更新 Homebrew,以便安装较新版的Redis。

2.通过Homebrew安装Redis

使用 brew install 软件包名可以安装相应的包,此处执行 brew install redis来安装Redis:

$ brew install redis

==> Downloading

https://downloads.sf.net/project/machomebrew/Bottles/redis-3.0.0.yosemite.bottle.tar.gz

######################################################################## 100.0%

==> Pouring redis-3.0.0.yosemite.bottle.tar.gz

==> Caveats

To have launchd start redis at login:

ln -sfv /usr/local/opt/redis/.plist ~/Library/LaunchAgents

Then to load redis now:

launchctl load ~/Library/LaunchAgents/homebrew.mxcl.redis.plist

Or, if you don't want/need launchctl, you can just run:

redis-server /usr/local/etc/redis.conf

==> Summary

/usr/local/Cellar/redis/3.0.0: 10 files, 1.4M

OS X 系统从Tiger 版本开始引入了launchd 工具来管理后台程序,如果想让Redis 随系统自动运行可以通过以下命令配置launchd:

ln -sfv /usr/local/opt/redis/.plist ~/Library/LaunchAgents

launchctl load ~/Library/LaunchAgents/homebrew.mxcl.redis.plist

通过launchd运行的Redis会加载位于/usr/local/etc/redis.conf的配置文件,关于配置文件会在2.4节中介绍。2.1.3 在Windows中安装[1]

Redis官方不支持Windows。2011年微软 向Redis提交了一个补丁,以使Redis可以在Windows下编译运行,但被Salvatore Sanfilippo拒绝了,原因是在服务器领域上Linux已经得到了广泛的使用,让Redis能在Windows下运行相比而言显得不那么重要。并且Redis使用了如写时复制等很多操作系统相关的特性,兼容 Windows 会耗费太大的精力而影响Redis其他功能的开发。尽管如此微软还是发布了一[2]个可以在Windows运行的Redis分支 ,而且更新相当频繁,截止到本书交稿时,Windows下的Redis版本为2.8。

如果想使用 Windows 学习或测试 Redis 可以通过 Cygwin 软件或虚拟机(如VirtualBox)来完成。Cygwin能够在Windows中模拟Linux系统环境。Cygwin实现了一个 Linux API 接口,使得大部分 Linux 下的软件可以重新编译后在 Windows 下运行。Cygwin还提供了自己的软件包管理工具,让用户能够方便地安装和升级几千个软件包。借助Cygwin,我们可以在Windows上通过源代码编译安装最新版的Redis。

1.安装Cygwin

从Cygwin官方网站(http://cygwin.com)下载setup.exe程序,setup.exe既是Cygwin的安装包,又是Cygwin的软件包管理器。运行setup.exe后进入安装向导。前几步会要求选择下载源、安装路径、代理和下载镜像等,可以根据具体需求选择,一般来说一路点击“Next”即可。之后会出现软件包管理界面,如图2-1所示。图2-1 Cygwin 包管理界面

编译安装Redis需要用到的包有gcc和make,二者都可以在“Devel”分类中找到。在“New”字段中标记为“Skip”的包表示不安装,单击“Skip”切换成需要安装的版本号即可令Cygwin在稍后安装该版本的包。图2-1中所示gcc包的状态为“Keep”是因为作者之前已经安装过该包了,同样如果读者在退出安装向导后还想安装其他软件包,只需要重新运行setup.exe程序再次进入此界面即可。

为了方便使用,我们还可以安装wget(用于下载Redis源代码,也可以手动下载并使用Windows资源管理器将其复制到Cygwin对应的目录中,见下文介绍)和vim(用于修改Redis的源代码使之可以在Cygwin下正常编译)。

之后单击“Next”,安装向导就会自动完成下载和安装工作了。

安装成功后打开Cygwin Terminal 程序即可进入Cygwin 环境,Cygwin 会将Windows中的目录映射到Cygwin中。如果安装时没有更改安装目录,Cygwin环境中的根目录对应的Windows中的目录是C:\cygwin。

2.修改Redis源代码

下载和解压Redis的过程和2.1.1节中介绍的一样,不过在make之前还需要修改Redis的源代码以使其可以在Cygwin下正常编译。

首先编辑src目录下的redis.h文件,在头部加入:

#ifdef CYGWIN

#ifndef SA ONSTACK

#define SA ONSTACK 0x08000000

#endif

#endif

而后编辑src目录下的object.c文件,在头部加入:

#define strtold(a,b) ((long double)strtod((a),(b)))

3.编译Redis

同2.1.1节一样,执行make命令即可完成编译。

注意 Cygwin 环境无法完全模拟Linux 系统,比如Cygwin 的fork 不支持写时复制;另外,Redis官方也并不提供对Cygwin的支持,Cygwin环境只能用于学习Redis。运行Redis的最佳系统是Linux和OS X,官方推荐的生产系统是Linux。

2.2 启动和停止Redis

安装完 Redis 后的下一步就是启动它,本节将分别介绍在开发环境和生产环境中运行Redis的方法以及正确停止Redis的步骤。

在这之前首先需要了解Redis包含的可执行文件都有哪些,表 2-1 中列出了这些程序的名称以及对应的说明。如果在编译后执行了 make install命令,这些程序会被复制到/usr/local/bin目录内,所以在命令行中直接输入程序名称即可执行。表2-1 Redis可执行文件说明

我们最常使用的两个程序是redis-server和redis-cli,其中redis-server是Redis的服务器,启动Redis即运行redis-server;而redis-cli是Redis自带的Redis命令行客户端,是学习Redis的重要工具,2.3节会详细介绍它。2.2.1 启动Redis

启动 Redis 有直接启动和通过初始化脚本启动两种方式,分别适用于开发环境和生产环境。

1.直接启动

直接运行redis-server即可启动Redis,十分简单:

$ redis-server

[5101] 14 Dec 20:58:59.944 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf

[5101] 14 Dec 20:58:59.948 * Max number of open files set to 10032

...

[5101] 14 Dec 20:58:59.949 # Server started, Redis version 2.6.9

[5101] 14 Dec 20:58:59.949 * The server is now ready to accept connections on port 6379[3]

Redis服务器默认会使用6379端口 ,通过--port参数可以自定义端口号:

$ redis-server --port 6380

2.通过初始化脚本启动Redis

在Linux系统中可以通过初始化脚本启动Redis,使得Redis能随系统自动运行,在生产环境中推荐使用此方法运行Redis,这里以Ubuntu和Debian发行版为例进行介绍。在Redis源代码目录的utils文件夹中有一个名为redis_init_script的初始化脚本文件,内容如下:

#!/bin/sh

#

# Simple Redis init.d script conceived to work on Linux systems

# as it does use of the /proc filesystem.

REDISPORT=6379

EXEC=/usr/local/bin/redis-server

CLIEXEC=/usr/local/bin/redis-cli

PIDFILE=/var/run/redis_${REDISPORT}.pid

CONF="/etc/redis/${REDISPORT}.conf"

case "$1" in

start)

if [ -f $PIDFILE ]

then

echo "$PIDFILE exists, process is already running or crashed"

else

echo "Starting Redis server..."

$EXEC $CONF

fi

;;

stop)

if [ ! -f $PIDFILE ]

then

echo "$PIDFILE does not exist, process is not running"

else

PID=$(cat $PIDFILE)

echo "Stopping ..."

$CLIEXEC -p $REDISPORT shutdown

while [ -x /proc/${PID} ]

do

echo "Waiting for Redis to shutdown ..."

sleep 1

done

echo "Redis stopped"

fi

;;

*)

echo "Please use start or stop as first argument"

;;

esac

我们需要配置Redis的运行方式和持久化文件、日志文件的存储位置等,具体步骤如下。(1)配置初始化脚本。首先将初始化脚本复制到/etc/init.d 目录中,文件名为 redis_端口号,其中端口号表示要让Redis监听的端口号,客户端通过该端口连接Redis。然后修改脚本第6行的REDISPORT变量的值为同样的端口号。(2)建立需要的文件夹。建立表2-2中列出的目录。表2-2 需要建立的目录及说明(3)修改配置文件。首先将配置文件模板(见 2.4 节介绍)复制到/etc/redis 目录中,以端口号命名(如“6379.conf”),然后按照表2-3对其中的部分参数进行编辑。表2-3 需要修改的配置及说明

现在就可以使用/etc/init.d/redis_端口号start来启动Redis了,而后需要执行下面的命令使Redis随系统自动启动:

$ sudo update-rc.d redis_端口号 defaults2.2.2 停止Redis

考虑到 Redis 有可能正在将内存中的数据同步到硬盘中,强行终止 Redis 进程可能会导致数据丢失。正确停止Redis的方式应该是向Redis发送SHUTDOWN命令,方法为:

$ redis-cli SHUTDOWN

当Redis收到SHUTDOWN命令后,会先断开所有客户端连接,然后根据配置执行持久化,最后完成退出。

Redis可以妥善处理 SIGTERM信号,所以使用 kill Redis 进程的 PID也可以正常结束Redis,效果与发送SHUTDOWN命令一样。

2.3 Redis命令行客户端

还记得我们刚才编译出来的redis-cli程序吗?redis-cli(Redis Command Line Interface)是Redis自带的基于命令行的Redis客户端,也是我们学习和测试Redis的重要工具,本书后面会使用它来讲解Redis各种命令的用法。

本节将会介绍如何通过redis-cli向Redis发送命令,并且对Redis命令返回值的不同类型进行简单介绍。2.3.1 发送命令

通过redis-cli向Redis发送命令有两种方式,第一种方式是将命令作为redis-cli的参数执行,比如在2.2.2节中用过的 redis-cli SHUTDOWN。redis-cli执行时会自动按照默认配置(服务器地址为127.0.0.1,端口号为6379)连接Redis,通过-h和-p参数可以自定义地址和端口号:

$ redis-cli -h 127.0.0.1 -p 6379

Redis提供了PING命令来测试客户端与Redis的连接是否正常,如果连接正常会收到回复PONG。如:

$ redis-cli PING

PONG

第二种方式是不附带参数运行 redis-cli,这样会进入交互模式,可以自由输入命令,例如:

$ redis-cli

redis 127.0.0.1:6379> PING

PONG

redis 127.0.0.1:6379> ECHO hi

"hi"

这种方式在要输入多条命令时比较方便,也是本书中主要采用的方式。为了简便起见,后文中我们将用 redis>表示 redis 127.0.0.1:6379>。2.3.2 命令返回值

在大多数情况下,执行一条命令后我们往往会关心命令的返回值,如 1.2.4 节中的HGET命令的返回值就是我们需要的指定键的title字段的值。命令的返回值有5种类型,对于每种类型redis-cli的展现结果都不同,下面分别说明。

1.状态回复

状态回复(status reply)是最简单的一种回复,比如向 Redis 发送 SET 命令设置某个键的值时,Redis会回复状态OK表示设置成功。另外之前演示的对PING命令的回复PONG也是状态回复。状态回复直接显示状态信息,如:

redis> PING

PONG

2.错误回复

当出现命令不存在或命令格式有错误等情况时 Redis 会返回错误回复(error reply)。错误回复以(error)开头,并在后面跟上错误信息。如执行一个不存在的命令:

redis> ERRORCOMMEND

(error) ERR unknown command 'ERRORCOMMEND'

在2.6版本时,错误信息均是以“ERR”开头,而在2.8版以后,部分错误信息会以具体的错误类型开头,如:

redis> LPUSH key 1

(integer) 1

redis> GET key

(error) WRONGTYPE Operation against a key holding the wrong kind of value

这里错误信息开头的“WRONGTYPE”就表示类型错误,这个改进使得在调试时能更容易地知道遇到的是哪种类型的错误。

3.整数回复

Redis 虽然没有整数类型,但是却提供了一些用于整数操作的命令,如递增键值的INCR命令会以整数形式返回递增后的键值。除此之外,一些其他命令也会返回整数,如可以获取当前数据库中键的数量的 DBSIZE命令等。整数回复(integer reply)以(integer)开头,并在后面跟上整数数据:

redis> INCR foo

(integer) 1

4.字符串回复

字符串回复(bulk reply)是最常见的一种回复类型,当请求一个字符串类型键的键值或一个其他类型键中的某个元素时就会得到一个字符串回复。字符串回复以双引号包裹:

redis> GET foo

"1"

特殊情况是当请求的键值不存在时会得到一个空结果,显示为(nil)。如:

redis> GET noexists

(nil)

5.多行字符串回复

多行字符串回复(multi-bulk reply)同样很常见,如当请求一个非字符串类型键的元素列表时就会收到多行字符串回复。多行字符串回复中的每行字符串都以一个序号开头,如:

redis> KEYS *

1) "bar"

2) "foo"

提示 KEYS命令的作用是获取数据库中符合指定规则的键名,由于读者的Redis中还没有存储数据,所以得到的返回值应该是(empty list or set)。3.1 节会具体介绍KEYS命令,此处读者只需了解多行字符串回复的格式即可。

2.4 配置

2.2.1 节中我们通过 redis-server 的启动参数 port 设置了 Redis 的端口号,除此之外Redis还支持其他配置选项,如是否开启持久化、日志级别等。由于可以配置的选项较多,通过启动参数设置这些选项并不方便,所以 Redis 支持通过配置文件来设置这些选项。启用配置文件的方法是在启动时将配置文件的路径作为启动参数传递给redis-server,如:

$ redis-server /path/to/redis.conf

通过启动参数传递同名的配置选项会覆盖配置文件中相应的参数,就像这样:

$ redis-server /path/to/redis.conf --loglevel warning

Redis提供了一个配置文件的模板redis.conf,位于源代码目录的根目录中。

除此之外还可以在Redis 运行时通过 CONFIG SET 命令在不重新启动Redis 的情况下动态修改部分Redis配置。就像这样:

redis> CONFIG SET loglevel warning

OK

并不是所有的配置都可以使用 CONFIG SET命令修改,附录B 列出了哪些配置能够使用该命令修改。同样在运行的时候也可以使用 CONFIG GET 命令获得Redis 当前的配置情况,如:

redis> CONFIG GET loglevel

1) "loglevel"

2) "warning"

其中第一行字符串回复表示的是选项名,第二行即是选项值。

2.5 多数据库

第1章介绍过Redis是一个字典结构的存储服务器,而实际上一个Redis实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中。这与我们熟知的在一个关系数据库实例中可以创建多个数据库类似,所以可以将其中的每个字典都理解成一个独立的数据库。

每个数据库对外都是以一个从0开始的递增数字命名,Redis默认支持16个数据库,可以通过配置参数databases来修改这一数字。客户端与Redis建立连接后会自动选择0号数据库,不过可以随时使用SELECT命令更换数据库,如要选择1号数据库:

redis> SELECT 1

OK

redis [1]> GET foo

(nil)

然而这些以数字命名的数据库又与我们理解的数据库有所区别。首先 Redis 不支持自定义数据库的名字,每个数据库都以编号命名,开发者必须自己记录哪些数据库存储了哪些数据。另外 Redis 也不支持为每个数据库设置不同的访问密码,所以一个客户端要么可以访问全部数据库,要么连一个数据库也没有权限访问。最重要的一点是多个数据库之间并不是完全隔离的,比如FLUSHALL命令可以清空一个Redis实例中所有数据库中的数据。综上所述,这些数据库更像是一种命名空间,而不适宜存储不同应用程序的数据。比如可以使用0号数据库存储某个应用生产环境中的数据,使用1号数据库存储测试环境中的数据,但不适宜使用0号数据库存储A应用的数据而使用1号数据库存储B应用的数据,不同的应用应该使用不同的Redis实例存储数据。由于Redis非常轻量级,一个空Redis实例占用的内存只有1MB左右,所以不用担心多个Redis实例会额外占用很多内存。

注 释

[1]. 微软开放技术有限公司(Microsoft Open Technologies Inc.),专注于参与开源项目、开放标准工作组以及提出倡议。

[2]. https://github.com/MSOpenTech/Redis

[3]. 6379 是手机键盘上MERZ对应的数字,MERZ是一名意大利歌女的名字。

第3章 入门

学会如何安装和运行Redis,并了解Redis的基础知识后,本章将详细介绍Redis的5种主要数据类型及相应的命令,带领读者真正进入 Redis 的世界。在学习的时候,手边打开一个 redis-cli 程序来跟着一起输入命令将会极大地提高学习效率。尽管在目前多数公司和团队的Redis的应用是以缓存和队列为主。

在之后的章节中你会遇到两个学习伙伴:小白和宋老师。小白是一个标准的极客,最近刚开始他的 Redis 学习之旅,而他大学时的计算机老师宋老师恰好对 Redis 颇有研究,于是就顺理成章地成为了小白的私人Redis教师。这不,小白想基于Redis开发一个博客,于是找到宋老师,向他请教。在本章中宋老师会向小白介绍 Redis 最核心的内容——数据类型,从他们的对话中你一定能学到不少知识!

3.2节到3.6节这5节将分别介绍Redis的5种数据类型,其中每节都是由4个部分组成,依次是“介绍”、“命令”、“实践”和“命令拾遗”。“介绍”部分是对数据类型的概述,“命令”部分会对“实践”部分将用到的命令进行介绍,“实践”部分会讲解该数据类型在开发中的应用方法,“命令拾遗”部分会对该数据类型其他比较有用的命令进行补充介绍。

3.1 热身

在介绍 Redis 的数据类型之前,我们先来了解几个比较基础的命令作为热身,赶快打开redis-cli,跟着样例亲自输入命令来体验一下吧!

1.获得符合规则的键名列表

KEYS pattern

pattern支持glob风格通配符格式,具体规则如表3-1所示。表3-1 glob 风格通配符规则

现在Redis中空空如也(如果你从第2章开始就一直跟着本书的进度输入命令,此时数据库中可能还会有个foo键),为了演示KEYS命令,首先我们得给Redis加点料。使用SET命令(会在3.2节介绍)建立一个名为bar的键:

redis> SET bar 1

OK

然后使用 KEYS *就能获得Redis中所有的键了(当然由于数据库中只有一个bar键,所以 KEYS ba*或者 KEYS bar 等命令都能获得同样的结果):

redis> KEYS *

1) "bar"

注意 KEYS命令需要遍历Redis中的所有键,当键的数量较多时会影响性能,不建议在生产环境中使用。

提示 Redis不区分命令大小写,但在本书中均会使用大写字母表示Redis 命令。

2.判断一个键是否存在

EXISTS key

如果键存在则返回整数类型1,否则返回0。例如:

redis> EXISTS bar

(integer) 1

redis> EXISTS noexists

(integer) 0

3.删除键

DEL key [key …]

可以删除一个或多个键,返回值是删除的键的个数。例如:

redis> DEL bar

(integer) 1

redis> DEL bar

(integer) 0

第二次执行DEL命令时因为bar键已经被删除了,实际上并没有删除任何键,所以返回0。

技巧 DEL 命令的参数不支持通配符,但我们可以结合Linux的管道和 xargs命令自己实现删除所有符合规则的键。比如要删除所有以“user:”开头的键,就可以执行redis-cli KEYS "user:*" | xargs redis-cli DEL。另外由于 DEL 命令支持多个键作为参数,所以还可以执行 redis-cli DEL `redis-cli KEYS "user:*"`来达到同样的效果,但是性能更好。

4.获得键值的数据类型

TYPE key

TYPE命令用来获得键值的数据类型,返回值可能是string(字符串类型)、hash(散列类型)、list(列表类型)、set(集合类型)、zset(有序集合类型)。例如:

redis> SET foo 1

OK

redis> TYPE foo

string

redis> LPUSH bar 1

(integer) 1

redis> TYPE bar

list

LPUSH命令的作用是向指定的列表类型键中增加一个元素,如果键不存在则创建它, 3.4节会详细介绍。

3.2 字符串类型

作为一个爱造轮子的资深极客,小白每次看到自己博客最下面的[1]“Powered by WordPress” 都觉得有些不舒服,终于有一天他下定决心要开发一个属于自己的博客。但是用腻了MySQL数据库的小白总想尝试一下新技术,恰好上次参加Node Party时听人介绍过 Redis 数据库,便想着趁机试一试。可小白只知道 Redis 是一个键值对数据库,其他的一概不知。抱着试一试的态度,小白找到了自己大学时教计算机的宋老师,一问之下欣喜地发现宋老师竟然对Redis颇有研究。宋老师有感于小白的好学,决定给小白开个小灶。

小白:

宋老师您好,我最近听别人介绍过 Redis,当时就对它很感兴趣。恰好最近想开发一个博客,准备尝试一下它。有什么能快速学会Redis的方法吗?

宋老师笑着说:

心急吃不了热豆腐,要学会 Redis就要先掌握 Redis的键值数据类型和相关的命令,这些内容是 Redis的基础。为了让你更全面地了解 Redis的每种数据类型,接下来我会先讲解如何将Redis作为数据库使用,但是实际上 Redis可不只是数据库这么简单,更多的公司和团队将 Redis用作缓存和队列系统,而这部分内容等你掌握了Redis的基础后我会再进行介绍。作为开始,我先来讲讲Redis中最基本的数据类型——字符串类型。3.2.1 介绍

字符串类型是 Redis 中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据。你可以用其存储用户的邮箱、JSON 化的对象甚至是一张图片。一个字符串类型键允许存储的数据的最大容量[2]是512 MB 。

字符串类型是其他4种数据类型的基础,其他数据类型和字符串类型的差别从某种角度来说只是组织字符串的形式不同。例如,列表类型是以列表的形式组织字符串,而集合类型是以集合的形式组织字符串。学习过本章后面几节后相信读者对此会有更深的理解。3.2.2 命令

1.赋值与取值

SET key value

GET key

SET和GET是Redis中最简单的两个命令,它们实现的功能和编程语言中的读写变量相似,如 key = "hello"在Redis中是这样表示的:

redis> SET key hello

OK

想要读取键值则更简单:

redis> GET key

"hello"

当键不存在时会返回空结果。

为了节约篇幅,同时避免读者过早地被编程语言的细节困扰,本书大部分章节将只使用redis-cli进行命令演示(必要的时候会配合伪代码),第5章会专门介绍在各种编程语言(PHP、Python、Ruby和Node.js)中使用Redis的方法。

不过,为了能让读者提前对 Redis 命令在实际开发时的用法有一个直观的体会,这里会先使用 PHP 实现一个 SET/GET命令的示例网页:用户访问示例网页时程序会通过 GET命令判断Redis中是否存储了用户的姓名,如果有则直接将姓名显示出来(如图3-1所示),如果没有则会提示用户填写(如图 3-2 所示),用户单击“提交”按钮后程序会使用 SET命令将用户的姓名存入到Redis中。图3-1 设置过姓名时的页面图3-2 没有设置过姓名时的页面

代码如下:

//加载 Predis 库的自动加载函数

require './predis/autoload.php';

//连接 Redis

$redis= new Predis\Client(array(

'host' => '127.0.0.1',

'port' => 6379

));

//如果提交了姓名则使用 SET 命令将姓名写入到 Redis 中

if ($_GET['name']) {

$redis->set('name', $_GET['name']);

}

//通过 GET 命令从 Redis 中读取姓名

$name = $redis->get('name');

?>

我的第一个Redis程序

您的姓名是:

您还没有设置姓名。


更改姓名

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载