第一章 初识redis Redis In Action阅读总结
Redis是一个远程内存数据库, 它不仅性能强劲, 而且还具有复制特性以及为解决问题而生的独一无二的数据模型。 Redis提供了5种不同类型的数据结构, 各式各样的问题都可以很自然地映射到这些数据结构上: Redis的数据结构致力于帮助用户解决问题, 而不会像其他数据库那样, 要求用户扭曲问题来适应数据库。除此之外, 通过复制、 持久化(persistence) 和客户端分片(client-side sharding)等特性, 用户可以很方便地将Redis扩展成一个能够包含数百GB数据、 每秒处理上百万次请求的系统。
1.1 Redis 简介
前面对于Redis数据库的描述只说出了一部分真相。Redis是 一个速度非常快的非关系数据库 (non-relational database) , 它可以存储键 (key) 与5种不同类型的值(value) 之间 的映射(mapping) , 可以将存储在内存的键值对数据持久化到硬盘, 可以使用复制特性来扩展读性能, 还可以使用客户端分片来扩展写性能.
1.1.1 Redis与其他数据库和软件的对比
如果你熟悉关系数据库,那么你肯定写过用来关联两个表的数据的 SQL查询。而Redis则属于人们常说的NoSQL数据库或者非关系数据库:Redis不使用表,它的数据库也不会预定义或者 强制去要求用户对Redis存储的不同数据进行关联。
高性能键值缓存服务器memcached也经常被拿来与Redis进行比较:这两者都可用于存储键 值映射, 彼此的性能也相差无几, 但是Redis能够自动以两种不同的方式将数据写入硬盘, 并且Redis除了能存储普通的字符串键之外 , 还可以存储其他4种数据结构, 而memcached只能存储普通的字符串键。这些不同之处使得Redis可以用于解决更为广泛的问题, 并且既可以用 作主数据库(primary database)使用,又可以作为其他存储系统的辅助数据库(auxiliary database) 使用。
1.1.2 附加特性
使用类似 Redis 这样的内存数据库时, 一个首先要考虑的问题就是 “当服务器被关闭时, 服务器存储的数据将何去何从呢? " Redis 拥有两种不同形式的持久化方法, 它们都可以用小而紧凑的格式将存储在内存中的数据写入硬盘:第一种持久化方法为时间点转储 (point-in-time dump), 转储操作既可以在 ”指定时间段内有指定数址的写操作执行 “ 这一条件被满足时执行, 又可以通过调用两条转储到硬盘 (dump-to-disk) 命令中的任何一条来执行;第二种持久化方法将所有修改了数据库的命令都写入一个只追加 (append-only) 文件里面, 用户可以根据数据的重要程度, 将只追加写入设置为从不同步 (sync) 、 每秒同步一次或者每写入一个命令就同步一次。我们将在第 4 章中更加深入地讨论这些持久化选项。
1.1.3 使用Redis的理由
使用Redis而不是memcached来解决问题,不仅可以让代码变得更简短、更易懂、更易维护,而且还可以使代码的运行速度更快(因为用户不需要通过读取数据库来更新数据)。除此之外,在其他许多情况下,Redis的效率和易用性也比关系数据库要好得多。
数据库的一个常见用法是存储长期的报告数据, 并将这些报告数据用作固定时间范围内的聚合数据(aggre gate s)。收集聚合数据的常见做法是:先将各个行插入一个报告表里面, 之后再通过扫描这些行来收集聚合数据, 并根据收集到的聚合数据来更新聚合表中巳有的那些行。之所以 使用插入行的方式来存储,是因为对于大部分数据库来说,插入行操作的执行速度非常快(插入行只会在硬盘文件末尾进行写入)。不过, 对表里面的行进行更新却是一个速度相当慢的操作,因为这种更新除了会引起一次随机读(randomread) 之外,还可能会引起一次随机写(random write )。而在Redis里面, 用户可以直接使用原子的(atomic) INCR命令及其变种来计算聚合数据,并且因为Redis将数据存储在内存里面 , 而且发送给Redis的命令请求并不需要经过典型的查询分析器(parser) 或者查询优化器(optimizer)进行处理,所以对Redis存储的数据执行随机 写的速度总是非常迅速的。
使用Redis而不是关系数据库或者其他硬盘存储数据库, 可以避免写入不必要的临时数 据, 也免去了对临时数据进行扫描或者删除的麻烦 , 并最终改善程序的性能。 虽然上面列举的都是一些简单的例子, 但它们很好地证明了 “工具会极大地改变人们解决问题的方式” 这一点。
1.2 Redis 数据结构简介
正如之前的表 1-1 所示, Redis 可以存储键与 5 种不同数据结构类型之间的映射, 这 5 种数据结构类型分别为 STRING (字符串)、LIST (列表)、 SET (集合)、 HASH (散列)和 ZSET (有序集合)。有一部分 Redis 命令对于这 5 种结构都是通用的, 如 DEL、TYPE、RENAME 等;但也有一部分 Redis 命令只能对特定的一种或者两种结构使用, 第 3 章将对 Redis 提供的命令进行更深入的介绍。
1.2.1 Redis中的字符串
字符串拥有一些和其他键值存储相似的命令,比如GET(获取值)、SET(设置值)和DEL (删除值)。如果读者已经按照附录A中给出的方法安装了Redis, 那么可以根据代码清单1-1展示 的例子,尝试使用redis-cli执行SET、GET和DEL, 表1-3描述了这3个命令的基本用法。
除了能够GET、SET和DEL字符串值之外,Redis还提供了一些可以对字符串的其中一部分内容进行读取和写入的命令,以及一些能对字符串存储的数值执行自增或者自减操作的命令。第3章将对这些命令进行介绍,但是在此之前,我们还有许多基础知识需要了解,下面来看一下Redis的列表及其功能。
1.2.2 Redis 中的列表
Redis对链表结构的支持使得它在键值存储的世界中独树一帜。一个列表结构可以有序的存储多个字符串,和表示字符串时使用的方法一样。
Redis列表可执行的操作和很多编程语言里面的列表操作非常相似:LPUSH命令和RPUSH命令分别用户将元素推入列表的左端和右端;LPOP命令和RPOP命令分别用于从列表的左端和右端弹出元素;LINDEX命令用于获取列表在给定位置上的一个元素;LRANGE命令用于获取列表在给定范围上的所有元素。
1.2.3 Redis的集合
Redis的集合和列表都可以存储多个字符串,它们之间的不同在于,列表可以存储多个相同的字符串,而集合则通过使用散列表 来保证自己存储的每个字符串都是各不相同的(这些散列表只有键,但没有与键相关联的值)。
因为Redis的集合使用无序(unordered)方式存储元素,所以用户不能像使用列表那样,将元素推入集合的某一端, 或者从集合的某一端弹出元素。不过用户可以使用SADD命令将元素添加到集合,或者使用SREM命令从集合里面移除元素。另外还可以通过SISMEMBER命令快速地检查一个元素是否巳经存在 于集合中,或者使用SMEMBERS命令获取集合包含的所有元素(如果集合包含的元素非常多,那么SMEMBERS命令的执行速度可能会很慢,所以请谨慎地使用这个命令)。
跟字符串和列表一样,集合除了基本的添加操作和移除操作之外,还支待很多其他操作,比如SINTER、SUNION、SDIFF这3个命令就可以分别执行常见的交集计算、并集计算和差集计算。
1.2.4 Redis的散列
Redis的散列可以存储多个键值对之间的映射。和字符串一样,散列存储的值既可以是字符串又可以是数字值,并且用户同样可以对散列存储的数字值执行自增操作或者自减操作。图1-4展示了一个包含两个键值对的散列。
1.2.5Redis 的有序集合
有序集合和散列一样,都用于存储键值对:有序集合的键被称为成员(member), 每个成员都是各不相同的;而有序集合的值则被称为分值(score), 分值 必须为浮点数。有序集合是Redis里面唯一一个既可以根据成员访问元素(这一点和散列一样),又可以根据 分值以及分值的排列顺序来访问元素的结构。
1.5 小结
本章希望向读者传达这样一个概念: Redis 是一个可以用来解决问题的工具, 它既拥有其他数据库不具备的数据结构, 又拥有内存存储(这使得 Redis 的速度非常快)、 远程(这使得 Redis 可以与多个客户端和服务器进行连接)、 持久化(这使得服务器可以在重启之后仍然保待重启之前的数据)和可扩展(通过主从复制和分片)等多个特性, 这使得用户可以以熟悉的方式为各种不同的问题构建解决方案。