RDB和AFO篇
(1)父进程执行fork操作创建子进程, fork操作过程中父进程会阻塞, 通过info stats命令查看latest_fork_usec选项, 可以获取最近一个fork操作的耗时, 单位为微秒。
fork耗时问题定位: 对于高流量的Redis实例OPS可达5万以上, 如果fork操作耗时在秒级别将拖慢Redis几万条命令执行, 对线上应用延迟影响非常明显。 正常情况下fork耗时应该是每GB消耗20毫秒左右。 可以在info stats统计中查latest_fork_usec指标获取最近一次fork操作耗时, 单位微秒。
(2)子进程创建RDB文件, 根据父进程内存生成临时快照文件, 完成后对原有文件进行原子替换。 执行lastsave命令可以获取最后一次生成RDB的时间, 对应info统计的rdb_last_save_time选项
(3)每当发生AOF追加阻塞事件发生时, 在info Persistence统计中,aof_delayed_fsync指标会累加, 查看这个指标方便定位AOF阻塞问题。
(4)避免在大量写入时做子进程重写操作, 这样将导致父进程维护大量页副本, 造成内存消耗。Linux kernel在2.6.38内核增加了Transparent Huge Pages( THP) , 支持huge page( 2MB) 的页分配, 默认开启。 当开启时可以降低fork创建子进程
的速度, 但执行fork之后, 如果开启THP, 复制页单位从原来4KB变为2MB, 会大幅增加重写期间父进程内存消耗。 建议设置“sudo echo never>/sys/kernel/mm/transparent_hugepage/enabled”关闭THP。
RDB配置参数:
stop-writes-on-bgsave-error yes 这个配置也是非常重要的一项配置,这是当备份进程出错时,主进程就停止接受新的写入操作,是为了保护持久化的数据一致性问题。如果自己的业务有完善的监控系统,可以禁止此项配置, 否则请开启。
关于压缩的配置 rdbcompression yes
运维提示:
当遇到坏盘或磁盘写满等情况时, 可以通过config set dir{newDir}在线修改文件路径到可用的磁盘路径, 之后执行bgsave进行磁盘切换, 同样适用于AOF持久化文件。
压缩:rdbcompression yes 。Redis默认采用LZF算法对生成的RDB文件做压缩处理, 压缩后的文件远远小于内存大小, 默认开启, 可以通过参数config set rdbcompression{yes|no}动态修改。虽然压缩RDB会消耗CPU, 但可大幅降低文件的体积, 方便保存到硬盘或通过网络发送给从节点, 因此线上建议开启。
主从复制
(1)主从节点一般部署在不同机器上, 复制时的网络延迟就成为需要考虑的问题, Redis为我们提供了repl-disable-tcp-nodelay参数用于控制是否关闭TCP_NODELAY, 默认关闭, 说明如下:
·当关闭时, 主节点产生的命令数据无论大小都会及时地发送给从节点, 这样主从之间延迟会变小, 但增加了网络带宽的消耗。 适用于主从之间的网络环境良好的场景, 如同机架或同机房部署。
·当开启时, 主节点会合并较小的TCP数据包从而节省带宽。 默认发送时间间隔取决于Linux的内核, 一般默认为40毫秒。 这种配置节省了带宽但增大主从之间的延迟。 适用于主从网络环境复杂或带宽紧张的场景, 如跨机房部署
运维提示:
部署主从节点时需要考虑网络延迟、 带宽使用率、 防灾级别等因素, 如要求低延迟时, 建议同机架或同机房部署并关闭repl-disable-tcp-nodelay; 如果考虑高容灾性, 可以同城跨机房部署并开启repl-disable-tcp-nodelay。
(2)复制偏移量的维护如图所示。通过对比主从节点的复制偏移量, 可以判断主从节点数据是否一致。
运维提示:
可以通过主节点的统计信息, 计算出master_repl_offset-slave_offset字节量, 判断主从节点复制相差的数据量, 根据这个差值判定当前复制的健康度。 如果主从之间复制偏移量相差较大, 则可能是网络延迟或命令阻塞等原因引起。
(3) 主节点发送RDB文件给从节点, 从节点把接收的RDB文件保存在本地并直接作为从节点的数据文件, 接收完RDB后从节点打印相关日志, 可以在日志中查看主节点发送的数据量:
需要注意, 对于数据量较大的主节点, 比如生成的RDB文件超过6GB以上时要格外小心。 传输文件这一步操作非常耗时, 速度取决于主从节点之间网络带宽, 通过细致分析Full resync和MASTER<->SLAVE这两行日志的时间差, 可以算出RDB文件从创建到传输完毕消耗的总时间。
之间时间间隔可以算出RDB消耗的时间如果总时间超过repl-timeout所配置的值(默认60秒) , 从节点将放弃接受RDB文件并清理已经下载的临时文件, 导致全量复制失败, 此时从节点打印如下日志:
repl-timeout:slave和master之间的复制超时时间,默认为60s, 推荐设置为180s;
a) slave角度,如果在repl-timeout时间内没有收到master SYNC传输的rdb snapshot数据,
b) slave角度,在repl-timeout没有收到master发送的数据包或者ping。
c) master角度,在repl-timeout时间没有收到REPCONF ACK确认信息。
当redis检测到repl-timeout超时(默认值60s),将会关闭主从之间的连接,redis slave发起重新建立主从连接的请求。
对于内存数据集比较大的系统,可以增大repl-timeout参数。
(4) 对于从节点开始接收RDB快照到接收完成期间, 主节点仍然响应读写命令, 因此主节点会把这期间写命令数据保存在复制客户端缓冲区内, 当从节点加载完RDB文件后, 主节点再把缓冲区内的数据发送给从节点, 保证主从之间数据一致性。 如果主节点创建和传输RDB的时间过长, 对于高流量写入场景非常容易造成主节点复制客户端缓冲区溢出。 默认配置为clientoutput-buffer-limit slave 256MB 64MB 60, 如果60秒内缓冲区消耗持续大于64MB或者直接超过256MB时, 主节点将直接关闭复制客户端连接, 造成全量同步失败。 对应日志如下:
因此, 运维人员需要根据主节点数据量和写命令并发量调整clientoutput-buffer-limit slave配置, 避免全量复制期间客户端缓冲区溢出。