目录
fork操作:
当redis进行RDB和AOF重写时,会fork创建子进程
fork创建不需要父进程物理内存空间,但会赋值父进程的内存空间页表
fork耗时问题:
info:last_fork_usec正常耗时20ms/GB
优先使用物理机
控制每个Redis实例的内存
合理控制Linux内存,避免fork失败
降低fork频率(AOF触发时机)
监控:可以编写shell脚本监控log定位问题
Linux内核:THP页分配 star iostat iotop
salve复制:
slaveof ip port建立连接
slaveof no one断开连接
slave-read-only=yes线上不要修改只读模式,防止出现数据不一致
repl-diable-tcp-nodelay设置传输延迟
数据同步:
psync命令:
psync {runId} {offset}
主从各自复制偏移量:
主节点处理完写入命令后,把命令长度做累加记录,统计在info replication master_repl_offset
从节点每秒钟上报复制偏移量给主节点info replication slave_repl_offset
主从复制挤压缓冲区:
在主节点上的一个固定大小的队列(默认1MB)
主节点运行id:
因为每次重启运行ID会发生变化,根据ip和port的话会有问题,比如重启替换了RDB或AOF,数据的偏移量是不对的,应该全量复制
如何在不改变运行ID的情况下重启?使用debug reload(会阻塞主线程)
全量复制:
一般用于初次复制,复制时候会把主节点在这期间的数据写命令保存到复制缓冲区(client-output-buffer-limit slave256MB64MB60)
从节点加载RDB的时候,依然响应读命令(slave-server-stale-data开启),无法容忍不一致可关闭
部分复制:用于因网络闪断等原因造成的数据丢失
心跳:
主节点每隔10s对从ping
从节点每隔1s发送replconf ack {offset},给主节点同步偏移量
读写分离:
使用从节点响应请求,可能存在下列问题:
复制数据延迟
监听主从节点的复制偏移量,当延迟较大时发送报警
可以采用zookeeper回调通知,切换客户端路由
读到过期数据
删除策略:惰性删除、定时删除
3.2版本已经解决
从节点故障
和数据延迟一样zookeeper
避免复制风暴:
一主多从,采用树状结构
单机多实例,主节点分散部署
阻塞:
发现阻塞:
客户端有异常JedisConnectionException(要打印ip port),借助日志系统报警
监控系统,指标:命令耗时、慢查询、持久化阻塞、链接拒绝、CPU/内存/网络/磁盘过载
内在原因:
api或数据结构使用不合理
slowlog get {n}:超时默认10ms,队列长度默认128
bigkeys发现大对象
CPU饱和
stat发现redis使用情况
info commandstats发现命令不合理开销时间
持久化阻塞
fork阻塞:info stats获取latest_fork_usec指标获取最近一次fork耗时
AOF刷盘:info persistence统计中aof_delayed_fsync
HugePage写操作:对于开启Transparent HugePages的会引起内存页单位放大
外在原因:
CPU竞争
top、star查看CPU消耗时间点和进程
绑定CPU,降低CPU切换的开销:开启了RDB和AOF以及slave不要这样做
内存交换
查看进程id:redis-cli -p 6379 info server | grep process_id
根据进程号查看内存交换信息:cat /proc/4476/smaps | grep Swap (0或4k正常)
降低系统swap优先级:echo 10>/proc/sys/vm/swappiness
网络问题
网络闪断:sar -n DEV查看流量是否正常
redis拒绝链接:info stats的rejected_connections设置tcp-keepalive和timeout让redis主动关闭
连接溢出:进程限制(ulimit -n)设置成65535防止too many open files
backlog队列溢出:netstats -s | grep overflowed查看连接拒绝的统计
网络延迟:使用–latency --latency-history
网卡软中断:top1中的si指标
理解内存
内存统计:mem_fragmentation_ratio >1:碎片 <1:内存交换
对象内存:数据结构
缓冲内存:客户端缓冲区、复制缓冲区、AOF缓冲区
内存碎片:jemalloc分配内存(频繁更新、大量过期键)
解决:数据对齐、安全重启
子进程内存消耗:THP问题(关闭它),sysctl vm.overcommit_memory=1允许分配所有内存
设置内存上限:
maxmemory实际的内存因为内存碎片的存在,要更大,超过的部分根据LRU淘汰
动态调整内存上限:
内存回收策略
删除过期键:
惰性删除:读取时返回空(内存泄漏,比如长久不访问就不会删)
定时任务删除:默认每秒运行10次(根据过期比例、使用快慢两种速率模式回收键)
内存溢出控制策略:
随机删,不删拒绝写、LRU删、过期键删
一般环境下才可以使用调小maxmemory,达到快速回收目的
缩减key value的长度;采用序列化工具
共享对象池:开启LRU相关淘汰策略,共享技术被禁止使用
哨兵
这部分雪球内部旧的方案,相比于gossip的cluster集群,不在解释
集群
哈希分区:
节点取余
一致性哈希:
加减节点会造成哈希环中部分数据无法命中
少量节点时,节点变化影响哈希环中数据映射
普通的一致性需要一半才能负载均衡
虚拟槽分配CRC16校验
redis数据分区:
解耦数据和槽之间的关系
支持点、槽、键之间映射
只有16384个槽全部分配完毕之后,集群才创建成功
goosip协议Gossip协议:
选择发送消息节点的数量:cluster_node_timeout
消息数据量:并不是越大越好
集群伸缩:
有坑啊,注意:使用redis-trib.rb比较好,如果直接meet,不会检查新节点的数据造成紊乱
迁移后使用redsi-trib.rb rebalance ip:port检查节点槽之间的均衡性
MOVE重定向是在client端完成,client缓存了一个node和slot的对应关系
ACK重定向
故障发现
主观下线:某个节点认为另外一个节点不可用
客观下线:集群内多个节点认为该节点下线
恢复:
短线时间>cluster-node-time*cluster-slave-validity-factor
根据从节点的复制偏移量offset设置优先级
更新configEpoch配置纪元
故障转移时间:
偏移量最大的从节点会在1000ms完成转移
故障转移时间和cluster-node-timeout息息相关(默认15s)