redis有了主从复制还需要集群吗?Redis主从复制原理及注意事项
redis有了主从复制还需要集群吗?Redis主从复制原理及注意事项数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。7.能够通过replication来避免master每次持久化时都将整个数据集持久化到硬盘中。只需把master配置为不进行持久化操作(把配置文件中持久化相关的配置项注释掉即可),然后连接上一个slave,这个slave则被配置持久化选项。4.master在进行replication时是非阻塞的,在replication期间,master依然能够处理客户端的请求。5.slave在replication期间也是非阻塞的,也可以接受来自客户端的请求,但是它用的是之前的旧数据。可以通过配置来决定slave是否在进行replication时用旧数据响应客户端的请求,如果配置为否,那么slave将会返回一个错误消息给客户端。不过当新的数据接收完全后,必须将新数据与旧数据替换,即删除旧数据,在替换数据的这个时间窗口内,slave将会
主从复制特点主从复制,是指将一台redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave) 数据的复制是单向的,只能由主节点到从节点.具有以下特点:
1.异步复制 从2.8版本开始的。
2.允许单个master配置多个slave
3.允许master -> slave -> slave 模式
4.master在进行replication时是非阻塞的,在replication期间,master依然能够处理客户端的请求。
5.slave在replication期间也是非阻塞的,也可以接受来自客户端的请求,但是它用的是之前的旧数据。可以通过配置来决定slave是否在进行replication时用旧数据响应客户端的请求,如果配置为否,那么slave将会返回一个错误消息给客户端。不过当新的数据接收完全后,必须将新数据与旧数据替换,即删除旧数据,在替换数据的这个时间窗口内,slave将会拒绝客户端的请求和连接。
6.一般使用replication来可以实现扩展性,例如说,可以将多个slave配置为只读,或者是纯粹的数据冗余备份。
7.能够通过replication来避免master每次持久化时都将整个数据集持久化到硬盘中。只需把master配置为不进行持久化操作(把配置文件中持久化相关的配置项注释掉即可),然后连接上一个slave,这个slave则被配置持久化选项。
主从复制的作用数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
高可用基石:主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
实现主从复制方法方法一:命令行
redis> slaveof master_ip master port
取消复制:redis> slaveof no one
取消复制后重新做另一个实例的从时会先清掉数据,然后重新生成。
方法二:写入文件配置
slaveof ip port
masterauth 主节点密码
slave-read-only yes ##从节点只能进行读的操作。
replication工作原理(全量复制)同步过程:
slave向master发送 psync? -1 命令,要求master主机同步数据。
master 向 slave 返回runid 和偏移量
slave 保存 master 的信息
master执行bgsave命令,创建RDB文件,在创建RDB文件期间的命令将保存在缓冲区中。(消耗master服务器大量的CPU、内存和磁盘I/O资源)
当master执行完BGSAVE后,会向slave发送RDB文件 (消耗master服务器大量的网络资源,并对master服务器响应命令请求的时间产生影响)
master再将之前缓存在内存中的命令发送给slave(replication buffer 缓存区)
清空slave中的老数据
slave加载RDB文件将数据库状态更新至master执行bgsave时的数据库状态(从在加载的过程中会因为阻塞而没办法处理命令请求)
slave缓冲区数据的加载
master同步长连接持续把写命令发送给slave,以保证数据的一致
全量复制开销:bgsave时间;rdb文件网络传输时间;从节点清空数据时间;从节点加载rdb的时间;可能的AOF重写时间
注意:在Redis2.8之前,主从断线或则重启之后再重连接,都需要做一次完整的sync操作(5步骤),即使断线期间只有几条的更新操作或则是没有操作,导致系统资源极度浪费。Redis2.8之后,会用一个psync来替换sync,不会进行完成的sync操作,只需要同步断线期间的记录。相关参数:repl-backlog-size、repl-backlog-ttl
Redis目前的复制是异步的,只保证最终一致性,而不是强一致性(主从数据库的更新还是分先后,先主后从)。要是一致性要求高的应用,目前还是读写都在主库上去。
replication工作原理(部分复制)从2.8版本开始,slave与master能够在网络连接断开重连后只进行部分数据复制。
master会在其内存中创建一个复制流的等待队列,master和它所有的slave都维护了复制的数据下标和master的进程id,因此,当网络连接断开后,slave会请求master继续进行未完成的复制,从所记录的数据下标开始。如果进程id变化了,或者数据下标不可用,那么将会进行一次全部数据的复制。
同步过程:
如果网络抖动(连接断开 connection lost)
master还是会写repl_back_buffer(复制缓冲区)
slave会继续尝试连接主机
slave会把自己当前run_id和偏移量传输给master,并且执行pysnc命令同步
slave发送过来的offset在repl_back_buffer中,则master会将缓存中从offset以后的数据一次性同步给slave,否则全量复制
master同步长连接持续把写命令发送给slave,以保证数据的一致
复制中几个重要概念复制偏移量:
执行复制的双方,主从节点,分别会维护一个复制偏移量offset:
主节点每次向从节点同步了N字节数据后,将修改自己的复制偏移量offset N
从节点每次从主节点同步了N字节数据后,将修改自己的复制偏移量offset N
offset用于判断主从节点的数据库状态是否一致:如果二者offset相同,则一致;如果offset不同,则不一致,此时可以根据两个offset找出从节点缺少的那部分数据。
复制积压缓冲区:
主节点内部维护了一个固定长度的、先进先出(FIFO)队列 作为复制积压缓冲区,其默认大小为1MB
在主节点进行命令传播时,不仅会将写命令同步到从节点,还会将写命令写入复制积压缓冲区。
由于复制积压缓冲区定长且是先进先出,所以它保存的是主节点最近执行的写命令;时间较早的写命令会被挤出缓冲区。因此,当主从节点offset的差距过大超过缓冲区长度时,将无法执行部分复制,只能执行全量复制。
如果offset偏移量之后的数据,仍然都在复制积压缓冲区里,则执行部分复制;否则(数据已被挤出),则执行全量复制。
为了提高网络中断时部分复制执行的概率,可以根据需要增大复制积压缓冲区的大小(通过配置repl-backlog-size)
服务器运行ID(runid):
每个Redis节点,都有其运行ID,运行ID由节点在启动时自动生成,主节点会将自己的运行ID发送给从节点,从节点会将主节点的运行ID存起来。
从节点Redis断开重连的时候,就是根据运行ID来判断同步的进度:
如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会继续尝试使用部分复制(到底能不能部分复制还要看offset和复制积压缓冲区的情况);
如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的Redis节点并不是当前的主节点,只能进行全量复制。
全量及部分复制发生的情况如果从服务器以前没有复制过任何主服务器,或者之前执行过SLAVEOF no one命令,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC ? -1命令,主动请求主服务器进行完整重同步(因为这时不可能执行部分重同步);
如果从服务器已经复制过某个主服务器,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC <runid> <offset>命令:其中runid是上一次复制的主服务器的运行ID,而offset则是从服务器当前的复制偏移量,接收到这个命令的主服务器会通过这两个参数来判断应该对从服务器执行哪种同步操作,如何判断已经在介绍runid时进行详细说明。
psync2redis4.0新版本除了增加混合持久化,还优化了psync(以下称psync2)并实现即使redis实例重启的情况下也能实现部分同步,psync2在psync1基础上新增两个复制id:
master_replid: 复制id1(后文简称:replid1),一个长度为41个字节(40个随机串 ’0’)的字符串,每个redis实例都有,和runid没有直接关联,但和runid生成规则相同。当实例变为从实例后,自己的replid1会被主实例的replid1覆盖。
master_replid2:复制id2(后文简称:replid2) 默认初始化为全0,用于存储上次主实例的replid1。
实现过程:
1.存储复制信息:
redis在关闭时,通过shutdown save 都会调用rdbSaveInfoAuxFields函数,把当前实例的repl-id和repl-offset保存到RDB文件中。
2.重启后加载RDB文件中的复制信息:
redis加载RDB文件,会专门处理文件中辅助字段(AUX fields)信息,把其中repl_id和repl_offset加载到实例中,分别赋给master_replid和master_repl_offset两个变量值,特别注意当从库开启了AOF持久化,redis加载顺序发生变化优先加载AOF文件,但是由于aof文件中没有复制信息,所以导致重启后从实例依旧使用全量复制.
3.向主库上报复制信息,判断是否进行部分同步:
从实例向主库上报master_replid和master_repl_offset 1;从实例同时满足以下两条件,就可以部分重新同步,否则执行全量同步:
从实例上报master_replid串,与主实例的master_replid1或replid2有一个相等,用于判断主从未发生改变;
从实例上报的master_repl_offset 1字节,还存在于主实例的复制积压缓冲区中,用于判断从库丢失部分是否在复制缓冲区中;
psync2除了解决redis重启使用部分同步外,还为解决在主库故障时候从库切换为主库时候使用部分同步机制。redis从库默认开启复制积压缓冲区功能,以便从库故障切换变化master后,其他落后该从库可以从缓冲区中获取缺少的命令。该过程的实现通过两组replid、offset替换原来的master runid和offset变量实现:
第一组:master_replid和master_repl_offset:如果redis是主实例,则表示为自己的replid和复制偏移量; 如果redis是从实例,则表示为自己主实例的replid1和同步主实例的复制偏移量。
第二组:master_replid2和second_repl_offset:无论主从,都表示自己上次主实例repid1和复制偏移量;用于兄弟实例或级联复制,主库故障切换psync。
判断是否使用部分复制条件:如果从库提供的master_replid与master的replid不同,且与master的replid2不同,或同步速度快于master; 就必须进行全量复制,否则执行部分复制。
1.读写分离
复制数据延迟:异步复制,延迟与数据的不一致不可避免。优化网络,监控延迟
读到过期数据:升级3.2及以上版本。Redis 3.2中,从节点在读取数据时,增加了对数据是否过期的判断:如果该数据已过期,则不返回给客户端;
从节点故障:故障切换
2.主从配置不一致
例如maxmemory不一致:丢失数据
例如数据结构优化参数(例如hash-max-ziplist-entries):内存不一致
3.规避全量复制
第一次全量复制:第一次不可避免,建议使用小主节点,低峰时复制全量
节点运行id不匹配全量复制:主节点重启(运行id变化),升级redis4.0及以上 或进行故障转移
复制积压缓冲区不足导致的全量复制:增大复制缓冲区配置rel_backlog_size(默认1Mb) 网络“增强”
4.规避复制风暴
单主节点复制风暴:主节点重启,多从节点复制,建议更换复制拓扑 M -> S -> S
单机器复制风暴:避免在一台机器上放多个主节点