本文是对Redis的集群部署模式一个学习总结,共包括如下章节内容:
- 概述
- 主从集群模式
- “哨兵”集群模式
- Cluster集群模式
- 小结
参考资料:
1、如果需要对Redis的基本知识有所了解,可参考《Redis学习笔记1-基础知识》
,本文中涉及到redis运行环境是基于这篇文章介绍的。
一、概述
Redis提供了单机模式的服务,但在实际的生产环境下,单机模式往往无法满足需求,一般需要集群模式。
Redis有三种集群模式,分别是:
-
主从集群模式
-
“哨兵”模式
-
Cluster集群模式
其中第三种的集群模式是在Redis 3.x以后的版本才增加进来的,也正是因为有这个功能,Redis才真正成为一个分布式的数据库系统。
下面我们来分别介绍这三种模式。
二、主从集群模式
(一)基本概念
Redis的主从集群模式,类似传统的主从数据库方式。在该模式下,可以有一个主数据库(master)节点,多个从数据库(slave)节点。主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库。而从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。
(二)配置
主节点不需要做特殊的配置。
从节点需要在配置文件redis.conf中增加一项配置,如下:
slaveof master_ip master_port
注意,上面的master_ip和master_portip指的是主节点的ip和port,显然这个配置信息的作用是让从节点可以找到主节点。
在测试环境下,也可以不在配置文件中配置,而是在启动从服务器时通过参数指定,如:
src/redis-server --slaveof master_ip master_port
(三)复制机制
Slave启动后,会连接到Master,连接之后,它将主动发送一个SYNC命令。Master收到同步命令后将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次完全同步。而Slave在接收到数据库文件数据之后将其存盘并加载到内存中。
此后,Master继续将所有已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在本次执行这些数据修改命令,从而达到最终的数据同步。 如果Master和Slave之间的链接出现断连现象,Slave可以自动重连Master,但是在连接成功之后,一次完全同步将被自动执行。
(四)主从模式的作用
Redis主从集群模式的作用主要有如下两点
1、数据备份保护:当一个节点数据损坏(物理损坏),因为有备份的节点,所以数据可以恢复。
2、负载均衡:所有客户端都访问一个节点肯定会影响Redis工作效率,有了主从以后,查询操作就可以通过查询从节点来完成。
(五)主从模式的特点
Redis主从集群模式的主要有如下特点:
1、一个Master可以有多个Slave,默认配置下,master节点可以进行读和写,slave节点只能进行读操作,写操作被禁止。不要修改配置让slave节点支持写操作,这没有意义,原因一,写入的数据不会被同步到其他节点;原因二,当master节点修改同一条数据后,slave节点的数据会被覆盖掉。
2、slave节点挂了不影响其他slave节点的读和master节点的读和写,重新启动后会将数据从master节点同步过来。
3、master节点挂了以后,不影响slave节点的读,但Redis不会自动从slave节点选一个master,这样将不再提供写服务,这是个很大的问题,因为这时集群相当于无法提供服务了。要想自动将slave转为master,需要采用“哨兵”集群模式,这个在下面介绍。
三、"哨兵"集群模式
(一)基本概念
上面介绍了Redis的主从集群模式,该模式最大的问题一旦master出问题,整个集群将无法提供写的服务,且不能自动将slave切换为master。所以在实际生产环境中,主从模式是不太常用的。
因此Redis官方提供了“哨兵”(Sentinel)集群模式,Sentinel模式,顾名思义,就是有一个Sentinel系统,来监控Redis集群的运行状态,并根据情况触发相应的动作。Redis Sentinel作为Redis官方提供的集群管理工具,主要有如下功能:
1、监控:能持续监控Redis的主从实例是否正常工作;
2、通知:当被监控的Redis实例出问题时,能通过API通知系统管理员或其他程序;
3、自动故障恢复:如果主实例无法正常工作,Sentinel将启动故障恢复机制把一个从实例提升为主实例,其他的从实例将会被重新配置到新的主实例,且应用程序会得到一个更换新地址的通知。
4、配置提供:因为sentinel保存着Redis主从的信息,所以Redis可以从sentinel那获得所有的配置信息。
Redis Sentinel本身也可以配置成一个集群系统,可以部署多个Sentinel实例来监控同一组Redis实例,当然只有一个Sentinel实例也qiehuanwei可以完成上面的功能,只是一个sentinel实例不具备高可用性,所以一般也会搭建sentinel集群。
虽然sentinel物理上对应的是一个独立的可执行文件,文件名是redis-sentinel,但实质上它只是一个运行在特殊模式下的 Redis 服务器, 也可以在启动一个普通 Redis 服务器时通过给定 --sentinel 选项来启动 Redis Sentinel。
(二)配置
sentinel服务与redis服务一样,也有一个配置文件,配置文件名叫sentinel.conf,与redis服务的redis.conf配置文件都位于redis的根目录下。
启动 Sentinel 实例必须指定相应的配置文件, 系统会使用配置文件来保存 Sentinel 的当前状态, 并在 Sentinel 重启时通过载入配置文件来进行状态还原。如果启动 Sentinel 时没有指定相应的配置文件, 或者指定的配置文件不可写(not writable), 那么 Sentinel 会拒绝启动。我们需要在sentinel.conf配置文件中配置要监听的redis主节点等信息,关于如何配置,这里不再详细介绍。配置好配置文件后,就可以启动sentinel服务了,启动方式如下:
src/redis-sentinel sentinel.conf
或者
src/redis-server sentinel.conf --sentinel
上面两种方式,都将启动一个sentinel实例。
(三)“哨兵”模式的特点
相比主从模式中,sentinel模式最大的特点是:当sentinel发现master节点挂了以后,sentinel就会从slave中重新选举一个master,这样保证Redis集群可持续的提供服务。
下面是对sentinel模式的一些特点的具体说明。
1、sentinel模式是建立在主从模式的基础上的,如果只有一个Redis节点,sentinel就没有任何意义。
2、当master节点挂了以后,sentinel会在slave中选择一个做为master,并修改它们的配置文件,其他slave的配置文件也会被修改,比如slaveof属性会指向新的master。
3、当master节点重新启动后,它将不再是master,而是做为slave接收新的master节点的同步数据。
4、sentinel因为也是一个进程有挂掉的可能,所以sentinel也可以启动多个形成一个sentinel集群。
5、一个sentinel或sentinel集群可以管理多个主从Redis。
6、sentinel最好不要和Redis部署在同一台机器,不然Redis的服务器挂了以后,sentinel也挂了。
7、sentinel监控的Redis集群都会定义一个master名字,这个名字代表Redis集群的master Redis。
8、当使用sentinel模式的时候,客户端就不要直接连接Redis,而是连接sentinel的ip和port,由sentinel来提供具体的可提供服务的Redis实现,这样当master节点挂掉以后,sentinel就会感知并将新的master节点提供给使用者。
sentinel模式基本可以满足一般生产的需求,具备高可用性。但是当数据量过大到一台服务器存放不下的情况时(因为不管是主从模式、还是sentinel模式,主节点上都存储了所有数据),这时主从模式或sentinel模式就不能满足需求了,就需要对存储的数据进行分片,将数据存储到多个Redis实例中,这就是下面要讲的cluster集群模式,即Redis真正的分布式集群系统。
四、Cluster集群模式
(一)基本概念
cluster模式是为了解决单机Redis容量有限的问题,同时也能提高存取速度。Redis-Cluster采用无中心结构,每个节点都保存数据和整个集群状态,每个节点都和其他所有节点连接。其架构图如下:
虽然在cluster模式下,各个结点是互联并且功能等同的,但实际上结点还是分为master和slave两种。一个cluster集群需要多个master节点,每个master节点对应一个或多个slave节点。同主从模式和“哨兵”模式一样,master节点可写可读,slave节点只能读,一旦master出问题,会让slave自动成为master。客户端写数据时,会根据一定的机制将数据写到不同的master上,并从该master复制到对应的slave节点上。
(二)集群机制
Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来决定数据的写入。一个 Redis cluster集群包含 16384 个哈希槽(hash slot)。集群中的每个主节点负责处理一部分哈希槽。 举个例子, 如果集群有三个主节点A,B,C, 会这样分配:
1、节点 A 负责处理 0 号至 5500 号哈希槽。
2、节点 B 负责处理 5501 号至 11000 号哈希槽。
3、节点 C 负责处理 11001 号至 16384 号哈希槽。
客户端写入的数据(键值对)中的键会按照一定的算法来确定这个键属于这16384 个哈希槽(hash slot)中的哪个槽,这样就会对应到由哪个主节点来负责写数据。
这种将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点。 例如:
1、如果用户将新节点 D 添加到集群中, 那么集群只需要将节点 A 、B 、 C 中的某些槽移动到节点 D 就可以了。
2、与此类似, 如果用户要从集群中移除节点 A , 那么集群只需要将节点 A 中的所有哈希槽移动到节点 B 和节点 C , 然后再移除空白(不包含任何哈希槽)的节点 A 就可以了。
因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞, 所以无论是添加新节点还是移除已存在节点, 又或者改变某个节点包含的哈希槽数量, 都不会造成集群下线。
为了使得集群在一部分节点出现故障时,集群仍然可以正常运作, Redis 集群对节点使用了主从复制功能: 集群中的每个节点都有 1 个至 N 个复制品(replica), 其中一个复制品为主节点(master), 而其余的 N-1 个复制品为从节点(slave)。在之前列举的节点 A 、B 、C 的例子中, 如果节点 B 下线了, 那么集群将无法正常运行, 因为集群找不到节点来处理 5501 号至 11000 号的哈希槽。
这时, 假如在创建集群的时候(或者至少在节点 B 下线之前), 我们为主节点 B 添加了从节点 B1 , 那么当主节点 B 下线的时候, 集群就会将 B1 设置为新的主节点, 并让它代替下线的主节点 B , 继续处理 5501 号至 11000 号的哈希槽, 这样集群就不会因为主节点 B 的下线而无法正常运作了。不过如果节点 B 和 B1 都下线的话, Redis 集群还是会停止运作。
下面我们用一个具体例子来看下如何对cluster集群环境进行配置。
(三)配置和创建集群
Redis的cluser集群,当存活的主节点数小于总节点数的一半时,整个集群就无法提供服务了。这样的化,整个最小的cluser集群至少需要3个节点,即3个主节点。但是在试用集群功能时,强烈建议最少配置6个节点,即3个主节点,3个从节点。如果是真实的生产环境,建议1个主节点配置3个从节点。
下面我们以在一台机器上搭建6个节点的cluster集群pe为例来说明,相当于是一个伪分布式的集群环境。如果是在多台机器上,操作类似。当然,也可以通过虚拟机或docker来模拟多台物理机。
假设该机器上已经有单机的Redis环境,具体可参见《Redis学习笔记1-基础知识》
文档。我们在该Redis环境的根目录下创建cluster-test目录,然后在cluster-test目录下创建六个以端口号为名字的子目录(因为是在同一台机器上测试,所以每个redis实例的端口号不能重复), 我们会在每个目录中运行一个 Redis 实例。命令如下:
mkdir cluster-test
cd cluster-test
mkdir 7000 7001 7002 7003 7004 7005
在文件夹 7000 至 7005 中, 各创建一个 redis.conf 文件, 文件的内容在原始的redis.conf文件基础上使用下面的示例配置项:
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
上面的配置项是集群环境下需要在默认的配置文件中最小改动的内容,要记得将各个配置文件中的端口号从 7000改为与文件夹名字相同的端口号。cluster-enabled 选项用于开实例的集群模式, 而 cluster-conf-file 选项则设定了保存节点配置文件的路径, 默认值为 nodes.conf ,节点配置文件无须人为修改, 它由 Redis 集群在启动时创建, 并在有需要时自动进行更新。
需要说明的是,主从节点不需要配置,集群会自动选择。
下面我们来依次启动6个redis实例,如启动第一个实例:
src/redis-server cluster-test/7000/redis.conf
上面的命令一共启动6次,注意每次需要使用不同的端口号值。
现在我们已经有了6个正在运行中的 Redis 实例, 但这6个实例还没有组成一个cluster集群环境。接下来我们需要将这些实例来创建集群, 并为每个节点编写配置文件(会由下面的操作自动生成,不需要手工操作)。
通过使用 Redis 提供的集群命令行工具 redis-trib , 编写节点配置文件的工作可以非常容易地完成。 redis-trib 位于 src 文件夹中, 它是一个 Ruby 程序, 这个程序通过向实例发送特殊命令来完成创建新集群、检查集群、 或者对集群进行重新分片(reshared)等工作。
我们需要执行以下命令来创建集群:
src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
命令的意义如下:
1)给定 redis-trib.rb 程序的命令是 create , 这表示我们希望创建一个新的集群。
2)选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
3)之后跟着的其他参数则是实例的地址列表, 我们希望程序使用这些地址所指示的实例来创建新集群。
简单来说, 以上命令的意思就是让 redis-trib 程序创建一个包含3个主节点和3个从节点的集群。
运行上面命令, redis-trib 会在控制台打印出一份预想中的配置信息, 并提示如果没问题就可以输入 yes , redis-trib 就会将这份配置应用到集群当中。
输入 yes 并按下回车确认之后, 集群就会将配置应用到各个节点, 并连接起(join)各个节点 —— 也即是, 让各个节点开始互相通讯。如果一切正常的话, redis-trib 将输出以下信息:
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
这表示集群中的 16384 个槽都有至少一个主节点在处理, 集群运作正常。
(四)测试集群
我们可以使用redis的命令行程序来测试集群,如下面示例:
$src/redis-cli -c -p 7000
redis 127.0.0.1:7000> set foo bar
-> Redirected to slot [12182] located at 127.0.0.1:7002
OK
redis 127.0.0.1:7002> set hello world
-> Redirected to slot [866] located at 127.0.0.1:7000
OK
redis 127.0.0.1:7000> get foo
-> Redirected to slot [12182] located at 127.0.0.1:7002
"bar"
redis 127.0.0.1:7000> get hello
-> Redirected to slot [866] located at 127.0.0.1:7000
"world"
可以看出,redis cluster集群的特点,它是去中心化的,每个节点都是对等的,连接哪个节点都可以获取和设置数据。redis-cli 对集群的支持是非常基本的, 它总是依靠 Redis 集群来将它转向(redirect)至正确的节点。一个真正的集群客户端应该做得比这更好: 它应该用缓存记录起哈希槽与节点地址之间的映射(map), 从而直接将命令发送到正确的节点上面。
我们也可以故意让某个redis主实例停止,来测试集群是否会自动完成替换操作,这个具体就不再演示。
五、小结
本文介绍了Redis的集群模式,Redis有三种集群模式,主从模式是个基础,但不能满足生产环境的要求;sentinel模式可以满足一般的生产环境,但在大数据场景下就有问题;cluster模式是一个真正的分布式集群系统,可以满足大数据场景下的应用。
网友评论