前言
我们在应用 Redis 时,经常会面临的运维工作,包括 Redis 的运行状态监控,数据迁移,主从集群、切片集群的部署和运维。
运行状态监控
我们先来看下监控 Redis 实时运行状态的工具,这些工具都用到了 Redis 提供的一个监控命令:INFO。
最基本的 INFO 命令
Redis 本身提供的 INFO 命令会返回丰富的实例运行监控信息,这个命令是 Redis 监控工具的基础。
INFO [section [section ...]]
INFO 命令在使用时,可以带一个参数 section,这个参数的取值有好几种,相应的,INFO 命令也会返回不同类型的监控信息。我把 INFO 命令的返回信息分成 5 大类,其中,有的类别当中又包含了不同的监控内容。
经常关注的 section 类别命令参数详解放在文章最后~,也可以查看官网的介绍。
面向 Prometheus 的 Redis-exporter 监控
Prometheus 是一套开源的系统监控报警框架。它的核心功能是从被监控系统中拉取监控数据,结合 Grafana 工具,进行可视化展示。而且,监控数据可以保存到时序数据库中,以便运维人员进行历史查询。同时,Prometheus 会检测系统的监控指标是否超过了预设的阈值,一旦超过阈值,Prometheus 就会触发报警。
Prometheus 正好提供了插件功能来实现对一个系统的监控,我们把插件称为 exporter,每一个 exporter 实际是一个采集监控数据的组件。exporter 采集的数据格式符合 Prometheus 的要求,Prometheus 获取这些数据后,就可以进行展示和保存了。
Redis-exporter 就是用来监控 Redis 的,它将 INFO 命令监控到的运行状态和各种统计信息提供给 Prometheus,从而进行可视化展示和报警设置。除了获取 Redis 实例的运行状态,Redis-exporter 还可以监控键值对的大小和集合类型数据的元素个数,这个可以在运行 Redis-exporter 时,使用 check-keys 的命令行选项来实现。
此外,我们可以开发一个 Lua 脚本,定制化采集所需监控的数据。然后,我们使用 scripts 命令行选项,让 Redis-exporter 运行这个特定的脚本,从而可以满足业务层的多样化监控需求。
最后,我还想再给你分享两个小工具:redis-stat 和Redis Live。跟 Redis-exporter 相比,这两个都是轻量级的监控工具。它们分别是用 Ruby 和 Python 开发的,也是将 INFO 命令提供的实例运行状态信息可视化展示。
数据迁移工具 Redis-shake
Redis-shake 的基本运行原理,是先启动 Redis-shake 进程,这个进程模拟了一个 Redis 实例。然后,Redis-shake 进程和数据迁出的源实例进行数据的全量同步。
Redis-shake 的一大优势,就是支持多种类型的迁移。
首先,它既支持单个实例间的数据迁移,也支持集群到集群间的数据迁移。
其次,有的 Redis 切片集群(例如 Codis)会使用 proxy 接收请求操作,Redis-shake 也同样支持和 proxy 进行数据迁移。
另外除了支持开源的 Redis 版本以外,Redis-shake 还支持云下的 Redis 实例和云上的 Redis 实例进行迁移,可以帮助我们实现 Redis 服务上云的目标。
在数据迁移后,我们通常需要对比源实例和目的实例中的数据是否一致。如果有不一致的数据,我们需要把它们找出来,从目的实例中剔除,或者是再次迁移这些不一致的数据。
数据比对工具 Redis-full-check
Redis-full-check 的工作原理很简单,就是对源实例和目的实例中的数据进行全量比对,从而完成数据校验。不过,为了降低数据校验的比对开销,Redis-full-check 采用了多轮比较的方法。
在第一轮校验时,Redis-full-check 会找出在源实例上的所有 key,然后从源实例和目的实例中把相应的值也都查找出来,进行比对。第一次比对后,redis-full-check 会把目的实例中和源实例不一致的数据,记录到 sqlite 数据库中。
从第二轮校验开始,Redis-full-check 只比较上一轮结束后记录在数据库中的不一致的数据。
为了避免对实例的正常请求处理造成影响,Redis-full-check 在每一轮比对结束后,会暂停一段时间。随着 Redis-shake 增量同步的进行,源实例和目的实例中的不一致数据也会逐步减少,所以,我们校验比对的轮数不用很多。
我们可以自己设置比对的轮数。具体的方法是,在运行 redis-full-check 命令时,把参数 comparetimes 的值设置为我们想要比对的轮数。
Redis-full-check 提供了三种比对模式,我们可以通过 comparemode 参数进行设置。comparemode 参数有三种取值,含义如下:
- KeyOutline:只对比 key 值是否相等;
- ValueOutline:只对比 value 值的长度是否相等;
- FullValue:对比 key 值、value 长度、value 值是否相等。
集群管理工具 CacheCloud
面向 Redis 运维管理的云平台,它实现了主从集群、哨兵集群和 Redis Cluster 的自动部署和管理,用户可以直接在平台的管理界面上进行操作。针对常见的集群运维需求,CacheCloud 提供了 5 个运维操作。
- 下线实例:关闭实例以及实例相关的监控任务。
- 上线实例:重新启动已下线的实例,并进行监控。
- 添加从节点:在主从集群中给主节点添加一个从节点。
- 故障切换:手动完成 Redis Cluster 主从节点的故障转移。
- 配置管理:用户提交配置修改的工单后,管理员进行审核,并完成配置修改。
CacheCloud 不仅会收集 INFO 命令提供的实例实时运行状态信息,进行可视化展示,而且还会把实例运行状态信息保存下来,例如内存使用情况、客户端连接数、键值对数据量。这样一来,当 Redis 运行发生问题时,运维人员可以查询保存的历史记录,并结合当时的运行状态信息进行分析。
INFO 命令详解
stats(General statistics)
- total_connections_received:接收成功的链接总数
- total_commands_processed:命令成立完成的总数
- instantaneous_ops_per_sec:每秒处理的命令数量
- total_net_input_bytes:输入流总量,byte级别
- total_net_output_bytes:输出流总量,byte级别
- instantaneous_input_kbps:每秒输入kb数量
- instantaneous_output_kbps:每秒输出kb数量
- rejected_connections:拒绝链接数量
- sync_full:与副本完全同步的次数
- sync_partial_ok:部分同步请求接受数量
- sync_partial_err:部分同步请求拒绝数量,或者说处理失败数量
- expired_keys:过期的key数量
- expired_stale_perc:过期key与总Key数量的占比
- evicted_keys:内存超出时,被逐出的Key数量
- keyspace_hits:自redis启动开始,成功命中的key数量
- keyspace_misses:自redis启动开始,未成功名称的key数量
- pubsub_channels:当前使用中的channel数量
- pubsub_patterns:当前使用的模式的数量
- latest_fork_usec:fork耗时,微秒,fork详情
- migrate_cached_sockets:socket缓冲
- slave_expires_tracked_keys:副本到期跟踪的key数量(仅适用于可写副本)
commandstat(Redis command statistics)
- calls:调用次数
- usec:总耗时(微秒)
- usec_per_call:平均耗时(微秒)
cpu(CPU consumption statistics)
- used_cpu_sys:redis主进程占用核心态的CPU总耗时(主线程和后台线程)
- used_cpu_user:redis主进程占用用户态的CPU总耗时(主线程和后台线程)
- used_cpu_sys_children:redis后台进程占用核心态的CPU总耗时
- used_cpu_user_children:redis后台进程占用用户态的CPU总耗时
memory(Memory consumption related information)
- used_memory:已使用内存,byte级别
- used_memory_human:已使用内存,可读方式展示
- used_memory_rss:Redis占用的物理内存,byte级别
- used_memory_rss_human:Redis占用的物理内存,可读方式展示
- used_memory_peak:Redis的内存使用峰值,byte级别
- used_memory_peak_human:Redis的内存使用峰值,可读方式展示
- used_memory_peak_perc:used_memory / used_memory_peak百分比
- used_memory_overhead:Redis管理数据结构使用的内存,byte级别
- used_memory_startup:Redis启动时消耗的内存
- used_memory_dataset:used_memory - used_memory_overhead数据集大小,byte级别
- used_memory_dataset_perc:used_memory_dataset / used_memory数据集站总消耗内存占比
- allocator_allocated:分配器分配的内存,作用未知,byte级别
- allocator_active:分配器活跃内存,作用未知,byte级别
- allocator_resident:分配器常驻内存,作用未知,byte级别
- total_system_memory:所在服务器系统总内存,byte级别
- total_system_memory_human:所在服务器系统总内存,可读方式显示
- used_memory_lua:lua使用的内存,byte级别
- used_memory_lua_human:lua使用的内存,可读方式展示
- used_memory_scripts:lua缓存使用的内存,byte级别
- used_memory_scripts_human:lua缓存使用的内存,可读方式展示
- maxmemory:最大使用内存限制,超过时,会使用LRU或LFU策略删除key,该值尽量设置的小于系统内存
- maxmemory_human:最大使用内存限制,可读方式展示
- maxmemory_policy:内存超出时,删除key的策略,有lru,lfu可选
- mem_fragmentation_ratio:used_memory_rss / used_memory内存碎片率,过高对性能的影响
- mem_fragmentation_bytes:内存碎片大小,byte级别
- mem_allocator:内存分配器
replication(Master/replica replication information)
- role:实例的角色,是master or slave
- connected_slaves:连接的slave实例个数
- slave0:副本连接信息(lag从库多少秒未向主库发送REPLCONF命令)
ip=10.16.36.19,port=8123,state=online,offset=193369160007,lag=0
- master_failover_state:是否正常进行故障切换的状态
- master_replid:当前Redis服务的复制实例ID
- master_repl_offset:主从同步 主库偏移量
- repl_backlog_active:复制积压缓冲区是否开启
- repl_backlog_size:复制积压缓冲区大小
- repl_backlog_first_byte_offset:复制积压缓冲区里偏移量的大小 repl_backlog_histlen:此值等于 master_repl_offset - * repl_backlog_first_byte_offset,该值不会超过repl_backlog_size的大小
persistence(RDB and AOF related information)
- loading:是否有加载转储文件的标识,0=无,1=有,内存耗尽可能会有
- rdb_changes_since_last_save:自最后一次持久保存后,rdb进行的改动数量
- rdb_bgsave_in_progress:标志rdb是否在保存,0=无,1=有
- rdb_last_save_time:最后一次保存时间戳
- rdb_last_bgsave_status:最后一次异步持久化操作的状态
- rdb_last_bgsave_time_sec:最后一次异步持久化持续时长,秒级
- rdb_current_bgsave_time_sec:当前异步持久化时长,-1表示当前没有异步持久化
- rdb_last_cow_size:最后一次持久化时内存copy的大小,byte级别
- aof_enabled:是否开启aof的持久化方式,0=不开启,1=开启
- aof_rewrite_in_progress:标志aof是否有在重写,0=无,1=有
- aof_rewrite_scheduled:标识是否将要在rdb save操作结束后执行
- aof_last_rewrite_time_sec:aof最后一次重写耗时,秒级
- aof_current_rewrite_time_sec:aof当前重写耗时,-1代表当前没有执行重写
- aof_last_bgrewrite_status:aof最后一次异步重写状态
- aof_last_write_status:aof最后一次重写状态
- aof_last_cow_size:aof最后一次重写消耗内存, byte级别
- aof_current_size:aof当前文件大小,byte级别
- aof_base_size:aof最新一次启动或重写的文件大小,byte级别
- aof_pending_rewrite:同上面的aof_rewrite_scheduled
- aof_buffer_length:aof buffer的大小
- aof_rewrite_buffer_length:aof 重写buffer大小
- aof_pending_bio_fsync:后台IO队列中等待fsync任务的个数
- aof_delayed_fsync:延迟的fsync计数器
总结
平时我们遇到的 Redis 变慢问题,有时觉得很难定位原因,其实是因为我们没有做好完善的监控。 Redis INFO 信息看似简单,但是这些信息记录着 Redis 运行时的各种状态数据,如果我们把这些数据采集到并监控到位,80% 的异常情况能在第一时间发现。
参考
摘自 极客时间 - 蒋德钧老师的《Redis 核心技术与实战》 <- 极其推荐大家阅读~
《Redis 核心技术与实战》学习笔记 Day5