Redis 主从复制、哨兵模式、Cluster集群
一、Redis主从复制
1.1、什么是主从复制
如图:
将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点。默认情况下,每台Redis服务器都是主节点,且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
- 简单的说就是主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。
1.2、主从复制的作用
- 一个是读写分离,分担 "master" 的读写压力
- 一个是方便做容灾恢复
除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
1.3、主从复制流程
(1)若启动一个Slave机器进程,则它会向Master机器发送一个"sync command"命令,请求同步连接
(2)无论是第一次连接还是重新连接,Master机器都会启动一个后台进程,将数据快照保存到数据文件中(执行rdb操作),同时Master还会记录修改数据的所有命令并缓存在数据文件中
(3)后台进程完成缓存操作之后,Master机器就会向Slave机器发送数据文件,slave端机器将数据文件保存到硬盘上,然后将其加载到内存中,接着Master机器就会将修改数据的所有操作一并发送给Slav端机器。若Slave出现故障导致宕机,则恢复正常后会自动重新连接
(4)Master机器收到Slave端机器的连接后,将其完整的数据文件发送给Slave端机器,如果Mater同时收到多个slave发来的同步请求,则Master会在后台启动一个进程以保存数据文件,然后将其发送给所有的Slave端机器,确保所有的slave端机器都正常
1.4、主从复制的优缺点
优点:
- 避免单点故障,将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务。
- master能自动将数据同步到slave,可以进行读写分离,分担master的读压力
- master、slave之间的同步是以非阻塞的方式进行的,同步期间,客户端仍然可以提交查询或更新请求
缺点:
- 不具备自动容错与恢复功能,master或slave的宕机都可能导致客户端请求失败,需要等待机器重启或手动切换客户端IP才能恢复
- master宕机,如果宕机前数据没有同步完,则切换IP后会存在数据不一致的问题
- 难以支持在线扩容,Redis的容量受限于单机配置
二、Redis哨兵模式
2.1、什么是哨兵模式?
第一种主从同步/复制的模式,当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个 Redis 实例。
2.2、哨兵模式的作用
1)通过发送命令,让 Redis 服务器返回监控其运行状态,包括主服务器和从服务器;
2)当哨兵监测到 master 宕机,会自动将 slave 切换成 master ,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
3)哨兵可以将故障转移的结果发送给客户端
2.3、多哨兵模式
然而一个哨兵进程对Redis服务器进行监控,也可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
2.4、哨兵的工作模式
(1)所有哨兵都会监控节点,哨兵之间会共享服务器的状态数据,对整个集群实现监控
(2)哨兵的启动依赖于主从模式,所以须把主从模式安装好的情况下再去做哨兵模式,所有节点上都需要部署哨兵模式,哨兵模式会监控所有的 Redis 工作节点是否正常,当Master出现问题的时候,
因为其他节点与主节点失去联系,因此会投票,投票过半就认为这个Master的确出现问题,然后会通知哨兵间,然后从Slaves中选取一个作为新的Master
(3)需要特别注意的是,客观下线是主节点才有的概念,如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作
主观下线:当某个哨兵认为节点宕机,是主观下线
客观下线:当所有哨兵投票后票数过半后确认宕机为客观下线,然后就会执行故障的切换等过程
三、Redis群集模式
3.1、什么是Cluster群集模式
Redis Cluster是Redis提供的分布式数据库方案,集群通过分片(sharding)来进行数据共享,并提供复制和故障转移功能,从Redis3.0版本开始正式提供。
Redis 的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台 Redis 服务器都存储相同的数据,很浪费内存,所以在 redis3.0上加入了 Cluster 集群模式,实现了 Redis 的分布式存储,也就是说每台 Redis 节点上存储不同的内容。
3.2、群集的作用
(1)数据分区:数据分区(或称数据分片)是集群最核心的功能。 集群将数据分散到多个节点,一方面突破了Redis单机内存大小的限制,存储容量大大增加;另一方面每个主节点都可以对外提供读服务
和写服务,大大提高了集群的响应能力。 Redis单机内存大小受限问题,在介绍持久化和主从复制时都有提及;例如,如果单机内存太大,bgsave和bgrewriteaof的fork操作可能导致主进程阻塞,主从环
境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出。
(2)高可用:集群支持主从复制和主节点的自动故障转移(与哨兵类似);当任一节点发生故障时,集群仍然可以对外提供服务。
3.3、群集的数据分片
Redis 集群没有使用一致性 hash,而是引入了哈希槽【hash slot】的概念。
Redis 集群有16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽。集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:
- 节点 A 包含 0 到 5460 号哈希槽
- 节点 B 包含 5461 到 10922 号哈希槽
- 节点 C 包含 10923 到 16383 号哈希槽
这种结构很容易添加或者删除节点。比如如果我想新添加个节点 D , 我需要将节点 A, B, C 中的部分槽移动到 节点D 上。如果我想移除节点 A ,需要将 A 中的槽移到 B 和 C 节点上,然后将没有任何槽的 A 节点从集群中移除即可。由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。在 Redis 的每一个节点上,都有这么两个东西,一个是插槽(slot),它的的取值范围是:0-16383。还有一个就是 cluster,可以理解为是一个集群管理的插件。当我们的存取的 Key到达的时候,Redis会根据 CRC16 的算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
四、实验搭建 主从复制,哨兵模式,群集模式
4.1、搭建redis主从复制
环境配置
master 192.168.118.100 slave1 192.168.118.101 slave2 192.168.118.102
所有服务器搭建redis数据库
所有节点都要安装redis这边只展示一台的搭建过程
1 关闭防火墙 2 systemctl stop firewalld 3 setenforce 0 4 #安装依赖环境 5 yum install -y gcc gcc-c++ make 6 7 #解压文件到指定文件夹 opt 8 tar zxvf redis-5.0.7.tar.gz -C /opt/ 9 cd /opt/redis-5.0.7/ 10 #安装 11 make 12 make PREFIX=/usr/local/redis install 13 #执行软件包提供的install_server.sh 脚本文件,设置Redis服务所需要的相关配置文件 14 cd /opt/redis-5.0.7/utils 15 ./install_server.sh 16 …… 17 慢慢回车 18 Please select the redis executable path [] 19 手动输入 20 /usr/local/redis/bin/redis-server 21 22 #创建软链接 23 ln -s /usr/local/redis/bin/* /usr/local/bin/ 24 25 /etc/init.d/redis_6379 stop #停止 26 /etc/init.d/redis_6379 start #启动 27 /etc/init.d/redis_6379 restart #重启 28 /etc/init.d/redis_6379 status 29 30 #重启redis服务 31 /etc/init.d/redis_6379 restart
修改Redis配置文件(Master节点操作)
1 vim /etc/redis/6379.conf 2 bind 0.0.0.0 #70行,修改监听地址为0.0.0.0 3 daemontze yes #137行,开启守护进程 4 logfile/var/log/redis_6379.1og #172行,指定日志文件目录 5 dir/var/lib/redis/6379 #264行,指定工作目录 6 appendonly yes #700行,开启AOF持久化功能 7 /etc/init.d/redis_6379 restart
修改Redis配置文件(slave节点操作)
1 vim /etc/redis/6379.conf 2 3 bind 0.0.0.0 #70行,修改监听地址为0.0.0.0 4 daemonize yes #137行,开启守护进程 5 logfile/var/log/redis 6379.1og #172行,指定日志文件目录 6 dir/var/lib/redis/6379 #264行,指定工作目录 7 replicaof 192.168.52.140 6379#288行,指定要同步的Master节点IP和端口 8 appendonly yes #700行,开启AOF持久化功能 9 /etc/init.d/redis_6379 restart 10 netstat -natp | grep redis
slave节点配置与master节点类似使用scp命令进行远程传输后进行修改
scp /etc/redis/6379.conf 192.168.118.101:/etc/redis scp /etc/redis/6379.conf 192.168.118.102:/etc/redis
进入两台slave服务器进行修改
1 vim /etc/redis/6379.conf 2 replicaof 192.168.52.140 6379#288行,指定要同步的Master节点IP和端口 3 /etc/init.d/redis_6379 restart 4 netstat -natp | grep redis 查看主从服务器是否连接
验证主从效果
在Master节点上看日志
在Master节点上验证从节点
在master节点上添加数据 从节点查看
4.2、搭建redis哨兵模式
环境配置
master 192.168.118.100 slave1 192.168.118.101 slave2 192.168.118.102 sentinel-1: 192.168.118.103 sentinel-2: 192.168.118.104 sentinel-3: 192.168.118.105
所有哨兵服务器安装好redis服务
搭建主从复制的时候给过详细步骤这边就不配图了
1 关闭防火墙 2 systemctl stop firewalld 3 setenforce 0 4 #安装依赖环境 5 yum install -y gcc gcc-c++ make 6 7 #解压文件到指定文件夹 opt 8 tar zxvf redis-5.0.7.tar.gz -C /opt/ 9 cd /opt/redis-5.0.7/ 10 #安装 11 make 12 make PREFIX=/usr/local/redis install 13 #执行软件包提供的install_server.sh 脚本文件,设置Redis服务所需要的相关配置文件 14 cd /opt/redis-5.0.7/utils 15 ./install_server.sh 16 …… 17 慢慢回车 18 Please select the redis executable path [] 19 手动输入 20 /usr/local/redis/bin/redis-server 21 22 #创建软链接 23 ln -s /usr/local/redis/bin/* /usr/local/bin/ 24 25 /etc/init.d/redis_6379 stop #停止 26 /etc/init.d/redis_6379 start #启动 27 /etc/init.d/redis_6379 restart #重启 28 /etc/init.d/redis_6379 status 29 30 #重启redis服务 31 /etc/init.d/redis_6379 restart
master和slave部署Redis主从复制
####这边我之前做好主从复制了,这边就不重复做了,省略这一步
修改哨兵节点的配置文件sentinel.conf(所有哨兵节点操作)
- 此处修改192.168.118.103哨兵节点的配置文件,使用scp命令传给其他两个哨兵节点
vim /opt/redis-5.0.7/sentinel.conf protected-mode no #17行,关闭保护模式 port 26379 #21行,Redis哨兵默认的监听端口 daemonize yes #26行,指定sentine1为后台启动 logfile "/var/log/sentinel.log" #36行,指定日志存放路径 dir "/var/lib/redis/6379" #65行,指定数据库存放路径 sentinel monitor mymaster 192.168.118.100 6379 2 #84行,修改指定该哨兵节点监控192.168.118.100:6379这个主节点,该主节点的名称是mymaster,最后的2的含义与主节点的故障判定有关:至少需要2个哨兵节点同意,才能判定主节点故障并进行故障转移 sentinel down-after-milliseconds mymaster 3000 #113行,判定服务器down掉的时间周期,默认30000毫秒(30秒) sentinel failover-timeout mymaster 180000 #146行,同一个sentine1对同一个master两次failover之间的间隔时间(180秒) #远程传续将配置文件传输给其他哨兵服务器 scp /opt/redis-5.0.7/sentinel.conf 192.168.118.104:/opt/redis-5.0.7/ scp /opt/redis-5.0.7/sentinel.conf 192.168.118.105:/opt/redis-5.0.7/
启动哨兵模式
#所有哨兵服务器执行 cd /opt/redis-5.0.7/ redis-sentinel sentinel.conf &
在哨兵节点查看哨兵消息
故障模拟
#在master节点查看redis-server进程号 ps -ef | grep redis #杀死master节点redis-server进程 kill -9 79754
在哨兵节点上验证master是否转换至从服务器
redis-cli -p 26379 info sentinel
故障恢复
1 #主节点 2 rm -rf /var/run/redis_6379.pid #删除pid文件如果pid文件不删除则服务起不来 3 /etc/init.d/redis_6379 start #启动服务 4 netstat -natp |grep 6379 5 #主服务器查看 6 redis-cli info replication
4.3、搭建redis群集模式
实验环境配置
- redis的集群一般需要6个节点,3主3从,每个节点都要安装redis
服务器类型 | 系统和IP地址 | 需要安装的组件 |
master1 | 192.168.118.100 | redis-5.0.7.tar.gz |
master2 | 192.168.118.101 | redis-5.0.7.tar.gz |
master3 | 192.168.118.102 | redis-5.0.7.tar.gz |
slave1 | 192.168.118.103 | redis-5.0.7.tar.gz |
slave2 | 192.168.118.104 | redis-5.0.7.tar.gz |
slave3 | 192.168.118.105 | redis-5.0.7.tar.gz |
修改任意一台服务器配置文件
vim /opt/redis-5.0.7/redis.conf bind 192.168.118.100 #69行,注释掉bind项,改为自己 protected-mode no #88行,修改,关闭保护模式 port 6379 #92行redis默认监听端口, daemonize yes #136行,开启守护进程,以独立进程启动 appendonly yes #700行,修改,开启AOF持久化 cluster-enabled yes #832行,取消注释,开启群集功能 cluster-config-file nodes-6001.conf #840行,取消注释,群集名称文件设置 cluster-node-timeout 15000 #846行,取消注释群集超时时间设置 #远程传输完要修改监听地址为自己 scp /opt/redis-5.0.7/redis.conf 192.168.118.101:/opt/redis-5.0.7/ scp /opt/redis-5.0.7/redis.conf 192.168.118.102:/opt/redis-5.0.7/ scp /opt/redis-5.0.7/redis.conf 192.168.118.103:/opt/redis-5.0.7/ scp /opt/redis-5.0.7/redis.conf 192.168.118.104:/opt/redis-5.0.7/ scp /opt/redis-5.0.7/redis.conf 192.168.118.105:/opt/redis-5.0.7/
启动redis节点所有节点执行
cd /opt/redis-5.0.7/ redis-server redis.conf #启动redis节点
启动集群
集群开启成功
遇到的报错及解决办法
当我开启集群时,开启失败并报出以下错误提示
[ERR] Node 192.168.118.100:6379 is not configured as a cluster node.
先说下我当时的排错思路
- 检查端口是否开启成功
- 查看配置文件redis.conf群集设置是否开启
检查端口时发现监听地址是0.0.0.0,感觉有点不对劲,还有/usr/local/redis/bin/redis-server地址也不是我刚创建的,我才想起来,我在部署redis服务的时候使用脚本安装,脚本里是使用默认的服务目录启动
找到问题了,我们将之前开的服务关闭,在开启集群。
/etc/init.d/redis_6379 stop ###关闭服务 redis-server redis.conf ###重新开启 ps -ef | grep redis ###查看是否开启 root 7628 1 0 08:46 ? 00:00:00 redis-server 192.168.118.100:6379 [cluster] ###这时监听地址已经恢复正确 root 7633 7252 0 08:46 pts/2 00:00:00 grep --color=auto redis
接下来重新开启集群就可以正常开启了。