一、Redis集群概述
1)Redis 主从复制
到 目前 为止,我们所学习的 Redis 都是 单机版 的,这也就意味着一旦我们所依赖的 Redis 服务宕机了,我们的主流程也会受到一定的影响,这当然是我们不能够接受的。
所以一开始我们的想法是:搞一台备用机。这样我们就可以在一台服务器出现问题的时候切换动态地到另一台去:
幸运的是,两个节点数据的同步我们可以使用 Redis 的 主从同步 功能帮助到我们,这样一来,有个备份,心里就踏实多了。
2)Redis 哨兵
后来因为某种神秘力量,Redis 老会在莫名其妙的时间点出问题 (比如半夜 2 点),我总不能 24 小时时刻守在电脑旁边切换节点吧,于是另一个想法又开始了:给所有的节点找一个 "管家",自动帮我监听照顾节点的状态并切换:
这大概就是 Redis 哨兵 (Sentinel) 的简单理解啦。什么?管家宕机了怎么办?相较于有大量请求的 Redis 服务来说,管家宕机的概率就要小得多啦.. 如果真的宕机了,我们也可以直接切换成当前可用的节点保证可用..
3)Redis 集群化
好了,通过上面的一些解决方案我们对 Redis 的 稳定性 稍微有了一些底气了,但单台节点的计算能力始终有限,所谓人多力量大,如果我们把 多个节点组合 成 一个可用的工作节点,那就大大增加了 Redis 的 高可用、可扩展、分布式、容错 等特性:
二、主从复制
主从复制,是指将一台 Redis 服务器的数据,复制到其他的Redis服务器。前者称为 主节点 (master/leader),后者称为 从节点(slave/follower) ;数据的复制是单向的,只能由主节点到从节点。 Master以写为主,Slave 以读为主。 默认情况下,每台Redis服务器都是主节点; 且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点
主从复制主要的作用
- 数据冗余: 主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
- 故障恢复: 当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复 (实际上是一种服务的冗余)。
- 负载均衡: 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务 (即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点),分担服务器负载。尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
- 高可用基石: 除了上述作用以外,主从复制还是哨兵和集群能够实施的 基础,因此说主从复制是 Redis 高可用的基础。
一般来说,要将 Redis 运用于工程项目中,只使用一台 Redis 是万万不能的(宕机),原因如下:
1、从结构上,单个 Redis 服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大;
2、从容量上,单个 Redis 服务器内存容量有限,就算一台 Redis 服务器内存容量为 256G,也不能将所有 内存用作 Redis 存储内存,一般来说,单台 Redis 最大使用内存不应该超过 20G。
比如:电商网站上的商品,一般都是一次上传,无数次浏览的,也就是"多读少写"。
对于这种场景,我们可以使用这种架构:主从复制,读写分离。一个网站 80% 的情况下都是在进行读操作,为了减缓服务器的压力,一般都会配置多态服务器(一主二从)。 只要在公司中,主从复制就是必须要使用的,因为在真实的项目中不可能单机使用 Redis。
1)快速体验(这里条件不允许,就是用单机多服务进行测试)
① 环境配置
只配置从库,不用配置主库!
127.0.0.1:6379> info replication # 查看当前库的信息 # Replication role:master # 角色 master connected_slaves:0 # 没有从机 master_replid:b63c90e6c501143759cb0e7f450bd1eb0c70882a master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0
复制3个配置文件,然后修改对应的信息:
- 端口
- pid 名字
- log 文件名字
- dump.rdb 名字
启动我们的3个redis服务器:
② 建立复制
我们在 6380、6381 端口的节点中执行 slaveof 命令,使之变为从节点:
# 成为本地 6379 端口实例的从节点 127.0.0.1:6380> SLAVEOF 127.0.0.1 6379 OK
如果两个都配置完了,就是有两个从机的
真实的从主配置应该在配置文件中配置,这样的话是永久的,我们这里使用的是命令,暂时的!
③ 效果测试
主机可以写,从机不能写只能读。主机中的所有信息和数据,都会自动被从机保存!
主机写:
从机只能读取内容!
测试:主机断开连接,从机依旧连接到主机的,但是没有写操作,这个时候,主机如果回来了,从机依 旧可以直接获取到主机写的信息!
如果是使用命令行,来配置的主从,这个时候如果重启了,就会变回主机!只要变为从机,立马就会从 主机中获取值!
2)复制原理
Slave 启动成功连接到 master 后会发送一个 sync 同步命令
Master 接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行 完毕之后,master 将传送整个数据文件到 slave,并完成一次完全同步。
全量复制:而 slave 服务在接收到数据库文件数据后,将其存盘并加载到内存中。
增量复制:Master 继续将新的所有收集到的修改命令依次传给 slave,完成同步
但是只要是重新连接 master,一次完全同步(全量复制)将被自动执行! 我们的数据一定可以在从机中 看到!
3)层层链路
上一个M链接下一个 S!
这时候也可以完成我们的主从复制!
4)主机挂了怎么办?
如果主机断开了连接,我们可以使用 SLAVEOF no one 让自己变成主机!其他的节点就可以手动连 接到最新的这个主节点(手动)!如果这个时候老大修复了,那就重新连接!
很明显这是一个愚蠢的方法。当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工 干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑 哨兵模式。Redis 从2.8开始正式提供了 Sentinel(哨兵) 架构来解决这个问题。
所以下面我们要学习哨兵模式(自动选举老大的模式)
三、哨兵模式
哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独 立运行。其原理是 哨兵通过发送命令,等待 Redis 服务器响应,从而监控运行的多个 Redis 实例。
这里的哨兵有两个作用
- 通过发送命令,让 Redis 服务器返回监控其运行状态,包括主服务器和从服务器。
- 当哨兵监测到 master 宕机,会自动将 slave 切换成 master ,然后通过发布订阅模式通知其他的从服 务器,修改配置文件,让它们切换主机
然而一个哨兵进程对 Redis 服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。 各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
假设主服务器宕机,哨兵 1 先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认 为主服务器不可用,这个现象成为 主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一 定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行 failover [故障转移]操作。 切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为 客观下线。
1)快速体验
① 创建主从节点配置文件并启动
复制三份 redis.conf 配置文件分别命名为 redis-6379.conf、redis-6380.conf、redis-6381.conf 分别作为 1
个主节点和 2
个从节点的配置文件。
打开 .conf 配置文件,分别添加修改以下配置:
#主机:redis-6379.conf port 6379
bind 0.0.0.0 pidfile /var/run/redis_6379.pid logfile "6379.log" dbfilename "dump-6379.rdb" #从机:redis-6380.conf port 6380
bind 0.0.0.0 pidfile /var/run/redis_6380.pid logfile "6380.log" dbfilename "dump-6380.rdb" slaveof 127.0.0.1 6379 # 配置主机 #从机:redis-6381.conf port 6381
bind 0.0.0.0 pidfile /var/run/redis_6381.pid logfile "6381.log" dbfilename "dump-6381.rdb" slaveof 127.0.0.1 6379 # 配置主机
然后我们可以执行 redis-server <config file path> 来根据配置文件启动不同的 Redis 实例,依次启动主从节点:
redis-server myconf/redis-6379.conf redis-server myconf/redis-6380.conf redis-server myconf/redis-6381.conf
节点启动后,我们执行 redis-cli 默认连接到我们端口为 6379 的主节点执行 info replication 检查一下主从状态是否正常:
② 创建哨兵节点配置文件并启动
按照上面同样的方法,我们给哨兵节点也创建三个配置文件。(哨兵节点本质上是特殊的 Redis 节点,所以配置几乎没什么差别,只是在端口上做区分就好)
# redis-sentinel-1.conf port 26379 # 哨兵端口 daemonize yes # 以后台运行 logfile "26379.log" # 日志文件 # sentinel monitor 被监控的名称 host port 1 sentinel monitor myredis 127.0.0.1 6379 1 # redis-sentinel-2.conf port 26380 daemonize yes logfile "26380.log" sentinel monitor myredis 127.0.0.1 6379 1 # redis-sentinel-3.conf port 26381 daemonize yes logfile "26381.log" sentinel monitor myredis 127.0.0.1 6379 1
后面的这个数字 1,代表主机挂了,slave 投票看让谁接替成为主机,票数最多的,就会成为主机!
执行下方命令将哨兵节点启动起来:
redis-sentinel myconfig/redis-sentinel-1.conf redis-sentinel myconfig/redis-sentinel-2.conf redis-sentinel myconfig/redis-sentinel-3.conf
使用 redis-cli 工具连接哨兵节点,并执行 info Sentinel命令来查看是否已经在监视主节点了:
# 连接端口为 26379 的 Redis 节点 [root@cyan bin]# redis-cli -p 26379 127.0.0.1:26379> info Sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
此时你打开刚才写好的哨兵配置文件,你还会发现出现了一些变化
③ 演示故障转移
首先,我们使用 kill -s 9 命令来杀掉主节点,同时 在哨兵节点中执行 info Sentinel 命令来观察故障节点的过程:
# 查看redis服务 [root@cyan ~]# ps -aux|grep redis root 17438 0.1 0.1 169352 3444 ? Ssl 15:10 0:05 redis-server *:6379 root 17443 0.1 0.1 159624 3076 ? Ssl 15:10 0:04 redis-server *:6380 root 17450 0.1 0.1 159624 3084 ? Ssl 15:10 0:04 redis-server *:6381 root 17454 0.0 0.0 24856 1580 pts/0 S+ 15:10 0:00 redis-cli -p 6379 root 17455 0.0 0.0 24856 1576 pts/2 S+ 15:10 0:00 redis-cli -p 6380 root 17456 0.0 0.0 24856 1584 pts/3 S+ 15:11 0:00 redis-cli -p 6381 root 26699 0.2 0.1 153992 2648 ? Ssl 16:06 0:02 redis-sentinel *:26379 [sentinel] root 26707 0.2 0.1 153992 2648 ? Ssl 16:06 0:02 redis-sentinel *:26380 [sentinel] root 26713 0.2 0.1 153992 2640 ? Ssl 16:06 0:02 redis-sentinel *:26381 [sentinel] root 26867 0.0 0.0 112812 972 pts/4 R+ 16:23 0:00 grep --color=auto redis root 31944 0.0 0.0 24724 1388 pts/1 S+ 16:09 0:00 redis-cli -p 26379 # kill Redis服务 [root@cyan ~]# kill -s 9 17438
如果 刚杀掉瞬间 在哨兵节点中执行 info 命令来查看,会发现主节点还没有切换过来,因为哨兵发现主节点故障并转移需要一段时间:
# 第一时间查看哨兵节点发现并未转移,还在 6379 端口 127.0.0.1:26379> INFO sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=odown,address=127.0.0.1:6379,slaves=2,sentinels=3
一段时间之后你再执行 info 命令,查看,你就会发现主节点已经切换成了 6381 端口的从节点:
# 过一段时间之后在执行,发现已经切换了 6381 端口 127.0.0.1:26379> info Sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6381,slaves=2,sentinels=3
但同时还可以发现,哨兵节点认为新的主节点仍然有两个从节点 (上方 slaves=2),这是因为哨兵在将 6381 切换成主节点的同时,将 6379 节点置为其从节点。虽然 6379 从节点已经挂掉,但是由于 哨兵并不会对从节点进行客观下线,因此认为该从节点一直存在。当 6379 节点重新启动后,会自动变成 6381 节点的从节点。
另外,在故障转移的阶段,哨兵和主从节点的配置文件都会被改写:
● 对于主从节点: 主要是 slaveof 配置的变化,新的主节点没有了 slaveof 配置,其从节点则 slaveof 新的主节点。
● 对于哨兵节点:除了主从节点信息的变化,纪元(epoch)(记录当前集群状态的参数)也会变化,纪元相关的参数都 +1 了。
2)新的主机是怎么选举出来的
故障转移操作的第一步 要做的就是在已下线主服务器属下的所有从服务器中,挑选出一个状态良好、数据完整的从服务器,然后向这个从服务器发送 slaveof no one 命令,将这个从服务器转换为主服务器。但是这个从服务器是怎么样被挑选出来的呢?
简单来说 Sentinel 使用以下规则来选择新的主服务器:
① 在失效主服务器属下的从服务器当中, 那些被标记为主观下线、已断线、或者最后一次回复 PING 命令的时间大于五秒钟的从服务器都会被 淘汰。
② 在失效主服务器属下的从服务器当中, 那些与失效主服务器连接断开的时长超过 down-after 选项指定的时长十倍的从服务器都会被淘汰。
③ 在经历了以上两轮淘汰之后剩下来的从服务器中, 我们选出复制偏移量(replication offset)最大的那个从服务器作为新的主服务器;如果复制偏移量不可用,或者从服务器的复制偏移量相同,那么带有最小运行 ID的那个从服务器成为新的主服务器。
3)哨兵的优缺点
● 优点:
1、哨兵集群,基于主从复制模式,所有的主从配置优点,它全有
2、主从可以切换,故障可以转移,系统的可用性就会更好
3、哨兵模式就是主从模式的升级,手动到自动,更加健壮!
● 缺点:
1、Redis 不好在线扩容,集群容量一旦到达上限,在线扩容就十分麻烦!
2、实现哨兵模式的配置其实是很麻烦的,里面有很多选择!
@ 非原创 - @ 作者:我没有三颗心脏