Redis 实时监控与性能分析:Jedis + INFO 命令实战

基于 Redis INFO 命令和 Jedis 客户端,实现 Redis 运行状态的实时监控,包括内存使用、QPS、连接数、慢日志、缓存命中率等核心指标,并附带完整的 INFO 参数中文翻译对照表。


一、项目概述

1.1 监控目标

通过 Java 代码调用 Redis INFO 指令,获取 Redis 实例的运行数据,实现以下监控维度:

监控维度 关键指标
内存使用 used_memory、used_memory_rss、mem_fragmentation_ratio
性能指标 instantaneous_ops_per_sec(QPS)、命中率
连接状态 connected_clients、blocked_clients、rejected_connections
持久化 rdb_last_save_time、aof_enabled、aof_current_size
复制状态 master_repl_offset、connected_slaves、sync 状态
键统计 keyspace_hits、keyspace_misses、expired_keys、evicted_keys
慢日志 slowlog 查询与重置

1.2 技术架构

┌─────────────────┐     ┌──────────────┐     ┌─────────────────┐
│  INFO 命令       │◄────│  JedisPool   │◄────│  RedisConfig    │
│  (Redis Server)  │     │  (连接池)     │     │  (Spring Boot)  │
└─────────────────┘     └──────┬───────┘     └─────────────────┘
                               │
                    ┌──────────▼──────────┐
                    │    JedisUtil         │
                    │  (监控数据采集层)      │
                    └──────────┬──────────┘
                               │
          ┌────────────────────┼────────────────────┐
          ▼                    ▼                    ▼
   RedisMonitoringInfo  RedisIdService     RedisMonitoringService
   (概览面板数据)        (全量指标接口)       (动态图表数据)
          │                    │                    │
          └────────────────────┼────────────────────┘
                               ▼
                      Redis实时监控页面
                    (内存/QPS/CPU/命中率)

二、基础配置

2.1 RedisConfig:JedisPool 配置

package com.redis.monitor.config;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.util.logging.Logger;

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.password}")
    private String password;

    @Bean
    public JedisPool redisPoolFactory() {
        Logger.getLogger(getClass()).info("JedisPool注入成功!!");
        Logger.getLogger(getClass()).info("redis地址:" + host + ":" + port);
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // 可按需配置连接池参数
        jedisPoolConfig.setMaxTotal(200);
        jedisPoolConfig.setMaxIdle(50);
        jedisPoolConfig.setMinIdle(10);
        jedisPoolConfig.setTestOnBorrow(true);
        jedisPoolConfig.setTestOnReturn(true);

        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
        return jedisPool;
    }
}

2.2 application.yml 配置

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: yourpassword
    timeout: 5000

三、监控数据采集层

3.1 JedisUtil:核心采集工具

package com.redis.monitor.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Client;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.util.Slowlog;

import java.util.List;

@Component
public class JedisUtil {

    @Autowired
    JedisPool jedisPool;

    /**
     * 获取 Redis 服务器完整 INFO 信息
     */
    public String getRedisInfo() {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            Client client = jedis.getClient();
            client.info();
            String info = client.getBulkReply();
            return info;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 返还到连接池
            jedis.close();
        }
        return null;
    }

    /**
     * 获取慢日志列表
     * @param entries 返回的条目数
     */
    public List<Slowlog> getLogs(long entries) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            List<Slowlog> logList = jedis.slowlogGet(entries);
            return logList;
        } finally {
            jedis.close();
        }
    }

    /**
     * 获取慢日志总条数
     */
    public Long getLogsLen() {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            long logLen = jedis.slowlogLen();
            return logLen;
        } finally {
            jedis.close();
        }
    }

    /**
     * 清空慢日志
     */
    public String logEmpty() {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.slowlogReset();
        } finally {
            jedis.close();
        }
    }

    /**
     * 获取当前数据库 Key 的数量
     */
    public Long dbSize() {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            Client client = jedis.getClient();
            client.dbSize();
            return client.getIntegerReply();
        } finally {
            jedis.close();
        }
    }
}

四、INFO 参数中文翻译对照

4.1 RedisInfoDetail:参数翻译器

package com.redis.monitor.model;

import java.util.HashMap;
import java.util.Map;

/**
 * Redis INFO 命令返回参数的中文翻译解释
 * 将 Redis 的英文参数名映射为可读的中文描述
 */
public class RedisInfoDetail {

    private static Map<String, String> map = new HashMap<String, String>();

    static {
        // ========== Server 部分 ==========
        map.put("redis_version", "Redis 服务器版本");
        map.put("redis_git_sha1", "Git SHA1");
        map.put("redis_git_dirty", "Git dirty flag");
        map.put("os", "Redis 服务器的宿主操作系统");
        map.put("redis_build_id", "Redis 构建ID");
        map.put("redis_mode", "Redis启动模式:standalone、Sentinel、Cluster");
        map.put("arch_bits", "架构(32 或 64 位)");
        map.put("multiplexing_api", "Redis 所使用的事件处理机制");
        map.put("gcc_version", "编译 Redis 时所使用的 GCC 版本");
        map.put("process_id", "服务器进程的 PID");
        map.put("run_id", "Redis 服务器的随机标识符(用于 Sentinel 和集群)");
        map.put("tcp_port", "TCP/IP 监听端口");
        map.put("uptime_in_seconds", "自 Redis 服务器启动以来,经过的秒数");
        map.put("uptime_in_days", "自 Redis 服务器启动以来,经过的天数");
        map.put("hz", "redis内部调度(进行关闭timeout的客户端,删除过期key等等)频率");
        map.put("configured_hz", "redis的配置状态频率");
        map.put("executable", "服务器可执行文件的路径");
        map.put("config_file", "启动 redis 配置文件");
        map.put("lru_clock", "以分钟为单位进行自增的时钟,用于 LRU 管理");

        // ========== Clients 部分 ==========
        map.put("connected_clients", "已连接客户端的数量(不包括通过从属服务器连接的客户端)");
        map.put("client_longest_output_list", "当前连接的客户端当中,最长的输出列表");
        map.put("client_longest_input_buf", "当前连接的客户端当中,最大输入缓存");
        map.put("blocked_clients", "正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量");
        map.put("client_recent_max_output_buffer", "当前连接的客户端当中,最长的输出列表");
        map.put("client_recent_max_input_buffer", "当前连接的客户端当中,最大输入缓存");

        // ========== Memory 部分 ==========
        map.put("used_memory", "由 Redis 分配器分配的内存总量,以字节(byte)为单位");
        map.put("used_memory_human", "以人类可读的格式返回 Redis 分配的内存总量");
        map.put("used_memory_rss", "从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小)。这个值和 top 、 ps 等命令的输出一致");
        map.put("used_memory_rss_human", "以可读的格式,操作系统角度,返回 redis 分配的内存总量");
        map.put("used_memory_peak", "Redis 的内存消耗峰值(以字节为单位)");
        map.put("used_memory_peak_human", "以人类可读的格式返回 Redis 的内存消耗峰值");
        map.put("total_system_memory", "主机拥有的内存总量");
        map.put("total_system_memory_human", "以可读的格式返回主机拥有的内存总量");
        map.put("used_memory_lua", "Lua 引擎所使用的内存大小(以字节为单位)");
        map.put("used_memory_lua_human", "以可读的格式返回Lua引擎使用内存");
        map.put("maxmemory_human", "以可读的格式返回Redis实例的最大内存配置");
        map.put("maxmemory", "Redis实例的最大内存配置");
        map.put("maxmemory_policy", "当达到maxmemory时的淘汰策略");
        map.put("used_memory_startup", "启动时消耗的初始内存量(以字节为单位)");
        map.put("used_memory_overhead", "数据集的大小(以字节为单位,used_memory - used_memory_overhead)");
        map.put("used_memory_peak_perc", "used_memory_peak在used_memory中所占的百分比");
        map.put("used_memory_dataset", "数据集的大小(以字节为单位,used_memory - used_memory_overhead)");
        map.put("used_memory_dataset_perc", "used_memory_dataset在净内存(used_memory-used_memory_startup)使用量中所占的百分比");
        map.put("mem_aof_buffer", "aof时,占用的缓冲");
        map.put("mem_allocator", "内存分配器(在编译时选择)");
        map.put("mem_clients_normal", "Redis的客户端主的分配信息量");
        map.put("mem_clients_slaves", "Redis的客户端从的分配信息量");
        map.put("mem_replication_backlog", "Redis的内存复制积压分配信息量");
        map.put("mem_not_counted_for_evict", "被驱逐的大小");
        map.put("mem_fragmentation_bytes", "内存碎片的大小(以字节为单位)");
        map.put("mem_fragmentation_ratio", "内存碎片率,used_memory_rss 和 used_memory 之间的比率");
        map.put("rss_overhead_ratio", "常驻内存开销比例");
        map.put("rss_overhead_bytes", "常驻内存开销大小(以字节为单位)");
        map.put("allocator_rss_bytes", "分配器的常驻内存大小(以字节为单位)");
        map.put("allocator_rss_ratio", "分配器常驻内存比例");
        map.put("allocator_frag_bytes", "分配器的碎片大小(以字节为单位)");
        map.put("allocator_frag_ratio", "分配器的碎片率");
        map.put("allocator_resident", "分配器常驻的内存");
        map.put("allocator_active", "分配器活跃的内存");
        map.put("allocator_allocated", "分配器分配的内存");
        map.put("used_memory_scripts_human", "人类使用过的记忆脚本");
        map.put("used_memory_scripts", "Redis使用的内存脚本");

        // ========== Persistence 部分 ==========
        map.put("loading", "服务器是否正在载入持久化文件");
        map.put("rdb_changes_since_last_save", "离最近一次成功生成rdb文件,写入命令的个数");
        map.put("rdb_bgsave_in_progress", "服务器是否正在创建rdb文件");
        map.put("rdb_last_save_time", "最近一次成功rdb文件的时间戳");
        map.put("rdb_last_bgsave_status", "最近一次成功rdb文件的状态");
        map.put("rdb_last_bgsave_time_sec", "最近一次成功rdb文件的耗时");
        map.put("rdb_current_bgsave_time_sec", "若当前正在创建rdb文件,指当前的创建操作已经耗费的时间");
        map.put("rdb_last_cow_size", "上一次RBD保存操作期间写时复制的大小(以字节为单位)");
        map.put("aof_enabled", "aof是否开启");
        map.put("aof_rewrite_in_progress", "aof的rewrite操作是否在进行中");
        map.put("aof_last_cow_size", "上一次AOF保存操作期间写时复制的大小(以字节为单位)");
        map.put("aof_rewrite_scheduled", "rewrite任务计划,当客户端发送bgrewriteaof指令,如果当前rewrite子进程正在执行,那么将客户端请求的bgrewriteaof变为计划任务,待aof子进程结束后执行rewrite");
        map.put("aof_last_rewrite_time_sec", "最近一次aof rewrite耗费时长");
        map.put("aof_current_rewrite_time_sec", "若当前正在执行aof rewrite,指当前的已经耗费的时间");
        map.put("aof_last_bgrewrite_status", "最近一次aof bgrewrite的状态");
        map.put("aof_last_write_status", "最近一次aof写入状态");
        map.put("aof_current_size", "aof文件当前大小");
        map.put("aof_pending_rewrite", "rewrite任务计划,当客户端发送bgrewriteaof指令,如果当前rewrite子进程正在执行,那么将客户端请求的bgrewriteaof变为计划任务,待aof子进程结束后执行rewrite");
        map.put("aof_buffer_length", "aof 缓冲区的大小");
        map.put("aof_rewrite_buffer_length", "aof 重写缓冲区的大小");
        map.put("aof_pending_bio_fsync", "后台IO队列中,等待fsync任务的个数");
        map.put("aof_delayed_fsync", "被延迟的 fsync 调用数量");

        // ========== Stats 部分 ==========
        map.put("total_connections_received", "自启动起连接过的总数。如果连接过多,说明短连接严重或连接池使用有问题,需调研代码的连接设置");
        map.put("total_commands_processed", "自启动起运行命令的总数");
        map.put("instantaneous_ops_per_sec", "每秒执行的命令数,相当于QPS");
        map.put("total_net_input_bytes", "网络入口流量字节数");
        map.put("total_net_output_bytes", "网络出口流量字节数");
        map.put("instantaneous_input_kbps", "网络入口kps");
        map.put("instantaneous_output_kbps", "网络出口kps");
        map.put("rejected_connections", "拒绝的连接个数,由于maxclients限制,拒绝新连接的个数");
        map.put("sync_full", "主从完全同步成功次数");
        map.put("sync_partial_ok", "主从部分同步成功次数");
        map.put("sync_partial_err", "主从部分同步失败次数");
        map.put("expired_keys", "自启动起过期的key的总数");
        map.put("evicted_keys", "使用内存大于maxmemory后,淘汰的key的总数");
        map.put("expired_stale_perc", "过期的比率");
        map.put("expired_time_cap_reached_count", "过期计数");
        map.put("keyspace_hits", "在main dictionary字典中成功查到的key个数");
        map.put("keyspace_misses", "同上,未命中的key的个数");
        map.put("pubsub_channels", "发布/订阅频道数");
        map.put("pubsub_patterns", "发布/订阅模式数");
        map.put("latest_fork_usec", "上次的fork操作使用的时间(单位ms)");
        map.put("migrate_cached_sockets", "是否已经缓存了到该地址的连接");
        map.put("slave_expires_tracked_keys", "从实例到期key数量");

        // ========== Replication 部分 ==========
        map.put("role", "当前实例的角色master还是slave");
        map.put("connected_slaves", "slave的数量");
        map.put("master_replid", "主实例启动随机字符串");
        map.put("master_replid2", "主实例启动随机字符串2");
        map.put("slave0", "slave机器的信息、状态");
        map.put("master_repl_offset", "主从同步偏移量,此值如果和上面的offset相同说明主从一致没延迟,与master_replid可被用来标识主实例复制流中的位置。");
        map.put("second_repl_offset", "主从同步偏移量2,此值如果和上面的offset相同说明主从一致没延迟");
        map.put("repl_backlog_size", "复制缓冲区大小");
        map.put("repl_backlog_first_byte_offset", "复制缓冲区里偏移量的大小");
        map.put("repl_backlog_histlen", "此值等于 master_repl_offset - repl_backlog_first_byte_offset,该值不会超过repl_backlog_size的大小");
        map.put("repl_backlog_active", "复制缓冲区是否开启");

        // ========== CPU 部分 ==========
        map.put("used_cpu_sys", "Redis 服务器耗费的系统 CPU");
        map.put("used_cpu_user", "Redis 服务器耗费的用户 CPU");
        map.put("used_cpu_sys_children", "后台进程的核心态cpu使用率");
        map.put("used_cpu_user_children", "后台进程的用户态cpu使用率");

        // ========== Cluster 部分 ==========
        map.put("cluster_enabled", "例是否启用集群模式");

        // ========== Keyspace 部分 ==========
        map.put("Keyspace", "redis的Keyspace_db0值");

        // ========== 其他 ==========
        map.put("active_defrag_running", "碎片整理是否处于活动状态");
        map.put("active_defrag_hits", "主动碎片整理命中次数");
        map.put("active_defrag_misses", "主动碎片整理未命中次数");
        map.put("active_defrag_key_hits", "主动碎片整理key命中次数");
        map.put("active_defrag_key_misses", "主动碎片整理key未命中次数");
        map.put("lazyfree_pending_objects", "等待释放的对象数(由于使用ASYNC选项调用UNLINK或FLUSHDB和FLUSHALL)");
        map.put("number_of_cached_scripts", "Redis缓存脚本的数量");
        map.put("atomicvar_api", "Atomicvar API");
    }

    private String key;
    private String value;
    private String desctiption;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
        this.desctiption = map.get(this.key);
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getDesctiption() {
        return desctiption;
    }

    public void setDesctiption(String desctiption) {
        this.desctiption = desctiption;
    }

    @Override
    public String toString() {
        return "RedisInfoDetail [key=" + key + ", value=" + value
                + ", desctiption=" + desctiption + "]";
    }
}

五、慢日志模型

5.1 Operate:慢查询日志实体

package com.redis.monitor.model;

/**
 * Redis 慢查询日志实体
 * 对应 SLOWLOG GET 返回的每条记录
 */
public class Operate {

    private long id;            // slowlog唯一编号id
    private String executeTime; // 查询的时间戳
    private String usedTime;    // 查询的耗时(微妙),如表示本条命令查询耗时47微秒
    private String args;        // 查询命令,完整命令为 SLOWLOG GET,slowlog最多保存前面的31个key和128字符

    public Operate() {}

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getExecuteTime() {
        return executeTime;
    }

    public void setExecuteTime(String executeTime) {
        this.executeTime = executeTime;
    }

    public String getUsedTime() {
        return usedTime;
    }

    public void setUsedTime(String usedTime) {
        this.usedTime = usedTime;
    }

    public String getArgs() {
        return args;
    }

    public void setArgs(String args) {
        this.args = args;
    }
}

六、监控服务接口

6.1 RedisMonitoringInfo:监控概览面板

package com.redis.monitor.service;

import java.util.Map;

/**
 * 监控概览面板 - 获取 Redis 核心运行状态摘要
 */
public interface RedisMonitoringInfo {
    /**
     * @return 监控页面数据(进程ID、命中率、连接数、Key数、内存使用)
     */
    Map<String, Object> getMonitoringInfo();
}

6.2 RedisMonitoring:动态图表数据

package com.redis.monitor.service;

import java.util.Map;

/**
 * 监控动态图表 - 获取 Redis 实时动态数据
 */
public interface RedisMonitoring {
    /**
     * @param qps  采样QPS值
     * @param time 时间差值(秒)
     * @return 包含内存、CPU、QPS、时间戳的动态数据
     */
    Map<String, Object> getMonitoring(Integer qps, Integer time);
}

6.3 RedisIdService:全量指标查询接口

package com.redis.monitor.service;

import com.redis.monitor.model.Operate;
import java.util.List;
import java.util.Map;

/**
 * Redis 全量监控指标查询服务
 */
public interface RedisIdService {

    /** 获取 Redis INFO 完整参数列表 */
    List<Map<String, Object>> getRedisInfo();

    /** 获取 QPS 动态数据 */
    Double getDbSizeQps(Integer qps, Integer time);

    /** 获取 Redis 慢日志列表 */
    List<Operate> getLogs(long entries);

    /** 获取日志总数 */
    Long getLogLen();

    /** 清空日志 */
    String logEmpty();

    /** 获取当前数据库中 key 的数量 */
    Map<String, Object> getKeysSize();

    /** 获取当前 Redis 使用内存大小情况 */
    Map<String, Object> getMemeryInfo();

    /** 获取内存详情列表 */
    Map<String, Object> getMemeryInfolist();

    /** 获取 Redis 内存大小 */
    String getUsedMemory();

    /** 获取内存碎片率 */
    String getMemFragmentationRatio();

    /** 获取 CPU 系统使用率 */
    String getUsedCpuSys();

    /** 获取 CPU 用户态使用率 */
    String getUsedCpuUserChildren();

    /** 获取总连接数 */
    String getTotalConnectionsReceived();

    /** 获取内存常驻集大小(RSS) */
    String getUsedMemoryRss();

    /** 获取当前客户端连接数 */
    String getConnectedClients();

    /** 获取缓存命中率 */
    String getHitProbability();

    /** 获取进程 ID */
    String getProcessId();

    /** 获取 Redis db 库总量 */
    Integer getDbId();

    /** 获取 Keyspace 信息 */
    String getKeyspace();

    /** 获取 key 值列表(分页) */
    List<Map<String, Object>> getAllRedisVal2(Integer pageSize, Integer pageNumber, Integer id, String key);

    /** 切换 Redis db 库 */
    List<Map<String, Object>> getSwitchoverRedis();
}

七、监控服务实现

7.1 RedisMonitoringInfoServiceImpl:监控面板实现

package com.redis.monitor.service.impl;

import com.redis.monitor.service.RedisIdService;
import com.redis.monitor.service.RedisMonitoringInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * 监控概览面板实现
 */
@Service
public class RedisMonitoringInfoServiceImpl implements RedisMonitoringInfo {

    @Autowired
    private RedisIdService redisService;

    @Override
    public Map getMonitoringInfo() {
        Map<String, Object> map = new HashMap<>();
        Integer dbId = redisService.getDbId();
        String processId = redisService.getProcessId();
        String usedMemory = redisService.getUsedMemory();
        String connectedClients = redisService.getConnectedClients();
        String hitProbability = redisService.getHitProbability();

        map.put("processId", processId);
        map.put("hitProbability", hitProbability);
        map.put("connectedClients", connectedClients);
        map.put("keysSize", dbId);
        map.put("usedMemory", usedMemory + "M");
        return map;
    }
}

7.2 RedisMonitoringServiceImpl:动态图表实现

package com.redis.monitor.service.impl;

import com.redis.monitor.service.RedisIdService;
import com.redis.monitor.service.RedisMonitoring;
import com.redis.monitor.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 动态图表数据实现
 * 实时采集 Redis 内存、CPU、QPS 数据,供前端图表展示
 */
@Service
public class RedisMonitoringServiceImpl implements RedisMonitoring {

    @Autowired
    private RedisIdService redisService;

    @Autowired
    private RedisUtil redisUtils;

    @Override
    public Map<String, Object> getMonitoring(Integer qps, Integer time) {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        Map<String, Object> item = new HashMap<String, Object>();
        List<Map<String, Object>> arrayList = new ArrayList<Map<String, Object>>();

        // 采集当前时刻的监控数据
        String usedMemory = redisService.getUsedMemory();
        String usedCpuSys = redisService.getUsedCpuSys();
        String usedMemoryRss = redisService.getUsedMemoryRss();
        Double dbSizeQps = redisService.getDbSizeQps(qps, time);

        // 组装内存数据
        Map<String, Object> memeryInfomap = new HashMap<String, Object>();
        memeryInfomap.put("usedMemoryRss", usedMemoryRss);
        memeryInfomap.put("usedMemory", usedMemory + "M");

        // 组装返回数据
        item.put("dbSizeQps", dbSizeQps);
        item.put("memeryInfomap", memeryInfomap);
        item.put("usedCpuSys", usedCpuSys);

        Date d = new Date();
        String str = sdf.format(d);
        item.put("date", str);

        return item;
    }
}

八、监控指标详解

8.1 核心监控指标说明

前端展示项 对应 INFO 参数 说明
进程ID process_id Redis 服务器进程 ID,用于进程级别监控
内存使用 used_memory 已分配内存总量(含碎片),单位 M
内存常驻集 used_memory_rss 操作系统角度已分配内存,反映实际物理占用
内存碎片率 mem_fragmentation_ratio RSS/used_memory,>1.5 需要关注
QPS instantaneous_ops_per_sec 每秒执行的命令数,核心性能指标
客户端连接数 connected_clients 当前连接数,异常升高需排查
缓存命中率 hit/miss 比例 keyspace_hits/(keyspace_hits+keyspace_misses)
CPU 使用率 used_cpu_sys/user 系统态/用户态 CPU 消耗
过期 Key expired_keys 自启动起过期 key 总数
淘汰 Key evicted_keys 内存不足被淘汰的 key 总数
慢查询 slowlog 超过 slowlog-log-slower-than 的查询

8.2 内存碎片率参考

mem_fragmentation_ratio 状态 建议
≈ 1.0 ~ 1.2 健康 正常范围
1.2 ~ 1.5 轻度碎片 可观察,必要时重启
> 1.5 严重碎片 建议重启或使用 CONFIG SET activedefrag yes
< 1.0 异常 可能启用了交换分区,需检查内存

九、调用示例

9.1 Spring Boot 入口

package com.redis.monitor;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RedisMonitorApplication {
    public static void main(String[] args) {
        SpringApplication.run(RedisMonitorApplication.class, args);
    }
}

9.2 REST 控制器示例

@RestController
@RequestMapping("/redis/monitor")
public class RedisMonitorController {

    @Autowired
    private RedisMonitoringInfo redisMonitoringInfo;

    @Autowired
    private RedisMonitoring redisMonitoring;

    /** 监控面板概览 */
    @GetMapping("/overview")
    public Map<String, Object> overview() {
        return redisMonitoringInfo.getMonitoringInfo();
    }

    /** 动态图表数据 */
    @GetMapping("/dynamic")
    public Map<String, Object> dynamic(@RequestParam Integer qps,
                                       @RequestParam Integer time) {
        return redisMonitoring.getMonitoring(qps, time);
    }
}

9.3 测试代码

@Service
public class MonitorTestService {

    @Autowired
    private JedisUtil jedisUtil;

    public void testJedisUtil() {
        // 1. 获取完整 INFO
        String info = jedisUtil.getRedisInfo();
        System.out.println(info);

        // 2. 获取最近 10 条慢日志
        List<Slowlog> logs = jedisUtil.getLogs(10);
        for (Slowlog log : logs) {
            System.out.printf("ID: %d, 耗时: %d 微秒, 命令: %s%n",
                log.getId(), log.getTime(), log.getArgs());
        }

        // 3. 获取 Key 数量
        Long dbSize = jedisUtil.dbSize();
        System.out.println("当前数据库 Key 数量: " + dbSize);
    }
}

十、总结

本文从零搭建了一套完整的 Redis 实时监控系统,核心亮点:

  1. JedisPool 连接池 + Spring Boot 集成,生产可用
  2. INFO 参数完整中文翻译(120+ 参数),一目了然
  3. 慢日志查询 + 清空,帮助定位性能瓶颈
  4. 三层接口设计:概览面板、动态图表、全量指标查询
  5. 核心监控指标详解:内存碎片率、QPS、命中率等

适用场景:

  • Redis 运维监控面板开发
  • 自定义 Redis 监控告警系统
  • 学习 Redis INFO 命令各参数含义

扩展建议:

  • 集成 RedisReactive 实现响应式监控
  • 对接 Prometheus + Grafana 可视化
  • 增加告警阈值配置(内存超限、QPS 突降等)
  • 使用 RedisTimeSeries 模块存储时序监控数据
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐