思维草图
认识
主机更新后根据配置和策略,自动将数据同步到备机的master/slave机制,Master以写为主,Slave以读为主。
为什么要使用主从复制
- 读写分离,性能扩展,降低主服务器的压力
- 容灾,快速恢复,主机挂掉时,从机自动变为主机
主从复制的两种配置方式
配置文件配置
安装的redis,默认的配置端口是6379
现在再复制两份配置文件作为两台从机,端口号改成6380、6381。
使用cp命令将redis.conf复制到创建的对应文件夹中
创建3个新的配置文件,对主机和从机进行配置
第一个文件 redis-6379.conf ,里面的配置内容
# include引用redis.conf内容
include /Users/lihui/Documents/dev-tool/master-slave/redis.conf
# 是否开启后台运行
daemonize yes
# 服务器ip
bind 127.0.0.1
# 配置密码
requirepass 123456
# 相关目录配置
dir /Users/lihui/Documents/dev-tool/master-slave/
logfile /Users/lihui/Documents/dev-tool/master-slave/6379.log
# 端口
port 6379
# rdb文件
dbfilename dump_6379.rdb
# pid文件
pidfile /Users/lihui/Documents/dev-tool/master-slave/var/run/redis_6379.pid
创建第二个文件redis-6380.conf
include /Users/lihui/Documents/dev-tool/master-slave/redis.conf
daemonize yes
bind 127.0.0.1
requirepass 123456
dir /Users/lihui/Documents/dev-tool/master-slave/
port 6380
dbfilename dump_6380.rdb
pidfile /Users/lihui/Documents/dev-tool/master-slave/var/run/redis_6380.pid
logfile /Users/lihui/Documents/dev-tool/master-slave/6380.log
# 指定主机:slaveof 主机ip 端口
slaveof 127.0.0.1 6379
# 主机的密码
masterauth 123456
创建第三个文件
include /Users/lihui/Documents/dev-tool/master-slave/redis.conf
daemonize yes
bind 127.0.0.1
requirepass 123456
dir /Users/lihui/Documents/dev-tool/master-slave/
port 6381
dbfilename dump_6381.rdb
pidfile /Users/lihui/Documents/dev-tool/master-slave/var/run/redis_6381.pid
logfile /Users/lihui/Documents/dev-tool/master-slave/6381.log
# 指定主机:slaveof 主机ip 端口
slaveof 127.0.0.1 6379
# 主机的密码
masterauth 123456
如图
启动master
redis-server /Users/lihui/Documents/dev-tool/master-slave/redis-6379.conf
启动slave
redis-server /Users/lihui/Documents/dev-tool/master-slave/redis-6380.conf
redis-server /Users/lihui/Documents/dev-tool/master-slave/redis-6381.conf
可以看到每一台reids服务器的启动日志
客户端连接主机病查看主机信息
# 连接6379主机
redis-cli -h 127.0.0.1 -p 6379 -a 123456
# 查看6379主机信息
info Replication
# 连接6380主机并查看主机信息
redis-cli -h 127.0.0.1 -p 6380 -a 123456
info Replication
# 连接6381主机并查看主机信息
redis-cli -h 127.0.0.1 -p 6381 -a 123456
info Replication
验证主机从机同步效果
控制台命令配置
还是先复制三份conf的配置文件,但是里面的内容不需要配置主从节点关系
redis-6379.conf
include /Users/lihui/Documents/dev-tool/master-slave/redis.conf
daemonize yes
bind 127.0.0.1
requirepass 123456
dir /Users/lihui/Documents/dev-tool/master-slave/
port 6379
dbfilename dump_6379.rdb
pidfile /Users/lihui/Documents/dev-tool/master-slave/var/run/redis_6379.pid
logfile /Users/lihui/Documents/dev-tool/master-slave/6379.log
redis-6380.conf
include /Users/lihui/Documents/dev-tool/master-slave/redis.conf
daemonize yes
bind 127.0.0.1
requirepass 123456
dir /Users/lihui/Documents/dev-tool/master-slave/
port 6380
dbfilename dump_6380.rdb
pidfile /Users/lihui/Documents/dev-tool/master-slave/var/run/redis_6380.pid
logfile /Users/lihui/Documents/dev-tool/master-slave/6380.log
redis-6381.conf
include /Users/lihui/Documents/dev-tool/master-slave/redis.conf
daemonize yes
bind 127.0.0.1
requirepass 123456
dir /Users/lihui/Documents/dev-tool/master-slave/
port 6381
dbfilename dump_6381.rdb
pidfile /Users/lihui/Documents/dev-tool/master-slave/var/run/redis_6381.pid
logfile /Users/lihui/Documents/dev-tool/master-slave/6380.log
按之前的命令正常启动三个redis服务,这时候这三个redis服务是独立没有关系的。
使用命令将6380设置为6379的从机
redis-cli -h 127.0.0.1 -p 6380 -a 123456
config set masterauth 123456
slaveof 127.0.0.1 6379
使用命令将6381设置为6379的从机
redis-cli -h 127.0.0.1 -p 6381 -a 123456
config set masterauth 123456
slaveof 127.0.0.1 6379
然后进控制台使用命令查看redis服务的信息,可以看到和之前一样的信息。
主从复制原理
- slave启动成功连接到master后(第一次),会给master发送数据同步消息(发送sync命令)
- master接收到slave发来的数据同步消息后,把主服务器的数据进行持久化到rdb文件,同时会收集接收到的用于修改数据的命令,master将传rdb文件发送给你slave,完成一次完全同步
- 全量复制:而slave服务在接收到master发来的rdb文件后,将其存盘并加载到内存
- 增量复制:master继续将收集到的修改命令依次传给slave,完成同步但是只要重新连接master,一次完全同步(全量复制)将会被自动执行
第一次连接成功后进行一次全量数据复制,后续进行增量数据复制。
注意:主机挂掉后,从机会待命,小弟还是小弟,会等着大哥恢复,不会篡位。
当主机挂掉之后,我们可以手动将从机设置为主机
如,想让6380成为主机,那么在6380的控制台输入
slaveof no one
然后再去其他slave上面执行 slaveof 命令将其挂在这台服务器上。
这种主备切换有个缺点:需要手动去执行命令去操作,不是太方便。
采用另外一种方式:哨兵模式,主挂掉之后,自动从slave中选举一个作为主机,自动实现故障转 移。
哨兵(Sentinel)模式
介绍
能够自动监控master是否发生故障,如果故障了会根据投票数从slave中挑选一个作为master,其他的slave会自动转向同步新的master,实现故障自动转移。
原理
-
sentinel会按照指定的频率给master发送ping请求,看看master是否还活着,若master在指定时间内未正常响应sentinel发送的ping请求,sentinel则认为master挂掉了,但是这种情况存在误判的可能,比如:可能master并没有挂,只是sentinel和master之间的网络不通导致,导致ping失败。
-
为了避免误判,通常会启动多个sentinel,一般是奇数个,比如3个,那么可以指定当有多个sentinel都觉得master挂掉了,此时才断定master真的挂掉了,通常这个值设置为sentinel的一半,比如sentinel 的数量是3个,那么这个量就可以设置为2个。
-
slaveof no one 当多个sentinel经过判定,断定master确实挂掉了,接下来sentinel会进行故障转移:会从slave中投票选出一个服务器,将其升级为新的主服务器, 并让失效主服务器的其他从服务器slaveof指向新的主服务器;
-
当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
配置示例
之前的一台主机,两台从机已经配置好启动了。现在来配置三台监视主机的哨兵服务。
创建sentinel-26379.conf文件
# 配置文件目录
dir "/Users/lihui/Documents/dev-tool/master-slave"
# 日志文件位置
logfile "./sentinel-26379.log"
# pid文件
pidfile "/Users/lihui/Documents/dev-tool/master-slave/var/run/sentinel_26379.pid"
# 是否后台运行
daemonize yes
# 端口
port 26379
# 监控主服务器master的名字:mymaster,IP:127.0.0.1,port:6379,最后的数字2表示当Sentinel集群中有2个Sentinel认为master存在故障不可用,则进行自动故障转移
sentinel monitor mymaster 127.0.0.1 6379 2
# master响应超时时间(毫秒),Sentinel会向master发送ping来确认master,如果在20秒内,ping不通master,则主观认为master不可用
sentinel down-after-milliseconds mymaster 60000
# 故障转移超时时间(毫秒),如果3分钟内没有完成故障转移操作,则视为转移失败
# 故障转移之后,进行新的主从复制,配置项指定了最多有多少个slave对新的master进行同步,那可以理解为1是串行复制,大于1是并行复制
# 指定mymaster主的密码(没有就不指定)
sentinel auth-pass mymaster 123456
# Generated by CONFIG REWRITE
protected-mode no
user default on nopass ~* &* +@all
sentinel myid be5608edf5bcb37c46af76860e005dc4b396c16a
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel current-epoch 0
sentinel known-replica mymaster 127.0.0.1 6381
sentinel known-replica mymaster 127.0.0.1 6380
sentinel-26380.conf
# 配置文件目录
dir /Users/lihui/Documents/dev-tool/master-slave/
# 日志文件位置
logfile "./sentinel-26380.log"
# pid文件
pidfile /Users/lihui/Documents/dev-tool/master-slave/var/run/sentinel_26380.pid
# 是否后台运行
daemonize yes
# 端口
port 26380
# 监控主服务器master的名字:mymaster,IP:127.0.0.1,port:6379,最后的数字2表示当
Sentinel集群中有2个Sentinel认为master存在故障不可用,则进行自动故障转移
sentinel monitor mymaster 127.0.0.1 6379 2
# master响应超时时间(毫秒),Sentinel会向master发送ping来确认master,如果在20秒内,ping
不通master,则主观认为master不可用
sentinel down-after-milliseconds mymaster 60000
# 故障转移超时时间(毫秒),如果3分钟内没有完成故障转移操作,则视为转移失败
sentinel failover-timeout mymaster 180000
# 故障转移之后,进行新的主从复制,配置项指定了最多有多少个slave对新的master进行同步,那可以理
解为1是串行复制,大于1是并行复制
sentinel parallel-syncs mymaster 1
# 指定mymaster主的密码(没有就不指定)
sentinel auth-pass mymaster 123456
sentinel-26381.conf
# 配置文件目录
dir /Users/lihui/Documents/dev-tool/master-slave/
# 日志文件位置
logfile "./sentinel-26381.log"
# pid文件
pidfile /Users/lihui/Documents/dev-tool/master-slave/var/run/sentinel_26381.pid
# 是否后台运行
daemonize yes
# 端口
port 26381
# 监控主服务器master的名字:mymaster,IP:127.0.0.1,port:6379,最后的数字2表示当
Sentinel集群中有2个Sentinel认为master存在故障不可用,则进行自动故障转移
sentinel monitor mymaster 127.0.0.1 6379 2
# master响应超时时间(毫秒),Sentinel会向master发送ping来确认master,如果在20秒内,ping
不通master,则主观认为master不可用
sentinel down-after-milliseconds mymaster 60000
# 故障转移超时时间(毫秒),如果3分钟内没有完成故障转移操作,则视为转移失败
sentinel failover-timeout mymaster 180000
# 故障转移之后,进行新的主从复制,配置项指定了最多有多少个slave对新的master进行同步,那可以理
解为1是串行复制,大于1是并行复制
sentinel parallel-syncs mymaster 1
# 指定mymaster主的密码(没有就不指定)
sentinel auth-pass mymaster 123456
启动三个sentinel
redis-sentinel /Users/lihui/Documents/dev-tool/master-slave/sentinel-26379.conf
redis-sentinel /Users/lihui/Documents/dev-tool/master-slave/sentinel-26380.conf
redis-sentinel /Users/lihui/Documents/dev-tool/master-slave/sentinel-26381.conf
查看3个sentinel的信息
redis-cli -p sentinel的端口
info sentinel
可以看到输出信息
现在停止主机6379服务,等待几分钟,完成故障转移
然后在6380的主机上使用info replication查看信息
可以看到6381服务自动变成了主机
这时候当6379服务又重新连接,恢复正常
可以看到之前的主机,自动变为从机,挂在新的主机之下了
SpringBoot整合Sentinel模式
引入对应的maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
application.properties中配置redis sentinel信息
# redis sentinel主服务名称,来源于:sentinel配置文件中sentinel monitor后面跟的那个名称
spring.redis.sentinel.master=mymaster
# sentinel节点列表(host:port),多个之间用逗号隔开
spring.redis.sentinel.nodes=ip:26379,ip:26380,ip:26381
# sentinel密码
#spring.redis.sentinel.password=
# 连接超时时间(毫秒)
spring.redis.timeout=60000
# Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
spring.redis.database=0