译者序
序言
前言
致谢
关于本书
代码约定和下载
Github地址:github.com/josiahcarlson/redis-in-action
关于封面插图
第一部分:基础知识
第1章 初识Redis
在其他编程语言里面使用Redis本书只展示 了使用Python 语言编写的示例代码,使用Ruby、Java和JavaScript (Node.js)编写的示例代码可以在这里找到: https://github.com/josiahcarlson/redis-in-action. 使用Spring 框架的读者可以通过查看http://www.springsouorce.org/spring-data/redis来学习如何在Spring框架中使用Redis.
1.1 Redis简介
1.1.1 Redis与其他数据库和软件的对比
表:一些数据库和缓存服务器的特性与功能
名称 | 类型 | 数据存储选项 | 查询类型 | 附加功能 |
---|---|---|---|---|
Redis | 使用内存存储(in-memory)的非关系数据库 | 字符串、列表、集合、散列表、 有序集合 | 每种数据类型都有自己的专属命令,另外还有批量操作( bulk operation)和不完全(partial)的事务支持 | 发布与订阅,主从复制(master/slave replication),持久化,脚本(存储过程,stored procedure) |
memcached | 使用内存存储的键值缓存 | 键值之间的映射 | 创建命令、读取命令、更新命令、删除命令以及其他几个命令 | 为提升性能而设的多线程服务器 |
MySQL | 关系数据库 | 每个数据库可以包含多个表,每个表可以包含多个行: 可以处理多个表的视图 (view);支持空间(spatial)和第三方扩展 |
SELECT、INSERT 、UPDATE、DELETE 、函数、存储过程 | 支持ACID性质(需要使用InnoDB),主从复制和主主复制(master/master replication) |
PostgreSQL | 关系数据库 | 每个数据库可以包含多个表,每个表可以包含多个行:可以处理多个表的视图:支持空间和第三方扩展:支持可定制类型 | SELECT、INSERT 、UPDATE、DELETE、内置函数、自定义的存储过程 | 支持ACID性质,主从复制,由第三方支持的多主复制(multi maser replication) |
MongoDB | 使用硬盘存储(on-disk)的非关系文档存储 | 每个数据库可以包含多个表,每个表可以包含多个无schema ( schema-less )的BSON文档 | 创建命令、读取命令、更新命令、删除命令、条件查询命令等 | 支持map-reduce操作,主从复制,分片,空间索引( spatial index) |
1.1.2 附加特性
在使用类似Redis这样的内存数据库时,一个首先要考虑的问题就是“当服务器被关闭时,服务器存储的数据将何去何从呢?” Redis 拥有两种不同形式的持久化方法,第一种持久化方法为时间点转储( point-in-time dump), 第二种持久化方法将所有修改了数据库的命令都写人一个只追加(append-only )文件里面。
1.1.3 使用Redis的理由
因为对于大部分数据库来说,插入行操作的执行速度非常快(插入行只会在硬盘文件末尾进行写人)。不过,对表里面的行进行更新却是个速度相当慢的操作,因为这种更新除了会引起一次随机读( random read)之外,还可能会引起一次随机写 (random write)。
工具会极大地改变人们解决问题的方式”
1.2 Redis数据结构简介
1.3 Redis,你好!
1.4 寻求帮助
1.5 小结
第2章 使用Redis构建Web应用
从高层次的角度来看, Web应用就是通过HTTP协议对网页浏览器发送的请求进行响应的服务器或者服务( service)。一个Web服务器对请求进行响应的典型步骤如下。
(1)服务器对客户端发来的请求( request) 进行解析。
(2)请求被转发给- 一个预定义的处理器( handler )。
(3)处理器可能会从数据库中取出数据。
(4)处理器根据取出的数据对模板( template)进行渲染( render )。
(5)处理器向客户端返回渲染后的内容作为对请求的响应(response)。
无状态的( stateless ),也就是说,服务器本身不会记录与过往请求有关的任何信息。
2.1 登录和cookie缓存
签名cookie通常会存储用户名,可能还有用户ID、用户最后一次成功登录的时间,以及网站觉得有用的其他任何信息。除了用户的相关信息之外,签名cookie 还包含一个签名,服务器可以使用这个签名来验证浏览器发送的信息是否未经改动(比如将cookie中的登录用户名改成另一个用户)。
令牌cookie 会在cookie里面存储一串随机字节作为令牌,服务器可以根据令牌在数据库中查找令牌的拥有者。
表 签名cookie和令牌cookie的优点与缺点
cookie类型 | 优点 | 缺点 |
---|---|---|
签名cookie | 验证cookie 所需的一切信息都存储在cookie里面。cookie可以包含额外的信息(additional infomation),并且对这些信息进行签名也很容易 | 正确地处理签名很难。很容易忘记对数据进行签名,或者忘记验证数据的签名,从而造成安全漏洞 |
令牌cookie | 添加信息非常容易。cookie 的体积非常小,因此移动终端和速度较慢的客户端可以更快地发送请求 | 需要在服务器中存储更多信息。如果使用的是关系数据库,那么载入和存储cookie的代价可能会很高 |
2.2 使用Redis实现购物车
2.3 网页缓存
在动态生成网页的时候,通常会使用模板语言( templating language )来简化网页的生成操作。需要手写每个页面的日子已经一去不复返——现在的 Web页面通常由包含首部、尾部、侧栏菜单、工具条、内容域的模板生成,有时候模板还用于生成JavaScript。
2.4 数据行缓存
网站是不能对整个促销页面进行缓存的,因为这可能会导致用户看到错误的特价商品剩余数量,但是每次载人页面都从数据库里面取出特价商品的剩余数量的话,又会给数据库带来巨大的压力,并导致我们需要花费额外的成本来扩展数据库。
为了应对促销活动带来的大量负载,我们需要对数据行进行缓存,具体的做法是:编写一个持续运行的守护进程函数,让这个函数将指定的数据行缓存到Redis里面,并不定期地对这些缓存进行更新。
2.5 网页分析
为了让商品浏览次数排行榜能够保持最新,每隔5分钟,代码清单函数就会删除所有排名在20 000名之后的商品,并将删除之后剩余的所有商品的浏览次数减半。
通过记录商品的浏览次数,并定期对记录浏览次数的有序集合进行修剪和分值调整。
2.6 小结
第二部分:核心概念
第3章 Redis命令
3.1 字符串
>>> conn = redis.Redis()
// 在尝试获取一个键的时候,命令将以字符串格式返回被存储的整数。
>>> conn.get ('key')
'11'
3.2 列表
3.3 集合
3.4 散列
3.5 有序集合
3.6 发布与订阅
一般来说, 发布与订阅(又称pub/sub )的特点是订阅者( listener)负责订阅频道( chanmel ),发送者( publisher )负责向频道发送二进制字符串消息( binary string messse )。每当有消息被发送至给定频道时,频道的所有订阅者都会收到消息。我们也可以把频道看作是电台,其中订阅者可以同时收听多个电台,而发送者则可以在任何电台发送消息。
3.7 其他命令
3.7.2 基本的Redis事务
什么是Redis的基本事务
Redis的基本事务( basic transaction) 需要用到MULTI命令和EXEC命令,这种事务可以让一个客户端在不被其他客户端打断的情况下执行多个命令。和关系数据库那种可以在执行的过程中进行回滚( rollback)的事务不同,在Redis里面,被MULTI命令和EXEC命令包围的所有命令会一个接一个地执行, 直到所有命令都执行完毕为止。
当Redis从一个客户端那里接收到MULTI命令时,Redis会将这个客户端之后发送的所有命令都放人到一个队列里面,直到这个客户端发送EXEC命令为止,然后Redis就会在不被打断的情况下,一个接一个地执行存储在队列里面的命令。
3.8 小结
第 4 章 数据安全与性能保障
4.1 持久化选项
Redis提供了两种不同的持久化方法来将数据存储到硬盘里面。一种方 法叫快照( sapshotting ),另一种方法叫只追加文件( append-only file, AOF)
4.1.1 快照持久化
Redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。
一定要记住:如果系统真的发生崩溃,用户将丢失最近一次生成快照之后更改的所有数据。因此,快照持久化只适用于那些即使丢失一部分数据也不会造成问题的应用程序。
4.1.2 AOF持久化
简单来说,AOF持久化会将被执行的写命令写到AOF文件的末尾,以此来记录数据
发生的变化。
Redis 每秒同步一次 AOF文件时的性能和不使用任何持久化特性时的性能相差无几,而通过每秒同步一次 AOF文件,Redis 可以保证,即使出现系统崩溃,用户也最多只会丢失一秒之内产生的数据。
4.1.3重写/压缩 AOF文件
所以随着Redis不断运行,AOF文件的体积也会不断增长,在极端情况下,体积不断增大的AOF文件甚至可能会用完硬盘的所有可用空间。还有另一个问题就是,因为Redis在重启之后需要通过重新执行AOF文件记录的所有写命令来还原数据集,所以如果AOF文件的体积非常大,那么还原操作执行的时间就可能会非常长。
4.2 复制
复制可以让其他服务器拥有一个不断地更新的数据副本,从而使得拥有数据副本的服务器可以用于处理客户端发送的读请求。
4.2.3 主从链
因为Redis 的主服务器和从服务器并没有特别不同的地方,所以从服务器也可以拥有自己的从服务器,并由此形成主从链( master/slave chaining )。
4.3 处理系统故障
如果我们决定要将Redis用作应用程序唯一的数据存储手段,那么就必须确保Redis不会丢失任何数据。跟提供了ACID保证的传统关系数据库不同,在使用Redis为后端构建应用程序的时候,用户需要多做一些工作才能保证数据的一致性。
4.3.1 验证快照文件和AOF文件
检查AOF文件和快照文件的状态,
$ redis-check-aof
Usage: redis-check-aof [--fix] <file.aof>
$ redis-check-dump
Usage: redis-check-dump <dump.rdb>
Linux平台和Unix平台都包含类似shalsum和sha256sum这样的用于生成和验证散列值的命令行程序。
校验和(checksum)与散列值(hash)
CRC校验和对于发现典型的网络传输错误和硬盘损坏非常有帮助,而SHA加密散列值则更擅长于发现文件中的任意错误( arbitrary eror)。简单来说,用户可以翻转文件中任意数量的二进制位,然后通过翻转文件最后64个二进制位的一个子集(subset) 来产生与原文件相同的CRC64校验和。而对于SHA1和SHA256,目前还没有任何已知的方法可以做到这一点。
4.4 Redis事务
Redis的事务和传统关系数据库的事务并不相同。在关系数据库中,用户首先向数据库服务器发送BEGIN,然后执行各个相互一致( consistent )的写操作和读操作,最后,用户可以选择发送COMMIT来确认之前所做的修改,或者发送ROLLBACK来放弃那些修改。
这个问题看上去似乎无足轻重,但实际上无法以一致的形式读取数据将导致某一类型的问题变得难以解决。
延迟执行事务有助于提升性能。这种“一次性发送多个命令,然后等待所有回复出现”的做法通常被称为流水线( pipelining),它可以通过减少客户端与Redis服务器之间的网络通信次数来提升Redis在执行多个命令时的性能。
4.5 非事务型流水线
4.6 关于性能方面的注意事项
试着用redis-benchmark 来了解Redis在自己服务器上的各种性能特征。
4.7 小结
第 5 章 使用Redis构建支持程序
5.1 使用Redis来记录日志
在Linux和Unix的世界中,有两种常见的记录日志的方法。第一种是将日志记录到文件里面,但这种记录日志的方式有时候可能会遇上麻烦:因为每个不同的服务都会创建不同的日志,而这些服务轮换(rlling)日志的机制也各不相同,并且也缺少一种能够方便地聚合所有日志并对其进行处理的常用方法。
syslog服务是第二种常用的日志记录方法,这个服务运行在几乎所有Linux服务器和Unix服务器的514号TCP端口和UDP端口上面。syslog 接受其他程序发来的日志消息,并将这些消息路由(route)至存储在硬盘上的各个日志文件里面。
替换syslog。syslog守护进程(通常是Rsyslogd)替换成sys1og-ng。
syslog的转发功能可以将不同的日志分别存储到同一台服务器的多个文件里面,这对于长时间地记录日志非常有帮助(记得备份)。
5.1.1 最新日志
在构建一个系统的时候,判断哪些信息需要被记录是一件困难的事情:需要记录用户的登人和登出行为吗?需要记录用户修改账号信息的时间吗?还是只记录错误和异常就可以了?
代码清单的1og_recent()
函数展示了将最新志记录到Redis里面的方法:为了维持一个包含最新日志的列表,程序使用LPUSH
命令将日志消息推入一个列表里面。之后,如果我们想要查看已有日志消息的话,那么可以使用LRANGE
命令来取出列表中的消息。
5.2 计数器和统计数据
1.对计数器进行更新
这个计数器以每5秒为一个时间片记录着网站的点击量。
现在我们已经知道怎样记录、获取和清理计数器数据了,接下来要做的似乎就是构建一个界面来展示这些数据了。如果读者有需要的话,可以试试jqplot ( http://www.jqplot.com/ )、Highcharts ( http://www.highcharts.com/)、dygraphs ( http://dygraphs.com/)以及D3 ( http://d3js.org/ ),这几个JavaScript绘图库无论是个人使用还是专业使用都非常合适。
5.2.3 简化统计数据的记录与发现
// Python生成器用作上下文管理器。
start = time.time()
yield // 运行被包裹的代码块。
delta = time.time() - start
5.3 查找IP所属城市以及国家
5.3.1 载入位置表格
为了开发IP所属地查找程序,我们将使用http://dev.maxmind.con/geoip/geolite提供的可免费
休用的IP所属城市数据库作为测试数据。这个数据库包含两个非常重要的文件:一个是GeoLiteCity-Blocks.csv
,它记录了多个IP地址段以及这些地址段所属城市的ID;另一个是GeoLiteCity-Location.csv
,它记录了城市ID与城市名、地区名州名/省名、国家名以及一些我们不会用到的其他信息之间的映射。
5.4 服务的发现与配置
用于连接其他服务以及服务器的配置信息一般都是以配置文件的形式存储在硬盘里面,而这一节要介绍的就是如何将大部分配置信息从文件转移到Redis里面,使得应用程序可以自己完成绝大部分配置工作。
5.4.1 使用Redis存储配置信息
在通常情况下,即使只更新配置中的一个标志, 也会导致更新后的配置文件被强制推送至所有Web服务器,收到更新的服务器可能需要重新载人配置,甚至可能还要重启应用程序服务器。
与其尝试为不断增多的服务写人和维护配置文件,不如让我们直接将配置写人Redis里面。只要将配置信息存储在Redis里面,并编写应用程序来获取这些信息,我们就不用再编写工具来向服务器推送配置信息了,服务器和服务也不用再通过重新载人配置文件的方式来更新配置信息了。
5.4.2 为每个应用程序组件分别配置一个Redis服务器
为了平滑地从单台服务器过渡到多台服务器,用户最好还是为应用程序中的每个独立部分都分别运行一个Redis服务器,比如说,一个专门负责记录日志、一个专门负责记录统计数据、一个专门负责进行缓存、一个专门负责存储cookies等。别忘了,一台机器上是可以运行多个Redis服务器的,只要这些服务器使用的端口号各不同就可以了。除此之外,在一个Redis服务器里面使用多个“数据库”,也可以减少系统管理的工作量。
我们将构建一个函数,该函数可以从一个键里面取出一个JSON编码的配置值,其中,存储配置值的键由服务的类型以及使用该服务的应用程序命名。
def set_config (conn, type, component, config):conn.set ('config:%s:%s' %(type, component), json.dumps(config))
5.5 小结
第 6 章 使用 Redis 构建应用组件
6.1 自动补完
自动补全一般会根据用户已输人的字母来查找所有以已输人字母为开头的单词。
6.1.1 自动补全最近联系人
函数首先获取整个自动补全列表,然后根据联系人的名字是否带有指定的前缀来判断是否对联系人进行过滤,最后返回过滤后的结果。因为这个操作非常简单,所以如果我们发现服务器在计算自动补全列表方面花费了太多时间,那么可以考虑把这个功能交给客户端来实现。
6.1.2 通讯录自动补全
因此,为了对包含非常多元素的列表进行自动补全,我们必须直接在Redis内部完成查找匹配元素的工作。
而当所有成员的分值都是0的时候,成员将按照字符串的二进制顺序进行排序。
那么查找带有abc前缀的单词实际上就是查找介于abbz之后和abd之前的字符串。那么就可以用一个ZRANGE调用来取得所有介于abbz和abd之间的元素。
因为在ASCII编码里面,排在z后面的第一个字符就是左花括号{
,第一个排在a前面的字符就是反引号‘
,
那么可以使用ab‘
作为范围查找的起始元素,并将aba{
用作范围查找的结束元素。
字符集与国际化:但如果你要处理的字符并不仅仅限于a~z范围,那么你还需要解决其他几个问题。首先,你需要想办法把所有字符都转换为字节,常见的做法是使用UTF-8。其次,你需要找出自己想要支持的字符范围,并确保你的字符编码在你所选范围的前面和后面都至少留有一个字符。
6.2 分布式锁
Redis使用WATCH命令来代替对数据进行加锁,因为WATCH只会在数据被其他客户端抢先修改了的情况下通知执行了这个命令的客户端,而不会阻止其他客户端对数据进行修改,所以这个命令被称为乐观锁( optimistic locking )。
6.2.3 使用Redis构建锁
SETNX命令天生就适合用来实现锁的获取功能,这个命令只会在键不存在的情况下为键设置值,而锁要做的就是将一个随机生成的128位UUID设置为键的值,并使用这个值来防止锁被其他进程取得。
6.2.4 细粒度锁
我们考虑的是如何实现与WATCH命令粒度相同的锁——这种锁可以把整个市场都锁住。因为我们是自己动手来构建锁实现,并且我们关心的不是整个市场,而是市场里面的某件商品是否存在,所以我们实际上可以将加锁的粒度变得更细一些。通过只锁住被买卖的商品而不是整个市场,可以减少锁竞争出现的几率并提升程序的性能。
dogpile 效应指的是,执行事务所需的时间越长,就会有越多待处理的事务互相重叠,这种重叠增加了执行单个事务所需的时间,并使得那些带有时间限制的事务失败的几率大幅上升,最终导致所有事务执行失败的几率和进行重试的几率都大幅地上升。
6.2.5 带有超时限制特性的锁
程序将在取得锁之后,调用EXPIRE命令来为锁设置过期时间,使得Redis可以自动删除超时的锁。
6.3 计数信号量
计数信号量是一种锁,它可以让用户限制一项资源最多能够同时被多少个进程访问,通常用于限定能够同时使用的资源数量。
6.4 任务队列
用户可以推迟执行那些需要一段时间才能完成的操作,这种将工作交给任务处理器来执行的做法被称为任务队列(task queue)。现在有很多专门的任务队列软件(如ActiveMQ、RabbitMQ、 Gearman、 Amazon SQS)。
6.4.1 先进先出队列
程序将一封已售出商品邮件推入邮件队列里面的具体步骤。
// 将待发送邮件推入队列里面
comm.rpush('queue:emall', jaon .dumpa (data))// 尝试获取一封待发送邮件
packed = conn.blpop(['queue:emai1'], 30)
我们已经完成了一个用于执行邮件发送工作的任务队列,现在要考虑的问题是,如果要执行的任务不止一种, 我们该怎么办?
1.多个可执行任务
// 尝试从队列里面取出一项待执行任务
packed = conn.blpop([queue], 30)// 执行任务
callbacks[name](*args)
有了这个通用的工作进程,我们就可以把邮件发送程序写成回调函数,并将它和其他回调函数一同传给工作进程使用。
2.任务优先级
假设现在我们需要为任务设置高、中、低3种优先级别,其中:高优先级任务在出现之后会第一时间被执行,而中等优先级任务则会在没有任何高优先级任务存在的情况下被执行。
6.4.2 延迟任务
有几种不同的方法可以为队列中的任务添加延迟性质。
- 在任务信息中包含任务的执行时间,如果工作进程发现任务的执行时间尚未来临,那么它将在短暂等待之后,把任务重新推人队列里面。
- 工作进程使用一个本地的等待列表来记录所有需要在未来执行的任务,并在每次进行while循环的时候,检查等待列表并执行那些已经到期的任务。
- 把所有需要在未来执行的任务都添加到有序集合里面,并将任务的执行时间设置为分值,另外再使用一个进程来查找有序集合里面是否存在可以立即被执行的任务,如果有的话,就从在序集合里面移除那个任务,并将它添加到适当的任务队列里面。
因为无论是进行短暂的等待,还是将任务重新推入队列里面,都会浪费工作进程的时间,所以我们不会采用第一种方法。 此外,因为工作进程可能会因为崩溃而丢失本地记录的所有待执行任务,所以我们也不会采用第二种方法。
每个被延迟的任务都是一个包含4个值的JSON列表,这4个值分别是: 唯一标识符 、处理任务的队列的名字、处理任务的回调函数的名字、传给回调函数的参数。
6.5 消息拉取
两个或多个客户端在互相发送和接收消息的时候,通常会使用以下两种方法来传递消息。第一种方法被称为消息推送( push messaging )。第二种方法被称为消息拉取( pull messaging), 这种方法要求接收者自己去获取存储在某种邮箱( mailbox )里面的消息。
6.5.1 单接收者消息的发送与订阅替代品
但是当我们需要在遇到连接故障的情况下仍然不丢失任何消息的时候,PUBLISH 命令和SUBSCRIBE命令就派不上用场了。
.用户jack451的未读消息队列
mailbox:jack451 list
{'sender' :jll84', 'msg':'Are you coming or not?', 'ts':133066..}
{'sender':'mom65', 'msg':"Did you hear about aunt Elly?", ...}
6.6 使用 Redis 进行文件分发
在构建分布式软件和分布式系统的时候,我们常常需要在多台机器上复制、分发或者处理数据文件,而现有的工具可以以几种不同的方式来完成这些工作:如果服务器需要持续地分发文件,那么常见的做法是使用NFS或者Samba来载入-一个路径(path) 或者驱动器;对于内容会逐渐发生变化的文件来说,常见的做法是使用一款 名为Rsync的软件来尽量减少两个系统之间需要传输的数据量;在需要将多个文件副本分发到多台机器上面的时候,可以使用Bi tTorrent协议来将文件部分地(partial) 分发到多台机器.上面,然后通过让各台机器互相分享自己所拥有的数据来降低服务器的负载。
6.7 小结
第 7 章 基于搜索的应用程序
Redis还特别适用于解决基于搜索的问题(search-based problem) ,这类问题通常需要使用集合以及有序集合的交集、并集和差集操作查找符合指定要求的元素。
7.1 使用 Redis 进行搜索
7.1.1 基本搜索原理
反向索引( inverted indexes)是互联网上绝大部分搜索引擎所使用的底层结构。Redis自带的集合和有序集合都非常适合于处理反向索引。
2.基本搜索操作
要根据两个或多个单词查找文档的话,程序就需要把给定单词集合里面的所有文档都找出来,然后再从中找到那些在所有单词集合里面都出现了的文档。
7.1.2 对搜索结果进行排序
搜索程序在取得多个文档之后,通常还需要根据每个文档的重要性对它们进行排序一-搜索领域把这.问题称为关联度计算问题。
7.2 有序索引
7.3 广告定向
7.4 职位搜索
7.5 小结
第 8 章 构建简单的社交网站
8.1 用户和状态
8.2 定制时间线
8.3 关注者列表以及正在关注列表
8.4 状态消息的发布与删除
8.5 流 API
8.6 小结
第三部分:进阶内容
第 9 章 降低内存占用
9.1 短结构
9.2 分片结构
分片本质上就是基于某些简单的规则将数据划分为更小的部分,然后根据数据所属的部分来决定将数据发送到哪个位置上面。
9.2.1 分片式散列
对散列进行分片首先需要选择-一个方法来对数据进行划分。因为散列本身就存储着一些键,所以程序在对键进行划分的时候,可以把散列存储的键用作其中一个信息源,并使用散列函数为键计算出一个数字散列值。然后程序会根据需要存储的键的总数量以及每个分片需要存储的键数量,计算出所需的分片数量,并使用这个分片数量和键的散列值来决定应该把键存储到哪个分片里面。
对于不是整数的键,shard_key()函数将计算出它们的CRC32校验和。
9.3 打包储存二进制位和字节
9.3.3 对分片字符串进行聚合计算
要弄清楚某个给定用户的关注者都居住在什么地方,程序只需要获取那些关注者的位置信息,然后就像之前对所有用户的位置信息进行聚合计算一样,对那些关注者的位置信息进行聚合计算就可以了。
9.4 小结
第 10 章 扩展 Redis
10.1 扩展读性能
一些Redis用户就发现使用带压缩的SSH隧道( tunnel)进行连接可以明显地降低带宽占用,比如某个公司就曾经使用这种方法,将复制单个从服务器所需的带宽从原来的21Mbit降低为1.8Mbit (http://mng.bz/2ivv)。
加密和压缩开销一般来 说,使用SSH隧道带来的加密开销并不会给服务器造成大的负担,因为2.6GHz主频的英特尔酷睿2单核处理器在只使用单个处理核心的情况下,每秒能够使用AES- 128算法加密180MB数据,而在使用RC4算法的情况下,每秒则可以加密大约350 MB数据。
10.2 扩展写性能和内存容量
10.3 对复杂的查询进行扩展
10.3.2 扩展搜索索引大小
在所有分片上执行search_ get_ values ()函数的方法有两种。第一种是一个接一个地在每个分片上面执行它,第二种是同时在所有分片上面执行它。
在取得所有分片的全部查询结果之后,程序要做的就是重新对这些结果进行排序,从而使得所有查询的结果都变得有序起来。
10.4 小结
第 11 章 Redis 的 Lua 脚本编程
11.1 在不编写 C 代码的情况下添加新功能
11.2 使用 Lua 重写锁和信号量
11.3 移除 WATCH/MULTI/EXEC 事务
11.4 使用 Lua 对列表进行分片
11.5 小结
第四部分:附录
附录A 快速安装指南
A.1 在Debian Linux或者Ubuntu Linux上面安装Redis的方法
A.2 在OS X上面安装Redis的方法
A.3 在Windows上安装Redis的方法
A.4 你好Redis
附录B 其他资源和参考资料
B.1 提供帮助的论坛
B.2 入门议题
B.3 队列函数库以及一些其他用途的函数库
B.4 数据可视化和数据记录
B.5 数据源
B.6 Redis经验分享和相关文章