为什么需要主从复制
Redis主从复制
实现主从复制架构的手段:一主多从
1 | #从节点的配置文件添加,主节点的ip端口,表示以该节点为主节点实现主从复制。 |
从节点不能写入数据(只读),只能从 m
aster
节点同步数据。get
成功,set
失败。
从节点取消指定主节点,自己成为主节点,也就是从节点断开slave
模式:slave no one
命令。
主从复制原理
连接阶段
- slave 节点启动时,会在自己本地保存master 节点的信息,包括ip port等。
- slave 节点内部有个定时任务 replicationCron,每隔1秒钟检查是否有新的master节点要连接和复制,如果有,就跟master节点建立一个Socket连接,如果连接成功,从节点为该Socket连接创建一个专门处理复制工作的文件事件处理器,负责后续的复制工作,如接收RDB命令,接收命令传播等。
- 当从节点变成了主节点的一个客户端之后,会给主节点发送 ping 请求。
数据同步阶段
数据一致性延迟是不可避免的,只能通过优化网络来尽可能减少数据延时时间。
1 | repl-disable-tcp-nodelay no |
上面配置的作用是:当设置为yes时,TCP会对多个写命令TCP包进行合并一次性发送从而减少带宽,但是发送的频率会降低,从节点的数据延时会增加,一致性变差,具体发送频率与linux内核参数有关,默认为40ms,当设置为no时,TCP会立马把主节点的数据发送给从节点,带宽增加但延时变小。
一般来说,只有当应用对 Redis 数据不一致的容忍度较高,且主从节点之间网络状况不好时,才会设置为 yes;多数情况使用默认值 no。
主从复制的不足
- RDB文件过大时,同步耗时。
- 在一主一从或者一主多从情况下,如果主节点挂了,对外提供的写服务就是不可用了(从节点仍然可以对外提供读服务),单点问题没有解决,需要手动进行主从的切换才行,但是这样比较费事费力,还会导致服务一段时间不可用。
所以可以使用哨兵模式来实现自动的主从切换和故障转移。
Docker下redis的主从配置
拉取redis镜像
1 | docker pull redis |
启动3个redis容器
启动3个redis容器服务,分别使用到6379、6380、6381端口
1 | docker run redis-6379 -p 6379:6379 -d |
查看容器
1 | docker ps |
进入容器
1 | docker exec -it 容器ID/name redis-cli |
redis集群配置
看容器内网的ip地址
1 | docker inspect 容器ID/name |
查看当前redis角色(主还是从)
进入docker容器内部,查看当前redis角色(主还是从)
1 | [root@tcy1 tcy]# docker exec -it 容器ID /bin/bash |
使用redis-cli命令修改redis-6380、redis-6381的主机为172.17.0.3:6379
1 | SLAVEOF 172.17.0.3 6379 |
配置Sentinel哨兵
进入3台redis容器内部进行配置,在容器根目录里面创建sentinel.conf文件文件
内容为:sentinel monitor mymaster 172.17.0.1 6379 1
1 | [root@tcy1 tcy]# docker exec -it a9fa77adc598 /bin/bash |
如果出现:bash: vim: command not found
解决:
- apt-get update
- apt-get install vim
启动哨兵
1 | redis-sentinel /sentinel.conf |
哨兵模式
哨兵(Sentinel)模式的大致思路是创建一台服务器来监控所有的Redis服务节点状态,比如master节点超过一定时间没有给监控服务器发送心跳报文,就把master标记为下线,然后把某个slave节点变成master节点,重写进行数据的同步。应用程序(客户端)每一次都是从这个监控服务器拿到master的地址。
如果监控服务器本身出问题了怎么办?那我们就拿不到 master 的地址了,应用也没有办法访问。可以对sentinel服务器进行集群。
从 Redis2.8 版本起,提供了一个稳定版本的 Sentinel(哨兵),用来解决高可用的问题。它是一个特殊状态的 redis 实例。
我们会启动一个或者多个 Sentinel 的服务(通过 src/redis-sentinel),它本质上只是一个运行在特殊模式之下的 Redis,Sentinel 通过 info 命令得到被监听 Redis 机器的master,slave 等信息。
为了保证监控服务器的可用性,我们会对 Sentinel 做集群的部署。
Sentinel 既监控所有的 Redis 服务,Sentinel 之间也相互监控。
注意:Sentinel 本身没有主从之分,只有 Redis 服务节点有主从之分。
此时就要以下角色
- sentinel集合。
- redis服务节点group(一主多从为一个group)。
服务下线
Sentinel默认以每秒一次的频率向各Redis服务节点发送PING命令,如果在down-after-milliseconds 内都没有收到有效回复,Sentinel 会将该服务器标记为主观下线。
1 | sentinel down-after-milliseconds <master-name> <milliseconds> #sentinel.conf |
这个时候 Sentinel 节点会继续询问其他的 Sentinel 节点,确认这个节点是否下线,如果多数(超过半数) Sentinel 节点都认为 master 下线,master 才真正确认被下线(客观下线),这个时候就需要重新选举 master。
由于Sentinel实现了集群,所以首先需要通过Raft算法在Sentinel集群中选取出一个临时Leader来对下线的master进行故障转移。
故障转移
选举出的Leader Sentinel会向某个从节点发送 slaveof no one 使它成为一个独立主节点,然后向其余从节点发送slaveof xxx xxx ,使得这些从节点成为新主节点的从节点,并进行数据的同步,然后故障转移完成。
如何从多个slave节点中选择一个成为新的master节点:
Sentinel搭建实战
环境:
需要三个服务节点一主二从和三个sentinel集群节点,由于虚拟机不够,这里就只用三台虚拟机,每台虚拟机部署一个服务节点和一个sentinel节点。
ip |
节点角色/端口 |
---|---|
192.168.18.140 | master 6379 / sentinel 26379 |
192.168.18.141 | salve 6379 / sentinel 26379 |
192.168.18.142 | slave 6379 / sentinel 26379 |
修改从服务节点141、142的配置文件redis.conf,
添加 slaveof 192.168.18.140 6379。
或在redis-cli 内执行命令行 SLAVEOF 192.168.18.140 6379
来建立主从(主无需执行或修改 当前命令)
修改三个sentinel节点的配置文件sentinel.conf:【哨兵配置】
1 | daemonize yes #以服务进程模式启动 |
先启动三台服务节点再启动三台sentinel节点:
1 | ./redis-server ../redis.conf |
验证
- 使用info replication命令查看服务节点的状态。
- 故意关闭shutdown主节点。
- 经过一定时间后,某一台从节点会被升为主节点。自动故障转移成功。
哨兵机制的不足
主从切换时会丢失数据,主从复制是异步执行的,master节点写入数据后没来得及同步到slave节点就发送了故障,进行主从切换,该没有同步的数据就会丢失。
只能单点写,没有解决水平扩容的问题。
这种主从模式所以节点保存的数据都是一样的,无法对数据进行水平扩容,如果数据量非常大,这个时候我们需要多个 master-slave 的 group,把数据分布到不同的 group 中。
返回 redis 系列