聊聊Redis中的主从同步和哨兵模式
本篇文章带大家深入了解一下Redis中的主从同步和哨兵模式,介绍一下开启关闭主从同步、搭建启动Sentinel的方法,希望对大家有所帮助!
主从同步
主从同步(主从复制)是 Redis
高可用服务的基石,也是多机运行中最基础的一个。【相关推荐:Redis视频教程】
我们把主要存储数据的节点叫做主节点 (master
),把其他通过复制主节点数据的副本节点叫做从节点 (slave
),如下图所示:
在 Redis
中一个主节点可以拥有多个从节点,一个从节点也可以是其他服务器的主节点,如下图所示:
主从同步的优点
主从同步具有以下三个优点:
- 性能方面:有了主从同步之后,可以把查询任务分配给从服务器,用主服务器来执行写操作,这样极大的提高了程序运行的效率,把所有压力分摊到各个服务器了;
- 高可用:当有了主从同步之后,当主服务器节点宕机之后,可以很迅速的把从节点提升为主节点,为
Redis
服务器的宕机恢复节省了宝贵的时间; - 防止数据丢失:当主服务器磁盘坏掉之后,其他从服务器还保留着相关的数据,不至于数据全部丢失。
开启主从同步
运行中设置从服务器
在 Redis
运行过程中,我们可以使用 replicaof host port
命令,把自己设置为目标 IP
的从服务器。
如果主服务设置了密码,需要在从服务器输入主服务器的密码,使用 config set masterauth 主服务密码
命令的方式
在执行完 replicaof
命令之后,从服务器的数据会被清空,主服务会把它的数据副本同步给从服务器。
启动时设置从服务器
可以使用命令 redis-server --port 6380 --replicaof 127.0.0.1 6379
将自己设置成目标服务器的从服务器。
数据同步
完整数据同步
当有新的从服务器连接时,为了保障多个数据库的一致性,主服务器会执行一次 bgsave
命令生成一个 RDB
文件,然后再以 Socket
的方式发送给从服务器,从服务器收到 RDB
文件之后再把所有的数据加载到自己的程序中,就完成了一次全量的数据同步。
部分数据同步
在 Redis 2.8
之前每次从服务器离线再重新上线之前,主服务器会进行一次完整的数据同步,然后这种情况如果发生在离线时间比较短的情况下,只有少量的数据不同步却要同步所有的数据是非常笨拙和不划算的,在 Redis 2.8
这个功能得到了优化。
Redis 2.8
的优化方法是当从服务离线之后,主服务器会把离线之后的写入命令,存储在一个特定大小的队列中,队列是可以保证先进先出的执行顺序的,当从服务器重写恢复上线之后,主服务会判断离线这段时间内的命令是否还在队列中,如果在就直接把队列中的数据发送给从服务器,这样就避免了完整同步的资源浪费。
存储离线命令的队列大小默认是 1MB,使用者可以自行修改队列大小的配置项 repl-backlog-size
。
无盘数据同步
在第一次主从连接的时候,会先产生一个 RDB
文件,再把 RDB
文件发送给从服务器,如果主服务器是非固态硬盘的时候,系统的 I/O
操作是非常高的。
Redis 2.8.18
新增了无盘复制功能,无盘复制功能不会在本地创建 RDB
文件,而是会派生出一个子进程,然后由子进程通过 Socket
的方式,直接将 RDB
文件写入到从服务器,这样主服务器就可以在不创建 RDB
文件的情况下,完成与从服务器的数据同步。
要使用无须复制功能,只需把配置项 repl-diskless-sync
的值设置为 yes
即可,它默认配置值为 no
。
查询服务器的角色
使用 role
命令,来查询当前服务器的主从角色信息。
关闭主从同步
可以使用 replicaof no one
命令来停止从服务器的复制。
执行了 replicaof no one
命令之后,自己就从服务器变成主服务器了。
服务器类型的转换并不会影响数据,这台服务器的数据将会被保留。
注意事项
数据一致性问题
当从服务器已经完成和主服务的数据同步之后,再新增的命令会以异步的方式发送至从服务器,在这个过程中主从同步会有短暂的数据不一致,如在这个异步同步发生之前主服务器宕机了,会造成数据不一致。
从服务器只读性
默认情况下,处于复制模式的主服务器既可以执行写操作也可以执行读操作,而从服务器则只能执行读操作。
可以在从服务器上执行 config set replica-read-only no
命令,使从服务器开启写模式,但需要注意以下几点:
- 在从服务器上写的数据不会同步到主服务器;
- 当键值相同时主服务器上的数据可以覆盖从服务器;
- 在进行完整数据同步时,从服务器数据会被清空。
复制命令的变化
Redis 5.0
之前使用的复制命令是 slaveof
,在 Redis 5.0
之后复制命令才被改为 replicaof
,在高版本(Redis 5+
)中我们应该尽量使用 replicaof
,因为 slaveof
命令可能会被随时废弃掉。
哨兵模式
主从复制模式,它是属于
Redis
多机运行的基础,但这种模式本身存在一个致命的问题,当主节点奔溃之后,需要人工干预才能恢复Redis
的正常使用。我们需要一个自动的工具——
Redis Sentinel
(哨兵模式)来把手动的过程变成自动的,让Redis
拥有自动容灾恢复(failover
)的能力。哨兵就相当于对主从服务器做一个监视的任务。一旦发现主服务器宕机了,就迅速启动相应的规则将某一台从服务器升级为主服务器,无需人工干预,更稳定更快。
Redis Sentinel
的最小分配单位是一主一从。
Redis Sentinel 搭建
使用命令 ./src/redis-sentinel sentinel.conf
来启动 Sentinel
,在启动它时必须设置一个 sentinel.conf
文件,这个配置文件中必须包含监听的主节点信息:
sentinel monitor master-name ip port quorum
其中:
master-name
表示给监视的主节点起一个名称;ip
表示主节点的 IP;port
表示主节点的端口;quorum
表示确认主节点下线的Sentinel
数量,如果quorum
设置为 1 表示只要有一台Sentinel
判断它下线了,就可以确认它真的下线了。
如果主节点服务器 Redis
有密码,sentinel.conf
必须包含以下内容:
sentinel monitor mymaster 127.0.0.1 6379 1 sentinel auth-pass mymaster pwd654321
启动 Sentinel 集群
生产环境我们不会只启动一台 Sentinel
,因为如果启动一台 Sentinel
假如它不幸宕机的话,就不能提供自动容灾的服务了,不符合我们高可用的宗旨,所以我们会在不同的物理机上启动多个 Sentinel
来组成 Sentinel
集群,来保证 Redis
服务的高可用。
启动 Sentinel
集群的方法很简单,和上面启动单台的方式一样,我们只需要把多个 Sentinel
监听到一个主服务器节点,那么多个 Sentinel
就会自动发现彼此,并组成一个 Sentinel
集群。
一般情况下 Sentinel
集群的数量取大于 1 的奇数,quorum
的参数就设置为一半加 1,例如 5 就设置为 3,7 就设置为 4。
两个概念:主观下线和客观下线。
当 Sentinel
集群中,有一个 Sentinel
认为主服务器已经下线时,它会将这个主服务器标记为主观下线(Subjectively Down
,SDOWN
),然后询问集群中的其他 Sentinel
,是否也认为该服务器已下线,当同意主服务器已下线的 Sentinel
数量达到 quorum
参数所指定的数量时,Sentinel
就会将相应的主服务器标记为客观下线(Objectively down,ODOWN
),然后开始对其进行故障转移。
主服务竞选规则
新主节点竞选优先级设置
redis.conf
中的 replica-priority
选项来设置竞选新主节点的优先级,它的默认值是 100,它的最大值也是 100,这个值越小它的权重就越高。
新主节点竞选规则
新主节点的竞选会排除不符合条件的从节点,然后再剩余的从节点按照优先级来挑选。
存在以下条件的从节点会被排除:
排除所有已经下线以及长时间没有回复心跳检测的疑似已下线从服务器;
排除所有长时间没有与主服务器通信,数据状态过时的从服务器;
排除所有优先级(
replica-priority
)为 0 的服务器。
符合条件的从节点竞选顺序:
优先级最高的从节点将会作为新主节点;
优先级相等则判断复制偏移量,偏移量最大的从节点获胜;
如果以上两个条件都相同,选择
Redis
运行时随机生成 ID 最小那个为新的主服务器。
旧主节点恢复上线
如果之前的旧主节点恢复上线,会作为从节点运行在主从服务器模式中。
哨兵工作原理
首先每个 Sentinel
会以每秒钟 1 次的频率,向已知的主服务器、从服务器和以及其他 Sentinel
实例,发送一个 PING 命令。
如果最后一次有效回复 PING
命令的时间超过 down-after-milliseconds
所配置的值(默认 30s),那么这个实例会被 Sentinel
标记为主观下线。
如果一个主服务器被标记为主观下线,那么正在监视这个主服务器的所有 Sentinel
节点,要以每秒 1 次的频率确认主服务器的确进入了主观下线状态。
如果有足够数量(quorum
配置值)的 Sentinel
在指定的时间范围内同意这一判断,那么这个主服务器被标记为客观下线。此时所有的 Sentinel
会按照规则协商自动选出新的主节点。
注意:一个有效的 PING
回复可以是:+PONG、-LOADING
或者 -MASTERDOWN
。如果返回值非以上三种回复,或者在指定时间内没有回复 PING
命令, 那么 Sentinel
认为服务器返回的回复无效(non-valid
)。
Sentinel 命令操作
Sentinel 可以监视多台主节点,而不是只能监视一台服务器。想要监视多台主节点只需要在配置文件中设置多个 sentinel monitor master-name ip port quorum
即可,我们通过 master-name
来区分不同的主节点。
查询所有被监控的主服务器信息
sentinel masters
查询某个主节点的信息
sentinel master master-name
查看某个主节点的 IP 和端口
sentinel get-master-addr-by-name master-name
查询从节点的信息
sentinel replicas mymaster
或 sentinel slaves master-name
查询 Sentinel 集群中的其他 Sentinel 信息
sentinel sentinels master-name
检查可用 Sentinel 的数量
sentinel ckquorum master-name
强制故障转移
sentinel failover master-name
在线修改配置信息
在 Redis 2.8.4
之前如果需要修改 Sentinel
的配置文件,需要重启 Sentinel
。
Redis 2.8.4
之后,我们可以在线修改配置文件了。
增加监视主节点
sentinel monitor mymaster IP Port Quorum
命令。
移除主节点的监视
使用 sentinel remove master-name
命令。
修改 quorum 参数
使用 sentinel set master-name quorum n
命令。
quorum
参数用来表示确认主节点下线的 Sentinel
数量,如果 quorum
设置为 1 表示只要有一台 Sentinel 确认主观下线后,这个主节点就客观(真正地)下线了。
以上所有对配置文件的修改,都会自动被刷新到物理配置文件
sentinel.conf
中
代码实战
import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisSentinelPool; import utils.Config; import java.util.HashSet; import java.util.Set; public class SentinelExample { // master name private static String _MASTER_NAME = "mymaster"; public static void main(String[] args) { // Sentinel 配置信息 Set<String> set = new HashSet<>(); // 连接信息 ip:port set.add("127.0.0.1:26379"); // 创建 Sentinel 连接池 JedisSentinelPool jedisSentinel = new JedisSentinelPool(_MASTER_NAME, set, Config.REDIS_AUTH); // 获取 Redis 客户端 Jedis jedis = jedisSentinel.getResource(); // 设置元素 String setRes = jedis.set("key", "Hello, redis."); System.out.println(setRes); // 获取元素 System.out.println(jedis.get("key")); } }
更多编程相关知识,请访问:编程入门!!
以上就是聊聊Redis中的主从同步和哨兵模式的详细内容,更多请关注其它相关文章!