1. Redis集群简介
1.1 什么是Redis集群
Redis集群是一种通过将多个Redis节点连接在一起以实现高可用性、数据分片和负载均衡的技术。它允许Redis在不同节点上同时提供服务,提高整体性能和可靠性。根据搭建的方式和集群的特性,Redis集群主要有三种模式:主从复制模式(Master-Slave)、哨兵模式(Sentinel)和Cluster模式。
1.2 Redis集群的作用和优势
- 高可用性:Redis集群可以在某个节点发生故障时,自动进行故障转移,保证服务的持续可用。
- 负载均衡:Redis集群可以将客户端请求分发到不同的节点上,有效地分摊节点的压力,提高系统的整体性能。
- 容灾恢复:通过主从复制或哨兵模式,Redis集群可以在主节点出现故障时,快速切换到从节点,实现业务的无缝切换。
- 数据分片:在Cluster模式下,Redis集群可以将数据分散在不同的节点上,从而突破单节点内存限制,实现更大规模的数据存储。
- 易于扩展:Redis集群可以根据业务需求和系统负载,动态地添加或移除节点,实现水平扩展。
通过了解Redis集群的概念和优势,接下来将详细介绍三大集群模式的原理、配置、优缺点以及应用场景。
2. 主从复制模式(Master-Slave)
2.1 主从复制原理
主从复制是Redis的一种基本集群模式,它通过将一个Redis节点(主节点)的数据复制到一个或多个其他Redis节点(从节点)来实现数据的冗余和备份。
主节点负责处理客户端的写 操作,同时从节点会实时同步主节点的数据。客户端可以从从节点读取 数据,实现读写分离,提高系统性能。
在复制的概念中,数据库分为两类,一类是主数据库(master),另一类是从数据库 [1](replica)。主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库。而从数据库一般是只读的 ,并接收主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库
2.2 主从复制配置和实现
在Redis中使用复制功能非常容易,只需要在从数据库的配置文件中加入"slaveof主数据库地址 主数据库端口",主数据库无须进行任何配置。
我们要在一台服务器上启动两个Redis实例,其中一个作为主数据库,另一个作为从数据库,监听不同端口。首先我们不加任何参数来启动一个Redis实例作为主数据库:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_0">$ redis-server</code>
该实例默认监听6379端口。然后加上slaveof参数启动另一个Redis实例作为从数据库,并让其监听6380端口:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_1">$ redis-server --port 6380 --slaveof 127.0.0.1 6379</code>
此时,在主数据库中的任何数据变化都会自动地同步到从数据库中。我们打开redis-cli实例A并连接到主数据库:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_2">$ redis-cli -p 6379</code>
再打开redis-cli实例B并连接到从数据库:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_3">$ redis-cli -p 6380</code>
此时我们使用INFO命令来分别在实例A和实例B中获取replication节点的相关信息:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_4">redis A> INFO replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=1,lag=1
master_repl_offset:1</code>
可以看到,实例A的角色(上面输出中的role)是master,即主数据库,同时已连接的从数据库(上面输出中的connected_slaves)的个数为1。
同样在实例B中获取相应的信息为:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_5">redis B> INFO replication
role:slave
master_host:127.0.0.1
master_port:6379</code>
从这里可以看到,实例B的role是slave,即从数据库,同时其主数据库的IP地址为127.0.0.1,端口号为6379。在实例A中使用SET命令设置一个键的值:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_6">$ redis A> SET foo bar
OK</code>
此时在实例B中就可以获得该值了:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_7">$ redis B> GET foo
"bar"</code>
可以通过设置从数据库的配置文件中的slave-read-only为no以使从数据库可写,但是因为对从数据库的任何更改都不会同步给任何其他数据库,并且一旦主数据库中更新了对应的数据就会覆盖从数据库中的更改,所以通常的场景下不应该设置从数据库可写,以免导致易被忽略的潜在应用逻辑错误。配置多个从数据库的方法也一样,在所有的从数据库的配置文件中都加上 slaveof参数指向同一个主数据库即可。
除了通过配置文件或命令行参数设置slaveof参数,还可以在运行时使用SLAVEOF命令修改:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_9">$ redis> SLAVEOF 127.0.0.1 6379</code>
如果该数据库已经是其他主数据库的从数据库了,SLAVEOF命令会停止和原来数据库的同步转而和新数据库同步。此外对从数据库来说,还可以使用SLAVEOF NO ONE命令来使当前数据库停止接收其他数据库的同步数据并转换成为主数据库。
2.3 主从复制的优缺点
优点:
- 配置简单,易于实现。
- 实现数据冗余,提高数据可靠性。
- 读写分离,提高系统性能。
缺点:
- 主节点故障时,需要手动切换到从节点,故障恢复时间较长。
- 主节点承担所有写操作,可能成为性能瓶颈。
- 无法实现数据分片,受单节点内存限制。
2.4 主从复制场景应用
主从复制模式适用于以下场景:
- 数据备份和容灾恢复:通过从节点备份主节点的数据,实现数据冗余。
- 读写分离:将读操作分发到从节点,减轻主节点压力,提高系统性能。
- 在线升级和扩展:在不影响主节点的情况下,通过增加从节点来扩展系统的读取能力。
总结:主从复制模式适合数据备份、读写分离和在线升级等场景,但在主节点故障时需要手动切换,不能自动实现故障转移。如果对高可用性要求较高,可以考虑使用哨兵模式或Cluster模式。
3. 哨兵模式(Sentinel)
3.1 哨兵模式原理
哨兵模式是在主从复制基础上加入了哨兵节点,实现了自动故障转移 。哨兵节点是一种特殊的Redis节点,它会监控主节点和从节点的运行状态。当主节点发生故障时,哨兵节点会自动从从节点中选举出一个新的主节点,并通知其他从节点和客户端,实现故障转移。
顾名思义,哨兵的作用就是监控Redis系统的运行状况,它的功能包括以下两个。
(1)监控主数据库和从数据库是否正常运行。
(2)当主数据库出现故障时,自动将从数据库转换为主数据库。哨兵是一个独立的进程。
在一个一主多从的Redis系统中,可以使用多个哨兵进行监控任务以保证系统足够稳健,注意,此时不仅哨兵会同时监控主数据库和从数据库,哨兵之间也会互相监控。
3.2 哨兵模式配置和实现
我们采用一主(master)二从(slave)三sentinel的架构模式来做演示
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_10">master ip:127.0.0.1 port:6379
slave1 ip:127.0.0.1 port:6380
slave2 ip:127.0.0.1 port:6381</code>
3.2.1 新建和修改配置文件
1、修改redis.conf配置文件
由于我们采用的是一主二从三sentinel的模式,所以我们需要6个配置文件,拷贝2份redis.conf配置文件,分别命名为redis6380.conf和redis6381.conf,其中修改redis.conf配置文件的如下几个参数:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_11">port 6379
bind 127.0.0.1</code>
修改redis6380.conf配置文件的如下几个参数:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_12">port 6380
bind 127.0.0.1
slaveof 127.0.0.1 6379 // 设置master服务器为6379</code>
同理修改redis6381.conf配置文件
2、创建并修改sentinel.conf
该模式使用了3 sentinel,所以我们需要复制3份sentinel.conf配置文件,并分别命名为sentinel26379.conf,sentinel26479.conf和sentinel26579.conf,其中修改sentinel.conf配置文件中的如下几个参数:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_13">port 26379 // 当前Sentinel服务运行的端口
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 15000</code>
同理,修改另外的两个配置文件。 配置文件说明:
1、**port :**当前Sentinel服务运行的端口
2、**sentinel monitor mymaster 127.0.0.1 6379 2:**Sentinel去监视一个名为mymaster的主redis实例,这个主实例的IP地址为本机地址127.0.0.1,端口号为6379,而将这个主实例判断为失效至少需要2个 Sentinel进程的同意,只要同意Sentinel的数量不达标,自动failover就不会执行
3、**sentinel down-after-milliseconds mymaster 5000:**指定了Sentinel认为Redis实例已经失效所需的毫秒数。当 实例超过该时间没有返回PING,或者直接返回错误,那么Sentinel将这个实例标记为主观下线。只有一个 Sentinel进程将实例标记为主观下线并不一定会引起实例的自动故障迁移:只有在足够数量的Sentinel都将一个实例标记为主观下线之后,实例才会被标记为客观下线,这时自动故障迁移才会执行
4、**sentinel parallel-syncs mymaster 1:**指定了在执行故障转移时,最多可以有多少个从Redis实例在同步新的主实例,在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长
5、**sentinel failover-timeout mymaster 15000:**如果在该时间(ms)内未能完成failover操作,则认为该failover失败
3.2.2 启动服务器
1、分别启动master,slave1,slave2
启动命令分别如下:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_14">redis-server.exe redis.conf
redis-server.exe redis6380.conf
redis-server.exe redis6381.conf</code>
2、分别启动sentinel1,sentinel2,sentinel3
启动命令分别如下:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_15">redis-server.exe sentinel.conf --sentinel
redis-server.exe sentinel26479.conf --sentinel
redis-server.exe sentinel26579.conf --sentinel</code>
3、查看redis服务器状态
4、查看sentinel的状态
3.2.3 redis主从自动failover测试
我们停止Master服务,查看剩余服务的运行状态,如下图:
从上图中可以看出来,master的服务器端口从6379变成了6380,也就是说redis自动的实现了主从切换
4. Cluster模式
4.1 Cluster模式原理
Cluster模式是Redis的一种高级集群模式,它通过数据分片和分布式存储实现了负载均衡和高可用性。**在Cluster模式下,Redis将所有的键值对数据分散在多个节点上。每个节点负责一部分数据,称为槽位。**通过对数据的分片,Cluster模式可以突破单节点的内存限制,实现更大规模的数据存储。
4.2 数据分片与槽位
Redis Cluster将数据分为16384个槽位,每个节点负责管理一部分槽位。当客户端向Redis Cluster发送请求时,Cluster会根据键的哈希值将请求路由到相应的节点。具体来说,Redis Cluster使用CRC16算法计算键的哈希值,然后对16384取模,得到槽位编号。
4.3 Cluster模式配置和实现
配置Redis节点:为每个节点创建一个redis.conf配置文件,并添加如下配置:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_16"># 【注意】节点不一样,IP不一样,记得修改这个bind配置
bind 0.0.0.0
# cluster节点端口号
port 7001
# 配置yes则开启集群功能,此redis实例作为集群的一个节点,否则,它是一个普通的单一的redis实例。
cluster-enabled yes
# 必须配置,否则会出现:waiting for the cluster to join
# 虽然此配置的名字叫"集群配置文件",但是此配置文件不能人工编辑,它是集群节点自动维护的文件,主要用于记录集群中有哪些节点、他们的状态以及一些持久化参数等,方便在重启时恢复这些状态。通常是在收到请求之后这个文件就会被更新。
cluster-config-file nodes_7001.conf
# 节点超时时间
cluster-node-timeout 15000</code>
像这样的配置,一共需要创建6个,我们做一个三主三从的集群。
启动Redis节点:使用如下命令启动6个节点:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_17">$ redis> redis-server redis_7001.conf</code>
创建Redis Cluster:使用Redis命令行工具执行如下命令创建Cluster:
登录后复制
java
<code class="language-plain has-numbering hljs" id="code_id_18">$ redis> redis-cli --cluster create 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 127.0.0.1:7006 --cluster-replicas 1</code>
- cluster-replicas 表示从节点的数量,1代表每个主节点都有一个从节点。
- 验证Cluster模式:向Cluster发送请求,观察请求是否正确路由到相应的节点。
查看集群信息
新建一个命令行窗口,输入以下命令登录:
java
<code class="language-plain has-numbering hljs" id="code_id_19">$ redis-cli -c -p 7001</code>
输入以下Redis命令查看集群信息
java
cluster nodes、cluster info、info replication
cluster nodes查看集群节点
java
<code class="language-plain has-numbering hljs" id="code_id_20">$ 127.0.0.1:7001> cluster nodes
4e404dd64cc2b099d1dfe9ac0f37a6dbf0bd66a9 127.0.0.1:7003@17003 master - 0 1702182050000 3 connected 10923-16383
771c3bb6e12f4979305d7640aaced1b981917c0a 127.0.0.1:7002@17002 master - 0 1702182053140 2 connected 5461-10922
dcdd6db0effa3c08ac2a8b96a7d75bc44f84fb7b 127.0.0.1:7004@17004 slave 771c3bb6e12f4979305d7640aaced1b981917c0a 0 1702182050930 4 connected
6b011cb1ccf1b427ffb431ed0f07aa5e6101f5da 127.0.0.1:7006@17006 slave d9a9044e33276ac07d96ccd35038c8ce4d412755 0 1702182051000 6 connected
d9a9044e33276ac07d96ccd35038c8ce4d412755 127.0.0.1:7001@17001 myself,master - 0 1702182049000 1 connected 0-5460
123b7ca3c4f59762da67e121c279be8cc5a74ee5 127.0.0.1:7005@17005 slave 4e404dd64cc2b099d1dfe9ac0f37a6dbf0bd66a9 0 1702182052037 5 connected</code>
cluster info查看集群信息
java
<code class="language-plain has-numbering hljs" id="code_id_21">$ 127.0.0.1:7001> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:1808
cluster_stats_messages_pong_sent:1727
cluster_stats_messages_sent:3535
cluster_stats_messages_ping_received:1722
cluster_stats_messages_pong_received:1808
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:3535</code>
info replication查看主从信息
java
<code class="language-plain has-numbering hljs" id="code_id_22">127.0.0.1:7001> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=7006,state=online,offset=2705,lag=1
master_replid:1f40986af754e76e8523920a5ae94282d8d9d1e5
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:2705
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:2705</code>
登录7001,尝试写入一个信息
java
<code class="language-plain has-numbering hljs" id="code_id_23">$ redis-cli -c -p 7001</code>
注意,一定要加-c(集群模式)参数,否则会报错:(error) MOVED 15495 127.0.0.1:7003
从上图可以看到,Cluster模式会根据自己的算法,自动选择对应的节点写入数据,并且自动重定向到对应的节点。
4.4 Cluster模式的优缺点
优点:
- 数据分片,实现大规模数据存储。
- 负载均衡,提高系统性能。
- 自动故障转移,提高高可用性。
缺点:
- 配置和管理较复杂。
- 一些复杂的多键操作可能受到限制。
4.5 Cluster模式场景应用
Cluster模式适用于以下场景:
- 大规模数据存储:通过数据分片,突破单节点内存限制。
- 高性能要求场景:通过负载均衡,提高系统性能。
- 高可用性要求场景:通过自动故障转移,确保服务的持续可用。
总结:Cluster模式在提供高可用性的同时,实现了数据分片和负载均衡,适用于大规模数据存储和高性能要求的场景。然而,它的配置和管理相对复杂,且某些复杂的多键操作可能受到限制。
5. 总结
本文详细介绍了Redis的三大集群模式:主从复制、哨兵模式和Cluster模式。每种模式都有其特点和应用场景,具体如下:
- 主从复制模式:适用于数据备份和读写分离场景,配置简单,但在主节点故障时需要手动切换。
- 哨兵模式:在主从复制的基础上实现自动故障转移,提高高可用性,适用于高可用性要求较高的场景。
- Cluster模式:通过数据分片和负载均衡实现大规模数据存储和高性能,适用于大规模数据存储和高性能要求场景。
在实际应用中,可以根据系统的需求和特点选择合适的Redis集群模式,以实现高可用性、高性能和大规模数据存储等目标。