目录
一、redis持久化
持久化的作用:将数据从内存异步保存到硬盘中。
持久化方式:快照 RDB;写日志 AOF;
(1)AOF
1、什么是AOF
AOF(append only file) 持久化: 以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。 AOF的主要作用是解决了数据持久化的实时性, 目前已经是Redis持久化的主流方式。
开启AOF功能需要设置配置: appendonly yes, 默认不开启。 AOF文件名通过appendfilename配置设置, 默认文件名是appendonly.aof。 保存路径同RDB持久化方式一致, 通过dir配置指定。
redis重启后
步骤:
- 所有的写入命令会追加到aof_buf(缓冲区) 中。
- AOF缓冲区根据对应的策略向硬盘做同步操作。
- 随着AOF文件越来越大, 需要定期对AOF文件进行重写, 达到压缩的目的。
- 当Redis服务器重启时, 可以加载AOF文件进行数据恢复。
2、缓冲区文件同步的三种策略
always,每一条命令都写入。不会丢失数据,I/O开销大
everysec,出现故障,会丢失一秒数据。通常使用这种方式。
no
建议:
- 配置为always时, 每次写入都要同步AOF文件, 在一般的SATA硬盘上, Redis只能支持大约几百TPS写入, 显然跟Redis高性能特性背道而驰,不建议配置。
- 配置为no, 由于操作系统每次同步AOF文件的周期不可控, 而且会加大每次同步硬盘的数据量, 虽然提升了性能, 但数据安全性无法保证。
- 配置为everysec, 是建议的同步策略, 也是默认配置, 做到兼顾性能和数据安全性。 理论上只有在系统突然宕机的情况下丢失1秒的数据。
AOF重写?
随着命令不断写入AOF, 文件会越来越大, 为了解决这个问题, Redis引入AOF重写机制压缩文件体积。 AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。
如incr count一亿次,只需设置set count 10000000即可,重复执行一亿次,开销比较大。
bgrewriteaof命令:手动触发
AOF重写配置:
配置:
统计:
(2)RDB
1、什么是RDB?
RDB持久化是把当前进程数据生成快照保存到硬盘的过程, 触发RDB持久化过程分为手动触发和自动触发。
2、触发机制
save( 同步),数据量比较大时,redis会阻塞。 如果存在老的RDB文件,新的替换旧的。复杂度O(n)
bgsave(异步),
步骤:
- 执行bgsave命令, Redis父进程判断当前是否存在正在执行的子进程, 如RDB/AOF子进程, 如果存在bgsave命令直接返回。
- 父进程执行fork操作创建子进程, fork操作过程中父进程会阻塞, 通过info stats命令查看latest_fork_usec选项, 可以获取最近一个fork操作的耗时, 单位为微秒。
- 父进程fork完成后, bgsave命令返回“Background saving started”信息并不再阻塞父进程, 可以继续响应其他命令。
- 子进程创建RDB文件, 根据父进程内存生成临时快照文件, 完成后对原有文件进行原子替换。 执行lastsave命令可以获取最后一次生成RDB的时间, 对应info统计的rdb_last_save_time选项。
- 进程发送信号给父进程表示完成, 父进程更新统计信息
自动
满足配置,就会触发。
其他触发机制:全量复制;debug reload;shutdown;
总结:
1、RDB是redis内存到硬盘的快照,用于持久化。
2、save会阻塞redis。
3、bgsave不会阻塞redis,但会fork新进程。
4、save自动配置满足任一条件就会被执行。
5、有些触发机制不容忽视。
(3)RDB和AOF比较
RDB的优缺点
RDB的优点:
- RDB是一个紧凑压缩的二进制文件, 代表Redis在某个时间点上的数据快照。 非常适用于备份, 全量复制等场景。 比如每6小时执行bgsave备份,并把RDB文件拷贝到远程机器或者文件系统中(如hdfs) , 用于灾难恢复。
- Redis加载RDB恢复数据远远快于AOF的方式。
RDB的缺点:
- RDB方式数据没办法做到实时持久化/秒级持久化。 因为bgsave每次运行都要执行fork操作创建子进程, 属于重量级操作, 频繁执行成本过高。
- RDB文件使用特定二进制格式保存, Redis版本演进过程中有多个格式的RDB版本, 存在老版本Redis服务无法兼容新版RDB格式的问题。针对RDB不适合实时持久化的问题, Redis提供了AOF持久化方式来解决。
AOF通过追加写命令到文件实现持久化, 通过appendfsync参数可以控制实时/秒级持久化。 因为需要不断追加写命令, 所以AOF文件体积逐渐变大, 需要定期执行重写操作来降低文件体积。
AOF重写可以通过auto-aof-rewrite-min-size和auto-aof-rewritepercentage参数控制自动触发, 也可以使用bgrewriteaof命令手动触发。
二、redis复制的原理与优化
1、什么是主从配置
单机有什么问题?
1、内存容量有限 2、处理能力有限 3、无法高可用。
主从复制的作用?
Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。 只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步给 从服务器,从而一直保证主从服务器的数据相同。
特点:
1、master/slave 角色;
2、master/slave 数据相同;
3、降低 master 读压力再转交从库。
问题:
无法保证高可用;
没有解决 master 写的压力。
2、复制的配置
①slaveof命令
在某台机器上执行,连接 slaveof 127.0.0.1:6379 断开 slaveof no one
②配置
slaveof ip port slave-read-only yes
3、全量复制和部分复制
runid:是一个标识,
redis-cli -p 6379 info server|grep run
由上述命令可以知道该 redis服务器的runid是多少,但服务器被重启或者是网络的原因,runid会发生变化,而从库探测到主库的runid发生了变化,会认为进行了很大的改动,则会进行一次全量复制。
①偏移量:偏移量是用来检测从库和主库数据是否一致。
全量复制:
一般用于初次复制场景, Redis早期支持的复制功能只有全量复制, 它会把主节点全部数据一次性发送给从节点, 当数据量较大时, 会对主从节点和网络造成很大的开销。
1、完成全量复制的功能,有两个参数(runid,offset),第一次不知道主节点的runid是多少,传?和-1做全量复制。
2、master检测出了slave是第一次复制,因为slave不知道master的runid和偏移量,所以master把自己的runid和偏移量传给了slave。
3、保存master的信息。
4、 master开始创建快照(bgsave),与其同时master也会把在创建快照的时间间期中产生的数据传到了自身的复制缓冲区。
5、master向slave发送RDB文件
6、发送缓冲区中新加入的命令。
7、slave清楚掉旧数据
8、加载RDB文件,同时加载buffer数据。
全量复制开销:
1、bdsave时间2、RDB文件网络传输时间
3、从节点清空数据时间
4、从节点加载RDB的时间。
②部分复制:
有时候因为网络的抖动或者其他原因,导致从库对主库失去连接。再次连接后,进行全量复制的话,比较消耗资源,所以就出现了部分复制。
2、master 把新命令加入缓冲区(通常1M)
4、发送自己当前的offset和runid,告诉master自己当前的状态。
5、如果master发现slave传输的偏移量在buffer之内,
6、就把从offset开始,到buffer结尾的数据传输给slave。
4、故障处理
master宕机之后,就挑选一个从节点称为master,其他从节点也以这个为新的master。这种方式会比较耗时,redis提供了自动故障转移机制——把slave晋升为master,让其他slave同步新master,通知客户端新的master。这种方式不需要手动实现。例如redis sentinel
5、常见问题
1、读写分离:读流量分摊到从结点。master只做写的操作,读操作分配给slave。
可能遇到问题:
- 复制数据延迟
Redis复制数据的延迟由于异步复制特性是无法避免的, 延迟取决于网络带宽和命令阻塞情况, 比如刚在主节点写入数据后立刻在从节点上读取可能获取不到。- 读到过期数据
当主节点存储大量设置超时的数据时, 如缓存数据, Redis内部需要维护过期数据删除策略, 删除策略主要有两种: 惰性删除和定时删除- 从节点故障
对于从节点的故障问题, 需要在客户端维护可用从节点列表, 当从节点故障时立刻切换到其他从节点或主节点上。2、主从配置不一致
- maxmemory不一致:丢失数据
- 数据结构优化参数(例如has-max-ziplist-entries):会出现内存不一致的情况
3、规避全量复制
- 第一次全量复制:第一次不可避免,但是我们可以使用小的主节点(maxmemory不设置过大),或者在半夜低峰的时刻做全量复制。
- 节点运行的ID不匹配:例如主节点重启,runid就会变化,可以使用自动故障转移,例如哨兵或者集群。
- 复制积压缓冲区不足:默认1M。网络中断,部分复制功能无法满足,这个时候可以增大复制缓冲区配置rep_backlog_size。
4、规避复制风暴
- 单主节点复制风暴:由于主节点重启,多个从节点要复制,会产生复制风暴。
解决办法是:更换复制拓扑。slave挂slave。- 单机器复制风暴:由于多个主节点都部署在同一个机器上面,机器宕机后需要大量的全量复制。 解决办法是:主节点分配到多台机器上面或者使用一些高可用架构,将从节点晋升为主节点。