Redis主从复制搭建和哨兵模式

Redis主从复制原理是什么?


 1.设置了一个从服务器,在连接时它发送了一个SYNC命令,不管它是第一次连接还是再次连接都没有关系

2.然后主服务器开始后台存储,并且开始缓存新连接进来的修改数据的命令。当后台存储完成后,主服务器把数据文件发送到从服务器,
从服务器将其保存在磁盘上,然后加载到内存中。然后主服务器把刚才缓存的命令发送到从服务器。这是作为命令流来完成的,并且
和Redis协议本身格式相同

3.在Redis服务器工作时连接到Redis端口,发送SYNC命令,会看到一个批量的传输,并且主服务器接收的每一个命令都会通过telnet会话重新发送一遍

4.当主从服务器之间的连接由于某些原因断开时,从服务器可以自动进行重连接。当有多个从服务器同时请求同步时,主服务器只进行一个后台存储

5.当连接断开又重新连上之后,一般都会进行一个完整的重新同步,但是从Redis2.8开始,只重新同步一部分也可以

 

主从复制的作用

1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式

2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余

3. 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量

4. 读写分离:可以用于实现读写分离,主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库的数量

5. 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础

 

服务器环境说明

操作系统:Centos 7

主服务器:172.30.93.122

从服务器:172.30.93.123

从服务器:172.30.93.124

Redis版本:5.0.9

 

安装Redis

三台服务器安装都一样,配置文件有一些不同如下:

[root@Redis-Node1 ~]# yum -y install tcl gcc gcc-c++  make zlib zlib-devel
[root@Redis-Node1 ~]# wget https://download.redis.io/releases/redis-5.0.9.tar.gz
[root@Redis-Node1 ~]# tar zxvf redis-5.0.9.tar.gz -C /usr/local/ && rm -rf redis-5.0.9.tar.gz 
[root@Redis-Node1 ~]# cd /usr/local/redis-5.0.9/
[root@Redis-Node1 /usr/local/redis-5.0.9]# make && make install PREFIX=/usr/local/redis
[root@Redis-Node1 /usr/local/redis-5.0.9]# cp -rf redis.conf /usr/local/redis
[root@Redis-Node1 /usr/local/redis-5.0.9]# cd /usr/local/redis
[root@Redis-Node1 /usr/local/redis]# vim redis.conf 
   
bind 172.30.93.122
daemonize yes
protected-mode no
port 6379 logfile
/usr/local/redis/logs/redis.log dir /usr/local/redis/data [root@Redis-Node1 /usr/local/redis]# [root@Redis-Node1 /usr/local/redis]# mkdir logs data [root@Redis-Node1 /usr/local/redis]# vim /etc/systemd/system/redis.service [Unit] Description=redis-server After=network.target [Service] Type=forking ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/redis.conf PrivateTmp=true [Install] WantedBy=multi-user.target [root@Redis-Node1 /usr/local/redis]# [root@Redis-Node1 /usr/local/redis]# systemctl daemon-reload [root@Redis-Node1 /usr/local/redis]# ln -s /usr/local/redis/bin/redis-cli /usr/bin/redis [root@Redis-Node1 /usr/local/redis]# vim /etc/sysctl.conf net.core.somaxconn = 1024 vm.overcommit_memory = 1 [root@Redis-Node1 /usr/local/redis]# [root@Redis-Node1 /usr/local/redis]# sysctl -p [root@Redis-Node1 /usr/local/redis]# vim /etc/rc.local echo never > /sys/kernel/mm/transparent_hugepage/enabled [root@Redis-Node1 /usr/local/redis]# [root@Redis-Node1 /usr/local/redis]# source /etc/rc.local [root@Redis-Node1 /usr/local/redis]# systemctl start redis.service

唯一不同的就是从服务器的配置文件需要修改一下内容,设置主节点的IP和端口

从服务器:172.30.93.123配置文件内容:

[root@Redis-Node2 /usr/local/redis]# vim redis.conf 
   
bind 172.30.93.123
daemonize yes
protected-mode no
port 6379
logfile /usr/local/redis/logs/redis.log
dir /usr/local/redis/data
replicaof 172.30.93.122 6379

[root@Redis-Node2 /usr/local/redis]#

从服务器:172.30.93.124配置文件内容:

[root@Redis-Node3 /usr/local/redis]# vim redis.conf 
   
bind 172.30.93.124
daemonize yes
protected-mode no
port 6379
logfile /usr/local/redis/logs/redis.log
dir /usr/local/redis/data
replicaof 172.30.93.122 6379

[root@Redis-Node3 /usr/local/redis]#

 

检查节点同步

主节点:

[root@Redis-Node1 /usr/local/redis]# redis -h 172.30.93.122 -p 6379
172.30.93.122:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.30.93.123,port=6379,state=online,offset=16982,lag=0
slave1:ip=172.30.93.124,port=6379,state=online,offset=16982,lag=0
master_replid:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:16982
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:16982
172.30.93.122:6379> set ops dev
OK
172.30.93.122:6379> 

启动节点之后查看到已经有其他数据库的信息,有两个slave连接到master,并且创建数据看slave是否同步

从节点:

[root@Redis-Node2 /usr/local/redis]# redis -h 172.30.93.123 -p 6379
172.30.93.123:6379> INFO replication
# Replication
role:slave
master_host:172.30.93.122
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:17316
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:17316
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:17316
172.30.93.123:6379> 
172.30.93.123:6379> get ops
"dev"
172.30.93.123:6379> 

从节点

[root@Redis-Node3 /usr/local/redis]# redis -h 172.30.93.124 -p 6379
172.30.93.124:6379> INFO replication
# Replication
role:slave
master_host:172.30.93.122
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:17708
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:17708
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:17708
172.30.93.124:6379> get ops
"dev"
172.30.93.124:6379> 

可以看到两个从节点都是slave状态,并且数据已经同步数据库里。主从同步成功

 

主从同步中需要注意几个问题

1. 在上面的全量同步过程中,master会将数据保存在rdb文件中然后发送给slave服务器,但是如果master上的磁盘空间有效怎么办呢?那么此时全部同步对于master来说将是一份十分有压力的操作了。此时可以通过无盘复制来达到目的,由master直接开启一个socket将rdb文件发送给slave服务器。(无盘复制一般应用在磁盘空间有限但是网络状态良好的情况下)

2. 主从复制结构,一般slave服务器不能进行写操作,但是这不是死的,之所以这样是为了更容易的保证主和各个从之间数据的一致性,如果slave服务器上数据进行了修改,那么要保证所有主从服务器都能一致,可能在结构上和处理逻辑上更为负责。不过你也可以通过配置文件让从服务器支持写操作。(不过所带来的影响还得自己承担哦)

3. 主从服务器之间会定期进行通话,但是如果master上设置了密码,那么如果不给slave设置密码就会导致slave不能跟master进行任何操作,所以如果你的master服务器上有密码,那么也给slave相应的设置一下密码吧(通过设置配置文件中的masterauth);

4. 关于slave服务器上过期键的处理,由master服务器负责键的过期删除处理,然后将相关删除命令已数据同步的方式同步给slave服务器,slave服务器根据删除命令删除本地的key

 

哨兵模式

Sentinel(哨兵)是用于监控redis集群中Master状态的工具,是Redis的高可用性解决方案。sentinel是redis高可用的解决方案,sentinel系统可以监视一个或者多个redis master服务,以及这些master服务的所有从服务;当某个master服务下线时,自动将该master下的某个从服务升级为master服务替代已下线的master服务继续处理请求。
sentinel可以让redis实现主从复制,当一个集群中的master失效之后,sentinel可以选举出一个新的master用于自动接替master的工作,集群中的其他redis服务器自动指向新的master同步数据。一般建议sentinel采取奇数台,防止某一台sentinel无法连接到master导致误切换。
Sentinel由一个或多个Sentinel 实例 组成的Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。

 

哨兵工作方式

1.每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个PING命令
2.如果一个实例(instance)距离最后一次有效回复PING命令的时间超过 own-after-milliseconds 选项所指定的值,则这个实例会被Sentinel标记为主观下线
3.如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态
4.当有足够数量的Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态,则Master会被标记为客观下线
5.在一般情况下,每个Sentinel 会以每10秒一次的频率向它已知的所有Master,Slave发送 INFO 命令
6.当Master被Sentinel标记为客观下线时,Sentinel 向下线的 Master 的所有Slave发送 INFO命令的频率会从10秒一次改为每秒一次
7.若没有足够数量的Sentinel同意Master已经下线,Master的客观下线状态就会被移除。若Master重新向Sentinel 的PING命令返回有效回复,Master的主观下线状态就会被移除

 

搭建哨兵模式

由于哨兵模式是基于主从复制,所以我们就基于上面的环境搭建

搭建的环境模式,一主两从三哨兵

[root@Redis-Node1 ~]# cd /usr/local/redis/
[root@Redis-Node1 /usr/local/redis]# vim sentinel.conf

port 26379

daemonize yes

protected-mode no

pidfile "/var/run/redis-sentinel.pid"

logfile "/usr/local/redis/logs/sentinel.log"

dir "/usr/local/redis/data"

sentinel monitor mymaster 172.30.93.122 6379 2

# redis主从密码,这里也需要设置
# sentinel auth-pass mymaster redis2021

sentinel down-after-milliseconds mymaster 3000 

snetinel parallel-syncs mymaster 1 

sentinel failover-timeout mymaster 180000

sentinel deny-scripts-reconfig yes


[root@Redis-Node1 /usr/local/redis]# vim /etc/systemd/system/redis-sentinel.service

[Unit]
Description=Redis sentinel Server
After=network.target

[Service]
Type=forking
PIDFile=/var/run/redis-sentinel.pid
ExecStart=/usr/local/redis/bin/redis-sentinel /usr/local/redis/sentinel.conf --sentinel
ExecStop=/usr/local/redis/bin/redis-cli -p 26379 shutdown
Restart=on-failure
[Install]
WantedBy=multi-user.target

[root@Redis-Node1 /usr/local/redis]# systemctl daemon-reload
[root@Redis-Node1 /usr/local/redis]# systemctl start redis-sentinel

三台服务器一起执行这些命令就可以了,其他 sentinel.conf 配置文件都是重新生成的(后期如果主的redis  master挂了,配置文件会自动修改)

配置文件修改说明:

//端口默认为26379 
port:26379 

//设置为后台启动
daemonize:yes 

//关闭保护模式,可以外部访问
protected-mode:no 

//PID文件路径
pidfile "/var/run/redis-sentinel.pid"

//日志文件路径 
logfile "/usr/local/redis/logs/sentinel.log"

//数据存放路径
dir "/usr/local/redis/data"

//指定主机IP地址和端口,并且指定当有2台哨兵认为主机挂了,则对主机进行容灾切换
sentinel monitor mymaster 172.30.93.122 6379 2 

//redis主从密码,这里也需要设置
# sentinel auth-pass mymaster redis2021

//这里设置了主机多少秒无响应,则认为挂了 
sentinel down-after-milliseconds mymaster 3000 

//主备切换时,最多有多少个slave同时对新的master进行同步,这里设置为默认的1
snetinel parallel-syncs mymaster 1 

//故障转移的超时时间,这里设置为三分钟 
sentinel failover-timeout mymaster 180000 

//避免了一个简单的安全问题,客户端可以将脚本设置为任何内容并触发故障转移以便执行程序
sentinel deny-scripts-reconfig yes

 

查看哨兵模式同步

[root@Redis-Node1 ~]# redis -h 172.30.93.122 -p 6379
172.30.93.122:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.30.93.123,port=6379,state=online,offset=88409,lag=1
slave1:ip=172.30.93.124,port=6379,state=online,offset=88409,lag=1
master_replid:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:88691
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:88691
172.30.93.122:6379> 
172.30.93.122:6379> 
172.30.93.122:6379> get ops
"dev"
172.30.93.122:6379> 
[root@Redis-Node1 ~]# 
[root@Redis-Node1 ~]# redis -h 172.30.93.122 -p 26379
172.30.93.122: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=172.30.93.122:6379,slaves=2,sentinels=3
172.30.93.122:26379>

[root@Redis-Node1 ~]# 

可以看到,哨兵已经监听到当前的主机IP端口和运行状态,并且有2台从机,3个哨兵。

 

模拟故障

[root@Redis-Node1 ~]# systemctl stop redis

把Redis主的master停了之后,查看其他节点情况

[root@Redis-Node2 /usr/local/redis]# redis -h 172.30.93.123 -p 6379
172.30.93.123:6379> info replication
# Replication
role:slave
master_host:172.30.93.122
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:128437
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:128437
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:128437
172.30.93.123:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=172.30.93.124,port=6379,state=online,offset=151174,lag=0
master_replid:d20539eba07d1083084387dc8e15f55ce265476f
master_replid2:2d051a800702dd2b2c33937a0ae4bbd8f1338285
master_repl_offset:151174
second_repl_offset:148600
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:151174
172.30.93.123:6379> 

现在我们去看三台服务器的情况,发现刚才的主机(172.30.93.122 6379)已经停机了,而哨兵(Sentinel)通过选举机制选举了从机(172.30.93.123 6379)作为了新的主机,还有一个从节点(172.30.93.124 6379)

到此,主从+哨兵的集群架构搭建完成

 

本文分享完毕,感谢支持点赞~~

posted @ 2021-01-07 09:27  背锅的Mike  阅读(152)  评论(0编辑  收藏  举报