concept

第二章 Redis核心概念与体系结构(Concepts and Architecture of Redis)

1 引言

本章将介绍Redis系统的核心概念和体系结构,分析Redis如何将这些概念应用于不同的应用场景之中,以帮助读者建立一个完整的Redis体系。本章的目的有以下三个:其一,虽然Redis是一个小巧的系统,但是它运用了数据库和分布式系统的许多概念,而且这些概念之间易于混淆,所以,本章会逐一讲解这些概念;其二,Redis的一些特性是可选的,这是为了使得Redis可应用于不同的场景之中。本章会从最简单的应用场景出发,逐步添加可选特性,以帮助读者更好的理解这些特性和概念;其三,我们后续章节会逐一介绍单个功能部件。在此之前建立一个整体上的认知有助于理解各功能部件之间的联系和在整体系统中的位置。

2 客户端/服务器模式

Redis系统工作于客户端/服务器模式,人们常说的Redis是指Redis的服务器端,而往往忽略了Redis客户端。在服务器端,Redis内置支持字符串(String),链表(List),集合(Set),有序集合(Sorted Set),哈希(Hash)等数据类型。Redis还支持位图(Bitmap)和HyperLogLogs数据类型,它们是基于字符串实现的。Redis服务器将这些类型的数据存放在内存中,并针对每一种数据类型提供了不同的操作方法。

Redis客户端集成在应用程序中。目前,Redis为常用编程语言(例如:C/C++,Java,Python等)提供了客户端代码库(Client Library)。所以,开发人员能够很容易的开发出与Redis交互的应用程序。读者可访问Redis客户端列表查看支持的编程语言。我们将在第十三章Redis编程中介绍如何使用Redis客户端代码库编写Redis应用程序。

Redis客户端与服务器端的通信采用了RESP协议(REdis Serialization Protocol)。RESP协议具有易于实现、数据易于解析、可读性好的优点。虽然RESP为Redis系统而设计,但是,它也可以用于其他客户端/服务器模式的系统。在Redis系统中,RESP建立在TCP连接之上,但是,理论上,RESP协议可建立在任意网络协议之上。

Redis客户端和服务器可以运行在同一台服务器上,也可以运行在不同的服务器上。

图一 Redis客户端/服务器模式

图一 Redis客户端/服务器模式。

因为客户端的实现较为简单,我们在接下来的内容中,将重点放在服务器端。

3 Redis服务器端是一个内存Key-Value数据库

在服务器端,Redis是一个Key-Value内存数据库。它将所有的数据以Key-Value的形式存放了内存中。Redis数据库提供多种数据操作,例如,添加数据,删除数据,查询数据等。

将数据放在内存中的好处是服务器可以快速的处理数据,响应客户端的请求,但是,一旦数据库重启,所有的数据将不复存在。为了确保数据的持久性(Data Persistence),Redis提供了可选的数据持久化特性。当数据持久化功能开启时,Redis数据库会将数据写入持久性存储设备(Persistent Storage)中(通常是硬盘)。在重启后,Redis会从持久性设备中重新读取和加载数据。

Redis支持两种数据持久化方式。在RDB(Redis Database Backup)方式下,Redis每隔一段时间会创建一个数据库的快照(a snapshot of database)。这个快照包含了在那个时刻数据库中包含的所有数据。RDB方法非常适用于数据备份,例如,每24小时备份一次数据库。而且,RDB对Redis的性能影响非常小,并且从RDB文件恢复数据的速度非常快。当然,RDB的缺点也很明显,即:当Redis系统出现故障时,Redis系统很可能会丢失数据。因为快照文件仅包含快照创建那个时刻的所有数据。如果系统在快照创建之后出现故障,在该快照创建之后的所有数据更新都不在该快照中,因此,这些数据更新是无法从该快照恢复的。

为了解决这个问题,Redis还支持另一种数据持久化方式,即AOF(Append Only File)。在AOF方法下,Redis将所有的数据更新按照处理顺序存放在AOF文件的末尾。当Redis出现系统故障时,Redis只需重新依次执行AOF文件中的记录即可恢复所有数据。在这种工作方式下,数据丢失的可能性非常小,因为AOF包含了所有数据更新的信息。但是,AOF方法的缺点是AOF文件的大小通常比较大,即使Redis会每隔一段时间重新组织AOF文件,但是,它通常会比RDB文件大许多。当系统出现故障后,使用AOF文件恢复数据的时间较长,因为,Redis需要重新处理所有的历史数据请求(Replay all history)。

另外,开发人员还可以通过下达"SAVE"指令创建一个RDB快照。

图二 Redis服务器端内存数据库结构

图二 Redis服务器端内存数据库结构。

4 Redis支持数据复制(Data Replication)

为了进一步保护数据,提高系统的可靠性(System Availability),Redis支持可选的数据复制服务。在数据复制服务开启的状态下,Redis服务器会启动一个主服务器(Master Instance)和一个或者多个从服务器(称为Replica Instance)。从服务器的个数可由配置参数控制。当主服务器出现故障时,从服务器能“代替”主服务器继续提供服务。数据复制功能和数据持久化功能是相互独立的。换句话说,开发人员可以同时开启这两个功能,或者开启其中任意一个,或者将它们同时关闭。主/从服务器的数据持久化功能也是相互独立的,即可以单独开启主服务器的数据持久化功能,也可以单独开启从服务器的数据持久化功能,或者同时开启。数据持久化的工作原理与上一节描述的内容保持一致。

为了达到更快的响应速度和数据处理速度,主从服务器之间采用异步数据复制(Asynchronous Replication)。当主服务器收到一个数据变化的请求时(例如,客户端插入了新的数据),主服务器会首先应答该请求,然后再将该请求复制给从服务器。主服务器会将数据请求按照处理的顺序发送到从服务器,以确保从服务器按照相同的顺序处理相同的指令,从而保证主服务器与从服务器之间的数据一致。可是当主从服务器之间出现通信故障时,从服务器会尝试与主服务器重新建立连接。当连接重新建立后,从服务器会向主服务器请求部分数据同步,以处理因为断连而丢失的指令和数据。当请求部分数据同步失败时,从服务器会请求全同步。在全同步过程中,主服务器会创建一个数据镜像(a snapshot of all data),发送给从服务器。Redis还支持从服务器与从服务器相连,形成从服务器数据同步链。

 

图三 Redis数据复制原理

图三 Redis数据复制原理。

5 Redis支持数据切分和分布式部署

Redis数据切分技术是将整个数据切分为多份,并将每一份数据放置在不同的Redis实例上(Redis Instance)。这些Redis实例共同提供一个完整的Redis数据库服务。总体上看,数据切分技术(Data Partitioning)为Redis带来了两大好处。其一,因为Redis是内存数据库,将所有数据放在内存中。因此,Redis所能容纳的数据大小受到物理内存大小的限制。如果将数据分散在多个服务器上,能帮助Redis提供更大的数据容量。其二,当数据分散在多个服务器上时,能够同时利用这些服务器的计算资源(CPU、内存、网络等资源),提供更快更高效的服务。

数据切分技术的核心在于如何切分数据。目前,两种流行且简单的算法是按区域切分(Range Partitioning)按照哈希值切分(Hash Partitioning)。区域切分是指数据按照它的Key的值所在的区域切分。例如,假设Key的取值范围为[1, 1000],数据部署在两台服务器上的话,那么,Key在[1, 500]范围内的数据可能被分派在第一台服务器上,而Key在(501, 1000]范围内的数据可能被分派在第二台服务器上。这种方法的好处是实现简单,但是它只能工作于数据具有相同类型的Key的场景下。假设,数据的Key可能是整数,也可能是字符串的话,这种方法是行不通的。哈希切分法能很好的解决这个问题。因为,在数据上运行哈希函数能将不同类型的数据标准化(Normalization)到同一类型上。然后,再根据哈希值采用区域切分,划分数据的分布。哈希切分法实现也很简单。

Redis集群部署结合了上述两种方法。一个Redis集群一共包含16384个哈希槽(Hash Slot)。每个Redis节点分配一定数量的哈希槽。当有新数据创建时,Redis首先计算数据Key的CRC16的值(CRC指Cyclic Redundancy Check,循环冗余校验)。然后,再对其取16384的模,作为该数据应存放的槽位,并将该数据分发到对应的节点上。在这里,CRC16算法被当作哈希函数用,将数据的Key归一为一个整数。

Redis还提供了哈希标签(Hash Tag)特性。哈希标签是Redis集群数据切分算法的一个特例。Redis集群为了方便处理多个Key的操作场景(Multi-Key Operation Scenarios),哈希标签特性能够确保当多个数据的Key被打上相同的哈希标签之后,这些数据能被分发到同一个哈希槽上,被同一个Redis节点处理。

图四展示的是一个三节点的Redis集群。每个节点之间通过Redis Cluster Bus相互通信。Redis节点能够自动检测新节点加入或者节点陷入错误状态。Redis客户端能与任一节点通信。当客户端将请求发送到一个节点,但是该节点不能处理该请求的话,该节点能告知客户端正确的请求节点,因此,客户端能够再次尝试将请求发送给正确的节点。这种实现方法被称为重定向(Redirecting)。

图四 Redis集群部署图

图四 Redis集群部署图。

值得注意的是,Redis集群使用的是在服务器端实现数据切分的方式。在Redis社区中,还有三种常见的实现方式。第一种是在客户端实现数据切分(Client Side Partitioning),即由客户端实现数据切分的算法,并且直接把数据发送到正确的Redis节点。使用这种方法的客户端有Redis-rbPredis。第二种是路径切分查询法(Query Routing)。这种方法是客户端可以向Redis节点查询节点的映射表。在查询后,客户端能够得到正确的请求节点的信息。第三种方法是辅助代理法(Proxy Assisted Partitioning)。在这种方法下,客户端首先将请求发送给一个代理服务器(Proxy Server),然后,再由该代理服务器将请求转发给正确的Redis节点。Redis数据库不支持这种方法,但是,Twitter开发了Twemproxy,使用的就是这种方法。辅助代理法与前两种方法的重要区别在于,辅助代理法是由代理实现数据切分的。这个代理不依赖于Redis的内部实现,它既不是Redis客户端的一部分,也不是Redis服务器端的一部分。因此,使用辅助代理法能够将Redis与其他数据库融合在一起,组成一个混合的数据库。目前,Twemproxy可以同时与Redis和Memcached协同工作。

5 开启数据持久化、数据复制的集群部署

上述的数据持久化,数据复制和集群部署都是相互独立的特性。当他们同时开启时,Redis数据库的部署图如图五所示。Redis数据库保存的数据存放在三个主节点上(Node 1-Master, Node 2-Master和Node 3-Master);由这三个主节点提供数据库服务。每个主节点配置了一个从节点(Node 1-Replica, Node 2-Replica和Node 3-Replica)。在从节点上保存一份主节点的数据拷贝。每个节点都会将数据写入持久化设备中。当节点出现故障时,数据可以从持久化设备从恢复,也可以从从节点恢复。当主节点出现故障时,从节点可被晋升为主节点,继续提供服务。

图五 Redis集群部署全景图

图五 Redis集群部署全景图。

6 总结

本章概括了Redis数据库的基本原理以及多种配置环境下的运行方式。我们将在随后的章节中,逐步讲解每个特性的实现细节。

上一章
下一章

注册用户登陆后可留言

Copyright  2019 Little Waterdrop, LLC. All Rights Reserved.