目录
一.主从复制
1.redis主从复制原理
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master),后者称为从节点(Slave);数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
2.redis主从复制的作用
-
数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
-
故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
-
负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
-
高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
3.redis主从复制流程
-
若启动一个Slave机器进程,则它会向Master机器发送一个“sync command" 命令,请求同步连接。
-
无论是第一次连接还是重新连接,Master机器 都会启动一个后台进程,将数据快照保存到数据文件中(执行rdb操作) ,同时 Master 还会记录修改数据的所有命令并缓存在数据文件中。
-
后台进程完成缓存操作之后,Master 机器就会向 Slave 机器发送数据文件,Slave 端机器将数据文件保存到硬盘上,然后将其加载到内存中,接着 Master 机器就会将修改数据的所有操作一并发送给 Slave 端机器。若 Slave 出现故障导致宕机,则恢复正常后会自动重新连接。
-
Master机器收到 Slave 端机器的连接后,将其完整的数据文件发送给 Slave 端机器,如果 Mater 同时收到多个 Slave 发来的同步请求,则 Master 会在后台启动一个进程以保存数据文件,然后将其发送给所有的 Slave 端机器,确保所有的 Slave 端机器都正常。
二.部署Redis 主从复制的具体操作步骤
master:192.168.68.200
slave1:192.168.68.30
slave2:192.168.68.105
1.修改Master节点Redis配置文件
master192.168.68.200
[root@master ~]# vim /etc/redis/6379.conf
70 bind 0.0.0.0 ##修改bind 项,0.0.0.0监听所有网段
137 daemonize yes ##开启守护进程
172 logfile /var/log/redis_6379.log ##指定日志文件目录
264 dir /var/lib/redis/6379 ##指定工作目录
700 appendonly yes ##开启AOF持久化功能
[root@master ~]# /etc/init.d/redis_6379 restart
2.修改Slave节点Redis配置文件
slave1:192.168.68.30 slave2:192.168.68.105
[root@master ~]# vim /etc/redis/6379.conf
70 bind 0.0.0.0 ##修改bind 项,0.0.0.0监听所有网段
137 daemonize yes ##开启守护进程
172 logfile /var/log/redis_6379.log ##指定日志文件目录
264 dir /var/lib/redis/6379 ##指定工作目录
288 replicaof 192.168.68.200 6379 ##指定要同步的Master节点IP和端口
700 appendonly yes ##开启AOF持久化功能
[root@master ~]# /etc/init.d/redis_6379 restart
3.验证主从效果
在Master节点上看日志
[root@master ~]# tail -f /var/log/redis_6379.log
在Master节点上验证从节点
三.哨兵模式
哨兵的核心功能:在主从复制的基础上,哨兵引入了主节点的自动故障转移
1.哨兵模式原理
哨兵(sentinel):是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的Master并将所有Slave 连接到新的Master。所以整个运行哨兵的集群的数量不得少于3个节点。
哨兵是Redis集群架构中非常重要的一个组件,哨兵的出现主要是解决了主从复制出现故障时需要认为干预的问题
2.哨兵模式的作用
-
集群监控:哨兵会不断地检查主节点和从节点是否运作正常。
-
自动故障转移:当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。
-
通知(提醒):哨兵可以将故障转移的结果发送给客户端。
-
配置中心:如果故障转移发生了,通知 client 客户端习新的 master 地址
3.哨兵模式的结构
哨兵结构由两部分组成:哨兵节点和数据节点。
-
哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的 redis 节点,不存储数据。
-
数据节点:主节点和从节点都是数据节点。
哨兵的启动依赖于主从模式,所以须把主从模式安装好的情况下再去做哨兵模式,所有节点上都需要部署哨兵模式,哨兵模式会监控所有的Redis 工作节点是否正常,当Master 出现问题的时候,因为其他节点与主节点失去联系,因此会投票,投票过半就认为这个 Master 的确出现问题,然后会通知哨兵间,然后从Slaves中选取一个作为新的 Master。
需要特别注意的是:客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作。
-
首先主节点的信息是配置在哨兵的配置文件中
-
哨兵节点会和配置的主节点建立起两条连接命令连接和订阅连接
-
哨兵会通过命令连接每10s发送一次INFO命令,通过INFO命令,主节点会返回自己的run_id 和自己的从节点信息
-
哨兵会对这些从节点也建立两条连接命令连接和订阅连接
-
哨兵通过命令连接向从节点发送INFO命令,获取到他的一些信息: run_id(redis服务器id) role(职能) 从服务器的复制偏移量 offset 其他
-
通过命令连接向服务器的 _sentinel:hello 频道发送一条消息,包括自己的ip端口、run_id、配置(后续投票的时候会用到)等
-
通过订阅连接对服务器的 _sentinel:hello 频道做监听,所以所有的向该频道发送的哨兵消息都能被接收到
-
解析监听到的消息,进行分析提取,就可以知道还有哪些别的哨兵服务节点也在监听这些主从节点了,更新结构体将这些哨兵节点记录下来
-
向观察到的其他的哨兵节点建立命令连接
4.主观下线
哨兵节点会每秒一次的频率向建立了命令节点的实例发送ping命令,如果在 down-after-milliseconds 毫秒内没有做出有效响应包括(pong/loading/masterdown)以外的响应,哨兵就会将该实例在本结构体中的状态标记为 sri_s_down 主观下线
5.客观下线
当一个哨兵节点发现主节点处于主观下线状态时,就会向其他的哨兵节点发出询问,该节点是否已经主观下线。如果超过配置参数 quorum 个节点认为是主观下线时,该哨兵节点就会将自己维护的结构体中该主节点标记为 sri_o_down 客观下线
6.master选举
在认为主节点客观下线的情况下,哨兵节点间会发起一次选举,命令为: SENTINEL is-master-down-by-addr,只是 run_id 这次会将自己的 run_id 带进去,希望接受者将自己设置为主节点。如果超过半数以上的节点返回将该节点标记为 leader 的情况下,会有该 leader 对故障进行迁移
7.故障迁移
-
在从节点中挑选出新的从节点
-
通讯正常
-
优先级排序
-
优先级相同时选择offset最大的
-
-
将该节点设置成新的主节点 slaveof no one ,并确保在后续的 INGO 命令时,该节点返回状态为 master
-
将其他的从节点设置成从新的主节点服务, slaveof 命令
-
将旧的主节点变成新的主节点的从节点
8.优缺点
-
优点:高可用,哨兵模式是基于主从模式的,所有主从模式的优点,哨兵模式都有;主从可以自动切换,系统更健壮,可用性更高
-
缺点:redis 比较难支持在线扩容,在群集容量达到上限时在线扩容会变得很复杂
四.哨兵模式部署的具体操作步骤
master:192.168.68.200
slave1:192.168.68.30
slave2:192.168.68.105
1.修改所有redis服务器配置文件
systemctl stop firewalld
setenforce 0
[root@master ~]# vim /opt/redis-5.0.7/sentinel.conf
17 protected-mode no ##关闭保护模式
21 port 26379 ##Redis哨兵默认的监听端口
26 daemonize yes ##指定sentinel为后台启动
36 logfile "/var/log/sentinel.log" ##指定日志存放路径
65 dir "/var/lib/redis/6379" ##指定数据库存放路径
84 sentinel monitor mymaster 192.168.68.200 6379 2
##修改指定该哨兵节点监控192.168.68.200:6379这个主节点,该主节点的名称是mymaster,最后的2的含义与主节点的故障判定有关:至少需要2个哨兵节点同意,才能判定主节点故障并进行故障转移
113 sentinel down-after-milliseconds mymaster 30000
##判定服务器down掉的时间周期,默认30000毫秒(30秒)
146 sentinel failover-timeout mymaster 180000
##故障节点的最大超时时间为180000(180秒)
[root@master ~]# vim /opt/redis-5.0.7/sentinel.conf
2.启动哨兵模式
先启master,再启slave
3.模拟故障
关闭redis服务,模拟宕机
验证结果
[root@master redis-5.0.7]# tail -f /var/log/sentinel.log
[root@master redis-5.0.7]# redis-cli -p 26379 INFO Sentinel
五.集群模式
1.集群模式的作用
-
数据分区:数据分区(或称数据分片) 是集群最核心的功能。 集群将数据分散到多个节点,一方面突破了 Redis 单机内存大小的限制,存储容量大大增加;另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。 Redis 单机内存大小受限问题,在介绍持久化和主从复制时都有提及;例如,如果单机内存太大,bgsave 和 bgrewriteaof的 fork 操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出。
-
高可用:集群支持主从复制和主节点的自动故障转移(与哨兵类似) ;当任一节点发生故障时,集群仍然可以对外提供服务。
2.集群模式的数据分片
-
Redis集群引入了哈希槽的概念
-
Redis集群有 16384 个哈希槽( 编号0-16383)
-
集群的每个节点负责一部分哈希槽
-
每个Key 通过 CRC16 校验后对16384取余来决定放置哪个哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作
六.Redis 集群部署的具体操作步骤
192.168.68.195
3个主节点端口号:6001/6002/6003, 对应的从节点端口号:6004/ 6005/ 6006。
1.创建目录复制配置文件到对应的节点上
[root@localhost ~]# cd /etc/redis/
[root@localhost redis]# mkdir -p redis-cluster/redis600{1..6}
[root@localhost redis-5.0.7]# for i in {1..6}
> do
> cp ./redis.conf src/redis-cli src/redis-server /etc/redis/redis-cluster/redis600$i
> done
[root@localhost ~]# cd /etc/redis/redis-cluster/
[root@localhost redis-cluster]# tree
[root@localhost redis-cluster]# cd redis6001
2. 修改主配置文件,开启群集功能
[root@localhost redis6001]# vim redis.conf
69 #bind 127.0.0.1 ##注释掉bind项,默认监听所有网卡
88 protected-mode no ##关闭保护模式
92 port 6001 ##redis监听端口
136 daemonize yes ##开启守护进程,以独立进程启动
699 appendonly yes ##开启AOF持久化
832 cluster-enabled yes ##取消注释,开启群集功能
840 cluster-config-file nodes-6001.conf ##取消注释,群集名称文件设置
846 cluster-node-timeout 15000 ##取消注释群集超时时间设置
[root@localhost redis6001]# \cp -f redis.conf ../redis6002
[root@localhost redis6001]# \cp -f redis.conf ../redis6003
[root@localhost redis6001]# \cp -f redis.conf ../redis6004
[root@localhost redis6001]# \cp -f redis.conf ../redis6005
[root@localhost redis6001]# \cp -f redis.conf ../redis6006
##修改其余的端口号
[root@localhost redis6002]# vim /etc/redis/redis-cluster/redis6002/redis.conf
92 port 6002 ##redis监听端口
840 cluster-config-file nodes-6002.conf ##取消注释,群集名称文件设置
[root@localhost redis6003]# vim /etc/redis/redis-cluster/redis6003/redis.conf
92 port 6003 ##redis监听端口
840 cluster-config-file nodes-6003.conf ##取消注释,群集名称文件设置
[root@localhost redis6004]# vim /etc/redis/redis-cluster/redis6004/redis.conf
92 port 6004 ##redis监听端口
840 cluster-config-file nodes-6004.conf ##取消注释,群集名称文件设置
[root@localhost redis6005]# vim /etc/redis/redis-cluster/redis6005/redis.conf
92 port 6005 ##redis监听端口
840 cluster-config-file nodes-6005.conf ##取消注释,群集名称文件设置
[root@localhost redis6006]# vim /etc/redis/redis-cluster/redis6006/redis.conf
92 port 6006 ##redis监听端口
840 cluster-config-file nodes-6006.conf ##取消注释,群集名称文件设置
[root@localhost redis6002]# vim /etc/redis/redis-cluster/redis6002/redis.conf
[root@localhost redis6003]# vim /etc/redis/redis-cluster/redis6003/redis.conf
[root@localhost redis6004]# vim /etc/redis/redis-cluster/redis6004/redis.conf
[root@localhost redis6005]# vim /etc/redis/redis-cluster/redis6005/redis.conf
[root@localhost redis6006]# vim /etc/redis/redis-cluster/redis6006/redis.conf
3.启动redis节点
[root@localhost redis-cluster]# cd redis6001
[root@localhost redis6001]# pwd
/etc/redis/redis-cluster/redis6001
[root@localhost redis6001]# redis-server redis.conf
[root@localhost redis6001]# for i in {1..6}
> do
> cd /etc/redis/redis-cluster/redis600$i
> redis-server redis.conf
> done
[root@localhost redis6006]# ps -elf |grep redis
5 S root 6416 1 0 80 0 - 38461 ep_pol 08:28 ? 00:00:08 /usr/local/redis/bin/redis-server 127.0.0.1:6379
5 S root 9914 1 0 80 0 - 38462 ep_pol 10:50 ? 00:00:00 redis-server *:6001 [cluster]
5 S root 9921 1 0 80 0 - 38462 ep_pol 10:50 ? 00:00:00 redis-server *:6002 [cluster]
5 S root 9926 1 0 80 0 - 38462 ep_pol 10:50 ? 00:00:00 redis-server *:6003 [cluster]
5 S root 9931 1 0 80 0 - 38462 ep_pol 10:50 ? 00:00:00 redis-server *:6004 [cluster]
5 S root 9936 1 0 80 0 - 38462 ep_pol 10:50 ? 00:00:00 redis-server *:6005 [cluster]
5 S root 9941 1 0 80 0 - 38462 ep_pol 10:50 ? 00:00:00 redis-server *:6006 [cluster]
0 S root 9948 9634 0 80 0 - 28169 pipe_w 10:51 pts/0 00:00:00 grep --color=auto redis
4.启动集群
[root@localhost redis6006]# redis-cli --cluster create 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:6004 127.0.0.1:6005 127.0.0.1:6006 --cluster-replicas 1
六个实例分为三组,每组一主一从,前面的做主节点,后面的做从节点。下面交互的时候需要输入yes才可以创建。–replicas 1表示每个主节点有1个从节点
5.测试群集
[root@localhost redis6006]# redis-cli -p 6001 -c ##-c 代表群集之间可以互相跳转
127.0.0.1:6001> cluster slots ##查看节点的哈希槽编号范围
1) 1) (integer) 10923
2) (integer) 16383 ##哈希槽编号范围
3) 1) "127.0.0.1"
2) (integer) 6003 ##主节点IP和端口号
3) "c20db91397beebc909cab883b658b622a93b8f2e"
4) 1) "127.0.0.1"
2) (integer) 6006 ##从节点IP和端口号
3) "f41bbfbef5ce386246d4f56ca173804ddc83e4ea"
2) 1) (integer) 5461
2) (integer) 10922
3) 1) "127.0.0.1"
2) (integer) 6002
3) "7f58ec37f0180fd889bb2c55c0906bf383a04968"
4) 1) "127.0.0.1"
2) (integer) 6005
3) "566eb50e7ea3bcbae4d1a57efee6eb730746baa9"
3) 1) (integer) 0
2) (integer) 5460
3) 1) "127.0.0.1"
2) (integer) 6001
3) "affd3362d7053ff848d3263fa947a05fd5961bbb"
4) 1) "127.0.0.1"
2) (integer) 6004
3) "af714e0bc19405a5724848859ad60528b5a634cd"
127.0.0.1:6001> set oyyy yibo
-> Redirected to slot [5850] located at 127.0.0.1:6002
OK
127.0.0.1:6002> cluster keyslot oyyy
(integer) 5850
[root@localhost redis6006]# redis-cli -h 192.168.68.195 -p 6002 -c
192.168.68.195:6002> keys *
1) "oyyy"
192.168.68.195:6002> get oyyy
"yibo"