深入理解Redis集群主从复制原理

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 该文章主要探讨了Redis集群中的主从复制原理,包括为何需要主从复制、配置方法、复制流程以及一些高级特性。

一、首先思考一个问题,为什么redis性能这么高还需要分布式方案?

1、实现更高性能:高并发应用,单机性能会有影响,需要更多redis服务器分担压力,实现负载均衡

2、实现高可用:如果单机,防止宕机/硬件故障

3、实现可扩展:单机内存和硬件有限制,实现横向扩展

冗余或者分片存储实现如上特性。

二、主从复制-replication配置

和Kafka,Mysql,Rocketmq一样,redis支持集群部署,集群节点有master和slave之分,主节点是master,从节点是slave(最新叫副本replica).slave会通过复制机制,从master同步最新的数据。Redis提供了非常方便的命令开启主从​复制。

如何配置开启主从复制?

以本机搭建伪集群为例,6379端口是从节点,6378作为主节点。

1、从节点redis.conf配置 replicaof masterip masterport 从节点启动后,自动连接到master节点,开始同步数据.

如果换了新的master节点,这个配置会被重写。

2、或者在redis-server程序启动时候指定

./redis-server --replicaof masterip masterport

3、或者登录客户端,执行如下命令

slaveof masterip masterport

注意这种方式是运行过程中修改,可以实现故障转移

注意: 一个从节点也可以是其他节点的主节点,形成级联复制的关系。但是其他节点也是从顶层主节点同步数据。

配置好集群后,通过info replication查看集群状态

通过role命令,可以查看节点在集群中的角色信息

注意从节点是只读的。写命令会报错。

slave如何退出集群? 可以执行如下命令:

slaveof no one

三、主从复制的流程

1、首先是副本-replica加入集群

2、与master建立连接,通过定时器定时检查是否要从主节点同步数据

​源码说明:​

//每1s执行这个方法void replicationCron(void) {    ...    //检查是否需要连接到master 如果是REPL_STATE_CONNECT状态,必须连接到master    //#define REPL_STATE_CONNECT 1  Must connect to master     if (server.repl_state == REPL_STATE_CONNECT) {        serverLog(LL_NOTICE,"Connecting to MASTER %s:%d",            server.masterhost, server.masterport);        //和master创建连接            if (connectWithMaster() == C_OK) {            serverLog(LL_NOTICE,"MASTER <-> REPLICA sync started");        }    }        //发送ping命令给slave     if ((replication_cron_loops % server.repl_ping_slave_period) == 0 &&        listLength(server.slaves))    {        /* Note that we don't send the PING if the clients are paused during         * a Redis Cluster manual failover: the PING we send will otherwise         * alter the replication offsets of master and slave, and will no longer         * match the one stored into 'mf_master_offset' state. */        int manual_failover_in_progress =            server.cluster_enabled &&            server.cluster->mf_end &&            clientsArePaused();​        if (!manual_failover_in_progress) {            ping_argv[0] = createStringObject("PING",4);            replicationFeedSlaves(server.slaves, server.slaveseldb,                ping_argv, 1);            decrRefCount(ping_argv[0]);        }    }        //发送换行符到所有slave,告诉slave等待接收rdb文件    listRewind(server.slaves,&li);    while((ln = listNext(&li))) {        client *slave = ln->value;​        int is_presync =            (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START ||            (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_END &&             server.rdb_child_type != RDB_CHILD_TYPE_SOCKET));​        if (is_presync) {            if (write(slave->fd, "\n", 1) == -1) {                /* Don't worry about socket errors, it's just a ping. */            }        }    }    ...}

3、全量复制流程-支持无盘复制或者rdb持久化复制

当slave连接到master后,使用psync(以前是sync命令,它不允许部分重新同步,所以现在改用PSYNC)命令初始化复制,将主节点replication id和处理过最大offset发送到master。

master节点拥有如下两个属性,一个replication id(标志实例),一个offset(标志写入从节点的stream)

Replication ID, offset

如果主节点缓冲区中没有足够的积压工作,或者如果复制副本引用的是不再已知的历史记录(复制ID),则会发生完全重新同步

​源码说明:​

    //没有在rdb进程,没有aof重写进程    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {
   
           time_t idle, max_idle = 0;        int slaves_waiting = 0;        int mincapa = -1;        listNode *ln;        listIter li;listRewind(server.slaves,&li);        while((ln = listNext(&li))) {
   
               client *slave = ln->value;            //判断slave是否是等待bgsave状态            if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) {
   
               //多久没有发送心跳或查询数据了 空闲时间间隔                idle = server.unixtime - slave->lastinteraction;                if (idle > max_idle) max_idle = idle;                slaves_waiting++;                mincapa = (mincapa == -1) ? slave->slave_capa :                                            (mincapa & slave->slave_capa);            }        }​        if (slaves_waiting &&            (!server.repl_diskless_sync ||             max_idle > server.repl_diskless_sync_delay))        {
   
               /* Start the BGSAVE. The called function may start a             * BGSAVE with socket target or disk target depending on the             * configuration and slaves capabilities. */             //bgsave rdb生成            startBgsaveForReplication(mincapa);        }    }

复制过程中,slave状态转换流程。

4、​命令传播阶段,执行完全量同步后,主从会进行命令传播​实现数据一致。

四、复制id理解

每次实例作为主实例从头开始重新启动,或者将复制副本提升为主实例,都会为此实例生成一个新的复制ID。如果两个replica的复制id相同,则他们可能在不同的时间,有相同的数据,对于保存最新数据集的给定历史记录(复制ID),偏移量作为一个逻辑时间来理解。需要通过Replication ID, offset两个数据来判断。用来判断从节点同步数据到哪了​。

五、主从复制常见问题

1、slave本身有数据,会怎么样?

slave先删除自身的数据,再用rdb文件加载。

2、生成rdb文件的过程中,客户端写命令怎么处理?

保存到内存缓存中,rdb发送完成后发送到slave。

3、Redis复制如何处理key过期的?

1、副本不会使key过期,而是等待主机使key过期。当主机使key过期(或由于LRU而将其逐出)时,它将合成一个DEL命令,该命令将传输到所有副本。

2、但是,由于主机驱动的expire,有时副本可能仍然具有逻辑上已过期的内存密钥,因为主服务器无法及时提供DEL命令。为了处理这个问题,副本使用它的逻辑时钟来报告一个key不存在,只用于不违反数据集一致性的读取操作(因为来自主服务器的新命令将到达)

3、在Lua脚本执行期间,不执行密钥过期。当Lua脚本运行时,从概念上讲,主节点中的时间是冻结的,因此给定的键在脚本运行的所有时间内都将存在或不存在。这可以防止key在脚本中间过期,并且需要key才能以保证在数据集中具有相同效果的方式将相同的脚本发送到副本。

一旦复制副本升级为主副本,它将开始独立地使key过期,并且不需要旧主副本的任何帮助。

六、主从复制总结

1、解决了数据备份的问题,但是rdb文件大,传输大文件,恢复时间也长

2、如果master异常,需要手工将replica选举为master

3、1主多从,1主1从的情况下,还是存在单点问题

4、Redis版本2.8.18​后支持无盘复制,性能更高。

七、复制说明

1、默认用异步复制,通过异步确认同步的命令数量

2、1个master可以有多个副本

3、副本也可以有自己的副本,从redis4.0开始,副本都会从主节点接收完全相同的复制流

4、复制既可以用于可扩展性,也可以用于只读查询的多个副本​

相关文章
|
8天前
|
存储 负载均衡 NoSQL
Redis主从复制
在分布式系统中,为解决单点故障和提升性能,常采用Redis主从复制架构。通过将数据复制到多个从节点,实现读写分离、负载均衡及高可用性,同时支持多种拓扑结构以适应不同场景需求。
|
2月前
|
负载均衡 NoSQL Redis
【赵渝强老师】Redis的主从复制集群
Redis主从复制是指将一台Redis服务器的数据复制到其他Redis服务器,实现数据热备份、故障恢复、负载均衡及高可用架构的基础。主节点负责写操作,从节点同步数据并可提供读服务,提升并发处理能力。
|
7月前
|
消息中间件 缓存 NoSQL
Redis原理—5.性能和使用总结
本文详细探讨了Redis的阻塞原因、性能优化、缓存相关问题及数据库与缓存的一致性问题。同时还列举了不同缓存操作方案下的并发情况,帮助读者理解并选择合适的缓存管理策略。最终得出结论,在实际应用中应尽量采用“先更新数据库再删除缓存”的方案,并结合异步重试机制来保证数据的一致性和系统的高性能。
Redis原理—5.性能和使用总结
|
7月前
|
NoSQL 算法 安全
Redis原理—1.Redis数据结构
本文介绍了Redis 的主要数据结构及应用。
Redis原理—1.Redis数据结构
|
7月前
|
缓存 NoSQL Redis
Redis原理—2.单机数据库的实现
本文概述了Redis数据库的核心结构和操作机制。
Redis原理—2.单机数据库的实现
|
NoSQL Redis
Redis 执行 Lua保证原子性原理
Redis 执行 Lua 保证原子性原理
857 1
|
7月前
|
存储 缓存 NoSQL
Redis原理—4.核心原理摘要
Redis 是一个基于内存的高性能NoSQL数据库,支持分布式集群和持久化。其网络通信模型采用多路复用监听与文件事件机制,通过单线程串行化处理大量并发请求,确保高效运行。本文主要简单介绍了 Redis 的核心特性。
|
7月前
|
缓存 NoSQL Redis
Redis原理—3.复制、哨兵和集群
详细介绍了Redis的复制原理、哨兵原理和集群原理。
|
9月前
|
NoSQL 关系型数据库 Redis
《docker高级篇(大厂进阶):1.Docker复杂安装详说》包括:安装mysql主从复制、安装redis集群
《docker高级篇(大厂进阶):1.Docker复杂安装详说》包括:安装mysql主从复制、安装redis集群
247 14
|
缓存 NoSQL Linux
redis的原理(三)
redis的原理(三)
redis的原理(三)