redis 性能指标


性能指标


1 Info 命令

redis使用info命令获取所有与Redis服务相关的各种信息和统计数值

    server   查看 Redis 服务器信息,如 Redis 的版本
    clients  客户端的连接部分
    memory   内存消耗相关信息       #
    persistence  RDB和AOF相关信息
    stats      一般统计           #
    replication   主/从复制信息
    cpu     统计CPU的消耗
    commandstats   Redis命令统计  #
    cluster    Redis集群信息
    keyspace   数据库的相关统计
    dbsize: 查看当前db的key数量

1) info memory 只返回与内存相关的数据

指标

含义

used_memory

由 Redis 分配器分配的内存总量,包含了redis进程内部的开销和数据占用的内存,以字节(byte)为单位,即当前redis使用内存大小

used_memory_human

已更直观的单位展示分配的内存总量。

used_memory_rss

向操作系统申请的内存大小,与 top 、 ps等命令的输出一致,即redis使用的物理内存大小。

used_memory_rss_human

已更直观的单位展示向操作系统申请的内存大小。

used_memory_peak

redis的内存消耗峰值(以字节为单位),即历史使用记录中redis使用内存峰值。

used_memory_peak_human

以更直观的格式返回redis的内存消耗峰值

used_memory_peak_perc

使用内存达到峰值内存的百分比,used_memory/ used_memory_peak) *100%,即当前redis使用内存/历史使用记录中redis使用内存峰值*100%

used_memory_overhead

Redis为了维护数据集的内部机制所需的内存开销,包括所有客户端输出缓冲区、查询缓冲区、AOF重写缓冲区和主从复制的backlog。

used_memory_startup

Redis服务器启动时消耗的内存

used_memory_dataset

数据实际占用的内存大小,即used_memory-used_memory_overhead

used_memory_dataset_perc

数据占用的内存大小的百分比,100%*(used_memory_dataset/(used_memory-used_memory_startup))

total_system_memory

整个系统内存

total_system_memory_human

以更直观的格式显示整个系统内存

used_memory_lua

Lua脚本存储占用的内存

used_memory_lua_human

以更直观的格式显示Lua脚本存储占用的内存

maxmemory

Redis实例的最大内存配置

maxmemory_human

以更直观的格式显示Redis实例的最大内存配置

maxmemory_policy

当达到maxmemory时的淘汰策略

mem_fragmentation_ratio

碎片率,used_memory_rss/ used_memory。ratio指数>1表明有内存碎片,越大表明越多,<1表明正在使用虚拟内存,虚拟内存其实就是硬盘,性能比内存低得多,这是应该增强机器的内存以提高性能。一般来说,mem_fragmentation_ratio的数值在1 ~ 1.5之间是比较健康的。详解

mem_allocator

内存分配器

active_defrag_running

表示没有活动的defrag任务正在运行,1表示有活动的defrag任务正在运行(defrag:表示内存碎片整理)详解

lazyfree_pending_objects

0表示不存在延迟释放的挂起对象

2) info stats 一般统计信息

指标 含义
total_connections_received 服务器接受的连接总数
total_commands_processed 服务器处理的命令总数
instantaneous_ops_per_sec 每秒处理的命令数
rejected_connections 由于maxclients限制而拒绝的连接数
expired_keys key到期事件的总数
evicted_keys 由于maxmemory最大内存限制而导致被驱逐的key的数量
keyspace_hits key命中次数
keyspace_misses key未命中次数

3) info clients 已连接客户端信息

指标 含义
connected_clients 已连接客户端的数量(不包括通过从属服务器连接的客户端
client_longest_output_list 当前连接的客户端当中,最长的输出列表
client_biggest_input_buf 当前连接的客户端当中,最大输入缓存
blocked_clients 正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量

4) info cpu 统计CPU的消耗

指标 含义
used_cpu_sys 消耗的系统CPU
used_cpu_user 消耗的用户CPU
used_cpu_sys_children 后台进程占用的系统CPU
used_cpu_user_children 后台进程占用的用户CPU

5) info commandstats Redis命令统计

提供基于命令类型的统计信息,包括调用次数,这些命令消耗的总CPU时间以及每个命令执行消耗的平均CPU时间

对于每一个命令类型,添加以下行:

    cmdstat_XXX: calls=XXX,usec=XXX,usec_per_call=XXX

    calls 次数
    usec 时间
    usec_per_call 平均时间

2 memory 命令

获得有关服务器内存的其他内省信息,可以参考MEMORY STATSMEMORY DOCTOR

指标 含义
MEMORY DOCTOR 列出 Redis 服务器遇到的内存相关问题,并提供相应的解决建议
MEMORY MALLOC-STATS 提供内存分配情况的内部统计报
MEMORY PURGE 尝试清除脏页以便内存分配器回收使用
MEMORY USAGE key 给出一个 key 和它的值在 RAM 中所占用的字节数
MEMORY STATS 将服务器的内存使用情况以数组情况返回
    jemalloc作为内存分配器

1) MEMORY STATS 命令将服务器的内存使用情况以数组情况返回

指标 含义
peak.allocated redis启动以来,allocator分配的内存峰值,单位字节;同INFO的used_memory_peak
total.allocated allocator 当前分配的内存总字节数;同 INFO命令used_memeory
startup.allocated Redis启动完成消耗的内存字节数;同INFO的used_memory_startup
clients.normal Redis所有常规客户端内存消耗总字节数(查询输出缓冲区,连接内存消耗)
overhead.total Redis 额外内存消耗总字节数,i.e. startup.allocated, replication.backlog, clients.slaves, clients.normal, aof.buffer 以及管理keyspace使用的内部数据接口消耗的内存字节数 同INFO的used_memory_overhead
keys.count 整个redis实例key的个数
keys.bytes-per-key 每个key平均字节数,net memory usage(total.allocated 减去 startup.allocated)与keys.count的比值
dataset.bytes Redis 实例中数据占用的总字节数,计算方法total.allocated减去overhead.total
dataset.percentage Redis 数据消耗内存占总内存的百分比
peak.percentage 当前内存消耗占峰值内存消耗的百分比

参考 » Redis 为什么变慢了?一文讲透如何排查 Redis 性能问题 | 万字长文


redis性能排查调优


1) 确定Redis链路耗时变长

    - (1)业务服务器到 Redis 服务器之间的网络存在问题,例如网络线路质量不佳,网络数据包在传输时存在延迟、丢包等情况 ( 第一种情况发生的概率比较小,如果是服务器之间网络存在问题,那部署在这台业务服务器上的所有服务都会发生网络延迟的情况,此时你需要联系网络运维同事,让其协助解决网络问题 )
    
    - (2)Redis 本身存在问题,需要进一步排查是什么原因导致 Redis 变慢

首先对 Redis 进行基准性能测试,了解Redis 在生产环境服务器上的基准性能

    基准性能 
    
    就是指 Redis 在一台负载正常的机器上
    
        最大的响应延迟
        平均响应延迟

避免业务服务器到 Redis 服务器之间的网络延迟,你需要直接在 Redis 服务器上测试实例的响应延迟情况

# 60 秒内的最大响应延迟

redis-cli -h 10.0.0.207 -p 16379 --intrinsic-latency 60

...
Max latency so far: 1488 microseconds.
Max latency so far: 5059 microseconds.



# 每间隔 1 秒,采样 Redis 的平均操作耗时

redis-cli -h 10.0.0.207 -p 16379 --latency-history -i 1 

min: 0, max: 7, avg: 0.43 (95 samples) -- 1.00 seconds range
...


2) 慢查询定位 slowlog

    127.0.0.1:6379> SLOWLOG get 5
    1) 1) (integer) 32693       # 慢日志ID
       2) (integer) 1593763337  # 执行时间戳
       3) (integer) 5299        # 执行耗时(微秒)
       4) 1) "LPUSH"            # 具体执行的命令和参数
          2) "Ftask"
          3) "0"


3) 避免使用复杂度过高的命令

  • 尽量不使用 O(N) 以上复杂度过高的命令,对于数据的聚合操作 (例如 SORT、SUNION、ZUNIONSTORE ),放在客户端做

  • 执行 O(N) 命令,保证 N 尽量的小(推荐 N <= 300),每次获取尽量少的数据,让 Redis 可以及时处理返回


4) 避免操作 bigkey

慢日志发现 SET / DEL 这种简单命令出现在慢日志中,那么你就要怀疑你的实例否写入了 bigkey

# 扫描 bigkey 的分布
redis-cli -h 127.0.0.1 -p 6379 --bigkeys -i 0.01 (单位是秒)
    Sampled 103 keys in the keyspace!
    Total key length in bytes is 4299 (avg len 41.74)
    
    Biggest string found 'stats:crawler:200:lifetime' has 12304 bytes
    Biggest   list found 'mplete:items' has 2128537 items
    Biggest    set found 'link:blacklist' has 3 members
    Biggest   zset found 'stats:200:86400' has 148509 members
    
    45 strings with 14416 bytes (43.69% of keys, avg size 320.36)
    3 lists with 2135188 items (02.91% of keys, avg size 711729.33)
    3 sets with 5 members (02.91% of keys, avg size 1.67)
    0 hashs with 0 fields (00.00% of keys, avg size 0.00)
    52 zsets with 355218 members (50.49% of keys, avg size 6831.12)

    原理: Redis 在内部执行了 SCAN 命令,遍历整个实例中所有的 key,然后针对 key 的类型,分别执行 STRLEN、LLEN、HLEN、SCARD、ZCARD 命令,来获取 String 类型的长度、容器类型(List、Hash、Set、ZSet)的元素个数

   注意: 对线上实例进行 bigkey 扫描时,Redis 的 OPS 会突增,为了降低扫描过程中对 Redis 的影响,最好控制一下扫描的频率,指定 -i 参数即可
   
   优化: 
        1) 业务应用尽量避免写入 bigkey
        2) Redis 4.0+,用 UNLINK 命令替代 DEL
        此命令可以把释放 key 内存的操作,放到后台线程中去执行,从而降低对 Redis 的影响
        3)  开启 lazy-free,  执行 DEL 命令时,释放内存也会放到后台线程中执行

5) 避免过期时间集中

Redis 的过期数据采用被动过期 + 主动过期两种策略

被动过期:只有当访问某个 key 时,才判断这个 key 是否已过期,如果已过期,则从实例中删除

主动过期:Redis 内部维护了一个定时任务,默认每隔 100 毫秒(1 秒 10 次)就会从全局的过期哈希表中随机取出 20 个 key,然后删除其中过期的 key,如果过期 key 的比例超过了 25%,则继续重复此过程,直到过期 key 的比例下降到 25% 以下,或者这次任务的执行耗时超过了 25 毫秒,才会退出循环

主动过期 key 的定时任务,是在 Redis 主线程中执行

优化: 

    1) 集中过期 key 增加一个随机过期时间,把集中过期的时间打散,降低 Redis 清理过期 key 的压力

    2) Redis 4.0 +,可以开启 lazy-free 机制,当删除过期 key 时,把释放内存的操作放到后台线程中执行,避免阻塞主线程

6) 实例内存达到上限maxmemory

当 Redis 内存达到 maxmemory 后,每次写入新的数据之前,Redis 必须先从实例中踢出一部分数据,让整个实例的内存维持在 maxmemory 之下,然后才能把新数据写进来

踢出旧数据的逻辑也是需要消耗时间的,而具体耗时的长短,要取决于你配置的淘汰策略:

allkeys-lru:不管 key 是否设置了过期,淘汰最近最少访问的 key

volatile-lru:只淘汰最近最少访问、并设置了过期时间的 key

allkeys-random:不管 key 是否设置了过期,随机淘汰 key

volatile-random:只随机淘汰设置了过期时间的 key

allkeys-ttl:不管 key 是否设置了过期,淘汰即将过期的 key

noeviction:不淘汰任何 key,实例内存达到 maxmeory 后,再写入新数据直接返回错误

allkeys-lfu:不管 key 是否设置了过期,淘汰访问频率最低的 key(4.0+版本支持)

volatile-lfu:只淘汰访问频率最低、并设置了过期时间 key(4.0+版本支持)

一般最常使用的是 allkeys-lru / volatile-lru 淘汰策略

如果此时你的 Redis 实例中还存储了 bigkey,那么在淘汰删除 bigkey 释放内存时,也会耗时比较久



优化: 

   1) 避免存储 bigkey,降低释放内存的耗时
   2) 淘汰策略改为随机淘汰,随机淘汰比 LRU 要快很多(视业务情况调整)
   3) 拆分实例,把淘汰 key 的压力分摊到多个实例上
   4) Redis 4.0 +,开启 layz-free 机制,把淘汰 key 释放内存的操作放到后台线程中执行(配置 lazyfree-lazy-eviction = yes)

7) 数据持久化 fork 耗时严重

info stats 



latest_fork_usec:19408 (微秒)

这个时间就是主进程在 fork 子进程期间,整个实例阻塞无法处理客户端请求的时间

果你发现这个耗时很久,就要警惕起来了,这意味在这期间,你的整个 Redis 实例都处于不可用的状态。

优化: 

    1)控制 Redis 实例的内存:尽量在 10G 以下,执行 fork 的耗时与实例大小有关,实例越大,耗时越久
    2) 合理配置数据持久化策略:在 slave 节点执行 RDB 备份,推荐在低峰期执行,而对于丢失数据不敏感的业务(例如把 Redis 当做纯缓存使用),可以关闭 AOF 和 AOF rewrite
    3)Redis 实例不要部署在虚拟机上:fork 的耗时也与系统也有关,虚拟机比物理机耗时更久
    
    4)降低主从库全量同步的概率:适当调大 repl-backlog-size 参数,避免主从全量同步

8)关闭 内存大页

主进程在拷贝内存数据时,这个阶段就涉及到新内存的申请,如果此时操作系统开启了内存大页,那么在此期间,客户端即便只修改 10B 的数据,Redis 在申请内存时也会以 2MB 为单位向操作系统申请,申请内存的耗时变长,进而导致每个写请求的延迟增加,影响到 Redis 性能

cat /sys/kernel/mm/transparent_hugepage/enabled


[always] madvise never
输出选项是 always,就表示目前开启了内存大页机制,我们需要关掉它

echo never > /sys/kernel/mm/transparent_hugepage/enabled

开启内存大页,可以在一定程序上降低应用程序申请内存的次数

但是对于 Redis 这种对性能和延迟极其敏感的数据库来说,我们希望 Redis 在每次申请内存时,耗时尽量短,

不建议你在 Redis 机器上开启这个机制

汇总

CPU 相关:使用复杂度过高命令、数据的持久化,都与耗费过多的 CPU 资源有关

内存相关:bigkey 内存的申请和释放、数据过期、数据淘汰、碎片整理、内存大页、内存写时复制都与内存息息相关

磁盘相关:数据持久化、AOF 刷盘策略,也会受到磁盘的影响

网络相关:短连接、实例流量过载、网络流量过载,也会降低 Redis 性能

计算机系统:CPU 结构、内存分配,都属于最基础的计算机系统知识

操作系统:写时复制、内存大页、Swap、CPU 绑定,都属于操作系统层面的知识
Buy me a 肥仔水!