Redis性能监控及优化
- 一、Redis性能指标
- 1.1 Redis性能压力
- 1.2.1 Server
- 1.2.2 Clients
- 1.2.3 Memory
- 1.2.4 Persistence
- 1.2.5 Stats
- 1.2.6 Replication
- 1.2.7 CPU
- 1.2.8 Cluster
- 1.2.9 Keyspace
- 1.2.10 Commandstats
- 二、Redis监控工具
- 2.1 Prometheus+Grafana
- 2.2 Redis-monitor
- 2.3 Redis-stat
- 2.4 Redis-faina
- 三、Redis性能优化
- 3.1 慢查询
- 3.2 网络延迟
- 3.3 数据持久化引发的延迟
- 3.4 大对象和大键/键个数和长度的突增
- 3.5 数据淘汰引发的延迟
- 3.6 引入读写分离机制
Redis是一个纯内存的Key-Value型数据库,可以提供高并发和低延时的服务,生产上Redis的性能将会直接影响到服务的质量。对此本文将主要对Redis的性能指标、监控工具以及性能优化方法进行介绍。
一、Redis性能指标
1.1 Redis性能压力
Redis性能压力主要源于响应时间变慢和内存突然增长,甚至达到上限的问题。其原因主要有以下几个方面:
- 慢查询
- 大对象和大键/键个数增长、平均长度突增
- 网络通信延迟
- Redis持久化引发的延迟
- 数据淘汰引发的延迟
当Redis出现问题时,我们很难直接定位到具体原因,需要通过Redis的监控提供的信息进行分析才能得到答案。
###1.2 Redis监控参数
Redis可以通过info all命令的的输出获取相关性能指标。可以分为以下十类:
- server(基本信息)
- clients(连接信息)
- memory(内存信息)
- persistence(持久化信息)
- stats(命令等状态信息)
- replication(复制信息)
- cpu(CPU相关信息)
- cluster(集群信息)
- keyspace(键空间信息)
- commandstats(调用命令相关信息)
在下面的介绍中,我将会介绍各类信息中的关键参数,其余部分可以自行研究。
1.2.1 Server
uptime_in_days:从Redis server 启动到现在的天数
1.2.2 Clients
connected_clients:已连接客户端的数量 (不包括从服务器)
blocked_clients:正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量
1.2.3 Memory
used_memory:已使用的内存(不包含内存碎片)
used_memory_rss:已使用的内存(包含内存碎片)
used_memory_peak:过去Redis内存使用的峰值
maxmemory:最大内存
通过used_memory/maxmemory可以计算出内存使用率,未设置淘汰策略(maxmemory_policy)时,达到maxmemory限制不能写入数据。
1.2.4 Persistence
rdb_last_bgsave_status/aof_last_write_statu/aof_last_bgrewrite_statuss:最后一次持久化/AOF重写状态
aof_pending_bio_fsync:后台IO队列中等待fsync的任务数
aof_current_size:AOF当前文件大小
1.2.5 Stats
total_commands_processed:服务器已执行的命令数量
instantaneous_ops_per_sec:每秒执行命令数
rejected_connections:因为最大客户端数量限制而被拒绝的连接请求数量
expired_keys:过期的数据库键数量
evicted_keys:因最大内存容量限制而被驱逐的键数量
keyspace_hits:键空间命中数
keyspace_misses:键空间未命中数
total_net_input_bytes:网络流入总流量
total_net_output_bytes:网络流出总流量
1.2.6 Replication
master_link_status:主从连接状态
master_repl_offset:主从间这个变量的差距代表延迟的偏移量
1.2.7 CPU
used_cpu_sys:Redis服务器耗费的系统CPU
used_cpu_user:Redis服务器耗费的用户CPU
used_cpu_sys_children:Redis后台进程耗费的系统CPU
used_cpu_user_children:Redis后台进程耗费的用户CPU
1.2.8 Cluster
cluster_enabled:是否使用集群
1.2.9 Keyspace
dbx:keys=xxx,expires=x,avg_ttl=x:数据库的键数量、带有过期时间的键的数量,存活的时间计数
1.2.10 Commandstats
# Commandstats (执行命令的次数,执行命令所耗费的毫秒数)
cmdstat_replconf:calls=175272,usec=335561,usec_per_call=1.91
cmdstat_command:calls=6,usec=5579,usec_per_call=929.83
cmdstat_set:calls=2117489,usec=8755492,usec_per_call=4.13
cmdstat_auth:calls=417,usec=809,usec_per_call=1.94
cmdstat_zrangebyscore:calls=174,usec=2521,usec_per_call=14.49
cmdstat_latency:calls=1210,usec=2403,usec_per_call=1.99
cmdstat_bgrewriteaof:calls=1,usec=1901,usec_per_call=1901.00
cmdstat_zadd:calls=26908,usec=573861,usec_per_call=21.33
cmdstat_host::calls=16,usec=398,usec_per_call=24.88
cmdstat_zremrangebyscore:calls=2454,usec=14800,usec_per_call=6.03
cmdstat_slowlog:calls=2420,usec=10422,usec_per_call=4.31
cmdstat_info:calls=90152,usec=7952483,usec_per_call=88.21
cmdstat_psync:calls=1,usec=2465,usec_per_call=2465.00
cmdstat_config:calls=1216,usec=101234,usec_per_call=83.25
二、Redis监控工具
2.1 Prometheus+Grafana
Prometheus可以理解为一个数据库+数据抓取工具,从各节点抓来统一的数据,放入Prometheus这一个时间序列数据库中。那如何保证各处的数据格式是统一的呢?就是通过这个exporter。exporter也是用GO写的程序,它开放一个http接口,对外提供格式化的数据。通过在node节点部署exporter即可实现对Redis的监控。Grafana是一个提供高度可视化的工具,将Prometheus的数据进行可视化展示。
[外链图片转存失败(img-Mxmy6uLy-1566821156899)(https://yqfile.alicdn.com/60d24629e2a8379dfa6144f0bf738d83e77bdbc8.png)]
2.2 Redis-monitor
Redis-monitor是由Python编写的开源的图形化监控工具。核心服务部分只包括一个web服务和基于Redis自带的Info命令以及monitor命令的监控服务。支持多实例监控,监控信息可以使用redis存储和sqlite持久化存储。
[外链图片转存失败(img-J9RQKVLY-1566821156900)(https://yqfile.alicdn.com/f0dac048b580fbc3d14abc395c7b1660bbef6c24.png)]
2.3 Redis-stat
Redis-stat是一个用Ruby编写的简单Redis监控工具,基于Redis的INFO命令,因此与基于MONITOR命令的其他监视工具不同,通常不会影响Redis实例的性能。Redis-stat监视Redis实例在客户端输出,也可以提供Web服务器提供的仪表板页面。
redis-stat localhost:6379 -a xxx 1 10 --csv=/tmp/output.csv --verbose #客户端输出类vmstat格式的信息
redis-stat --server --daemon #后台运行,在web界面进行输出。
[外链图片转存失败(img-9izgzyxa-1566821156900)(https://yqfile.alicdn.com/b71a9b002fc4bbfebab236157a80c22fb962d06f.png)]
2.4 Redis-faina
redis-faina是由Instagram开发并开源的一个Redis查询分析工具。Redis-faina是通过Redis的MONITOR命令来实现的,通过对在Redis上执行的query进行监控,统计出一段时间的query特性。
redis-cli -p 6379 MONITOR | head -n | ./redis-faina.py [options] #Redis-faina对MONITOR的输出文件进行分析展示
输出格式如下
Overall Stats
========================================
Lines Processed 7904
Commands/Sec 256.80
Top Prefixes
========================================
n/a
Top Keys
========================================
970125 3952 (50.00%)
aaa850 2 (0.03%)
aaa919 2 (0.03%)
aaa852 2 (0.03%)
aaa853 2 (0.03%)
aaa678 2 (0.03%)
aaa679 2 (0.03%)
aaa856 2 (0.03%)
Top Commands
========================================
AUTH 3952 (50.00%)
set 3950 (49.97%)
Command Time (microsecs)
========================================
Median 1920.0
75% 2016.25
90% 2092.0
99% 2840.0
Heaviest Commands (microsecs)
========================================
AUTH 22542297.5
set 8236623.75
Slowest Calls
========================================
20718202.0 "AUTH" "970125"
8456.0 "set" "aaa82" "aaaaaaaa82"
6624.0 "set" "aaa103" "aaaaaaaa103"
6506.0 "set" "aaa817" "aaaaaaaa817"
6105.0 "set" "aaa2024" "aaaaaaaa2024"
6081.0 "set" "aaa1057" "aaaaaaaa1057"
6074.75 "set" "aaa1948" "aaaaaaaa1948"
6067.0 "set" "aaa576" "aaaaaaaa576"
三、Redis性能优化
3.1 慢查询
通常来讲,时间复杂度是O(1)的命令是安全的,时间复杂度是O(N)命令在使用时需要注意,避免在使用这些O(N)命令时发生问题主要有几个办法:
- 不要把List当做列表使用,仅当做队列来使用。
- 通过机制严格控制Hash、Set、Sorted Set的大小。
- 可能的话,将排序、并集、交集等操作放在客户端执行。
- 绝对禁止使用KEYS命令。
- 避免一次性遍历集合类型的所有成员,而应使用SCAN类的命令进行分批的,游标式的遍历。
3.2 网络延迟
- 尽可能使用长连接或连接池,避免频繁创建销毁连接。
- 客户端进行的批量数据操作,应使用管道完成。
3.3 数据持久化引发的延迟
- AOF + fsync always的设置虽然能够绝对确保数据安全,但每个操作都会触发一次fsync,会对Redis的性能有比较明显的影响。
- AOF + fsync every second是比较好的折中方案,每秒fsync一次。
- AOF + fsync never会提供AOF持久化方案下的最优性能。
- 使用RDB持久化通常会提供比使用AOF更高的性能,但需要注意RDB的策略配置。
- 每一次RDB快照和AOF Rewrite都需要Redis主进程进行fork操作。fork操作本身可能会产生较高的耗时,与CPU和Redis占用的内存大小有关。根据具体的情况合理配置RDB快照和AOF Rewrite时机,避免过于频繁的fork带来的延迟。
3.4 大对象和大键/键个数和长度的突增
- 尽量只用小的KEY,并且KEY要有可读性,严格控制Value的大小。
3.5 数据淘汰引发的延迟
- 当同一秒内有大量key过期时,也会引发Redis的延迟。在使用时应尽量将key的失效时间错开。
3.6 引入读写分离机制
Redis的主从复制能力可以实现一主多从的多节点架构,在这一架构下,主节点接收所有写请求,并将数据同步给多个从节点。在这一基础上,可以让从节点提供对实时性要求不高的读请求服务,以减小主节点的压力。尤其是针对一些使用了长耗时命令的统计类任务,完全可以指定在一个或多个从节点上执行,避免这些长耗时命令影响其他请求的响应。