redis棘手问题处理

224 阅读6分钟

棘手问题处理

flushall,flushdb后恢复方法: 防止aof重写: config set auto-aof-rewrite-percentage 1000 config set auto-aof-rewrite-min-size 100000000000 去掉主从aof文件中的flush相关内容 *1 $8 flushall redis-check-aof 检查手动改写aof后,aof文件是否正确 重启主节点,恢复数据

bigkey处理: debug object key查看serializedlength属性,表示 key对应的value序列化之后的字节数 例如: debug object www:common:zxt Value at:0x7f3b7e9fd2a0 refcount:1 encoding:int serializedlength:3 lru:6487054 lru_seconds_idle:3211982 单位是字节

如何改善fork耗时: 1.查看fork耗时 info stats: 查看latest_fork_usec,单位为秒 2.fork耗时跟内存量成正比,redis内存不应该超过16G 3.放宽aof自动触发时机,避免不必要的全量复制,这样降低了fork频率 linux有写时复制机制,父子进程会共享相同的物理内存页,当父进程处理写请求时会把要修改的页创建副本,而子进程在fork操作过程中共享整个父进程内存快照

Linux的Transparent Huge Pages(THP)默认开启,支持huge page(2MB)的页分配,可以降低fork创建子进程速度,但会导致复制页单位从4KB变为2M,会大幅度增加重写期间父进程内存消耗,建议 echo never > /sys/kernel/mm/transparent_hugepage/enabled

AOF重写时回消耗大量硬盘IO,可以开启配置no-appendfsync-on-rewrite,表示在AOF重写期间不做fsync操作,但极端情况下可能丢失整个AOF重写期间的数据 aof_delayed_fsync指标方便定位AOF阻塞问题

redis为每个客户端分配了输入缓冲区,将客户端发送的命令临时保存,同时redis从缓冲区拉取命令执行,(qbuf即query buffer 查询缓冲区) client list可以查看qbuf:缓冲区总容量 qbuf-free:剩余容量 缓冲区大小不固定,根据输入内容动态调整,只要求每个客户端缓冲区大小不超过1G 1旦某个客户端的缓冲区超过1G,客户端将会被关闭 总的输入缓冲区是不受maxmemory限制的,不过超过限制后可能会出现数据丢失 info memory看used_memory_human 缓冲区过大原因: 1.Redis的处理速度跟不上输入缓冲区输入速度,并且每次进入输入缓冲区的命令包含大量bigkey 2.redis发生堵塞,短期内不能处理命令,造成客户端输入的命令积压在输入缓冲区

监控输入缓冲区异常的方法: 1.定期执行 client list命令,收集qbuf和qbuf-free,找到异常的连接并进行分析看哪个客户端有问题(这种方法执行速度慢,频繁执行可能堵塞redis) 2.通过info clients找到最大的输入缓冲区,设置超过10M就报警(这种方法不能精准定位到客户端) 127.0.0.1:6379> info clients

Clients

connected_clients:2 client_longest_output_list:0 client_biggest_input_buf:200 blocked_clients:0

输出缓冲区:与输入缓冲区不同的是,可通过client-output-buffer-limit设置,划分更细 分为普通客户端,发布订阅客户端,slave客户端 normal:普通客户端 slave:slave客户端 pubsub:发布订阅客户端 如果客户端使用的输出缓冲区超过了 并持续秒,客户端会被立即关闭 如果客户端使用的输出缓冲区超过了 ,客户端会被立即关闭 client-output-buffer-limit 监控方法: 1.client list 看obl,oll,omem三项 2.info clients 看 client_longest_output_list:0这项

默认 normal clients are not limited because they don't receive data without asking (in a push way), but just after a request, so only asynchronous clients may create a scenario (方案)where data is requested faster than it can read. 输出缓冲区出现异常概率比较大,输入缓冲区出现异常概率较小 obl代表固定缓冲区长度(存放返回比较小的命令执行结果),ool代表动态缓冲区列表(存放返回值较大的命令的结果)的长度,omem表示输出缓冲区总共的字节数 输出缓冲区 = ool + obl 固定缓冲区才16k用尽了也会使用ool

可以适当增加slave输出缓冲区:如果master节点,写入比较大,slave客户端的输出缓冲区可能会比较大,一旦slave客户端连接因为输出缓冲区溢出被kill,会造成重复重连。内存抖动频繁可能就是输出缓冲区较大。高并发情况下monitor命令会增大输出缓冲区

客户端存活状态:client list的age,和idle(单位是秒)代表已经连接的时间和最近一次的空闲时间,当age=idle时,说明连接一直处于空闲状态,不正常

config get maxclients 限制最大连接数,一旦连接数超过maxclients,新的连接将被拒绝 info clients查看当前客户端连接数 client list的flag标识当前客户端类型 N代表normal, S代表slave,O代表正在执行monitor命令

client setName | client getName为当前连接的客户端设定名称和获取名称,默认为nil client kill ip:port client pause timeout:阻塞客户端timeout豪秒 ,一旦发送这个命令,所有的客户端都会被阻塞住

monitor用于监控redis正在执行的命令

timeout检测客户端超时时间,为0表示不检测 tcp-keepalive,检测TCP活性周期,如果设置为60,每隔60s进行活性检测,防止大量死连接占用系统资源

tcp-backlog:三次握手后,会将接受的连接放入队列中,该参数表示队列大小,默认值511

connected_clients代表当前redis节点的客户端连接数,一旦超过maxclients,连接将会被拒绝

info stats的reject_connections可以查看拒绝的客户端连接数

主节点内存突然变大问题排查: 判断主从数据是否一致:看dbsize结果是否相同 info clients排查是否由客户端缓冲区造成主节点内存陡增 redis-cli client list|grep -v "omem=0"(因为处理速度足够快,大部分客户端omem为0) omem较大的,client kill杀死连接

客户端周期性超时问题:客户端周期性超时,服务端没有明显异常,只是有一些慢查询操作 分析: 网络原因:看是否网络出现周期性问题 redis本身:看redis日志统计 客户端:慢查询日志和超时时间是否对应