redis探针主要是监控redis相关情况,比如内存,连接数等。

原理

1、set log format,支持txt和json两种格式的日志

2、set log level,支持正常的日志级别

3、show version 支持option打印版本

4、解析addr和passwd和alias,这几个参数支持参数配置,也可以重环境变量中获取

Environment         Variables
Name                Description
REDIS_ADDR          Address of Redis node(s)
REDIS_PASSWORD      Password to use when authenticating to Redis
REDIS_ALIAS         Alias name of Redis node(s)
REDIS_FILE          Path to file containing Redis node(s)

5、创建一个Exporter结构体,初始化,将上面的信息传进去,并创建对应的指标,checkkey支持对多数据库的查询

// Exporter implements the prometheus.Exporter interface, and exports Redis metrics.
type Exporter struct {
    redis        RedisHost
    namespace    string
    keys         []dbKeyPair
    keyValues    *prometheus.GaugeVec
    keySizes     *prometheus.GaugeVec
    duration     prometheus.Gauge
    scrapeErrors prometheus.Gauge
    totalScrapes prometheus.Counter
    metrics      map[string]*prometheus.GaugeVec
    metricsMtx   sync.RWMutex
    sync.RWMutex
}


// RedisHost represents a set of Redis Hosts to health check.
type RedisHost struct {
    Addrs     []string
    Passwords []string
    Aliases   []string
}

6、然后调用client_golang的库函数进行数据采集,scrape连接数据库,调用命令,然后解析返回参数。完成监控。

由此可见,redis_exporter只是简单的对redis的单节点进行了监控,并没有对redis的cluster和sentinel进行监控。

sentinel监控

这边需要监控sentinel,这边做一个设计

  • 运行天数

    redis_start_time_seconds{addr="10.37.152.206:26379",alias=""} 1.551058403e+09
    

    这个指标直接解析info信息中的sentinel信息,每次通过执行info命令获取,获取uptime_in_days字段值,设计标签为通用的addr,alias字段。

  • 注册shard数据

    redis_sentinel_masters{addr="10.37.152.206:26379",alias=""} 4
    

    这个指标直接解析info信息中的sentinel信息,每次通过执行info命令获取,获取sentinel_masters字段值,设计标签为通用的addr,alias字段。

  • 正常shard的个数

    redis_sentinel_masters_ok{addr="10.37.152.206:26379",alias=""} 0
    

    这个指标直接解析info信息中的sentinel信息,每次通过执行info命令获取,获取status=ok的个数,设计标签为通用的addr,alias字段。

  • 异常shard的个数

    redis_sentinel_masters_down{addr="10.37.152.206:26379",alias=""} 4
    

    这个指标直接解析info信息中的sentinel信息,每次通过执行info命令获取,获取status=odown的个数,设计标签为通用的addr,alias字段。

  • sentinel的连接数

    redis_sentinel_connects{addr="10.37.152.206:26379",alias=""} 0
    

    这个指标是通过执行netstat命令来统计对应进程的连接数,设计标签为通用的addr,alias字段。

  • 检活

    redis_sentinel_status{addr="10.37.152.206:26379",alias=""} 1
    

    这个指标是通过执行redis PING命令来检测返回的是否是PONG,如果是则为1,否则为0,代表着sentinel的死活状态,设计标签为通用的addr,alias字段。

  • 26379端口检测

    redis_sentinel_port_isalive{addr="10.37.152.206:26379",alias=""} 0
    

    这个指标是通过执行netstat命令来统计对应端口为LiSTEN的数量,1代表端口正在监听,0代表没有监听端口,设计标签为通用的addr,alias字段。

目前探针融合在redis的探针中,可以自动识别sentinel还是redis,然后放回对应的指标,支持多地址混合配置,可以返回所有需要的指标。

连接池

redis探针短连接到长连接池改造

目前方案就是改短连接为长连接,可以只使用一个连接来解决这个问题,这个其实适用于长连接使用的场景,然后考虑长连接可能出来大量连接存在的场景,所以最好直接使用连接池,对连接的数量进行限制,这样就可以完美的解决问题。

探针启动直接初始化一个连接池,大小为2,正常使用一个长连接来采集高频率的数据,出现异常,可能会使用到第二个长连接。

验证在高频率的采集下连接数并没有出现增长。

问题

redis自身支持长连接需要设置参数,tcp_keepalive=1,默认是关闭的,所以都是以timeout时间为准,到时间后redis端会关闭连接,所以探针侧就会close_wait,当然这个连接是可以复用的,当重新请求的时候,又会建立连接在连接池上,按着我们每10s才是一次的频率,redis设置的180s的超时时间,基本上不会出现不断短连接的情形。

redis多活复制监控设计

Label设计

  1. 直接获取info信息中的# Remote_replication段里的remote_role:source的值,代表着当前redis的角色。
  2. 直接获取info信息中的# Remote_replication段里的source_host:10.244.176.44的值,代表着当前目的端的元ip地址
  3. 直接获取info信息中的# Remote_replication段里的dest_host:10.244.176.46的值,代表着当前源端对应的目的端ip地址
  4. 直接获取info信息中的# Remote_replication段里的source_link_status:up的值,代表着当前目的端对应复制状态

因为这些对应的是string类型的value,直接作为源端或者目的端的label使用,通过返回值可以增加以下label

source

# Remote_replication
remote_role:source
dest_host:10.244.176.46
dest_port:57093
dest_state:online
dest_last_io_seconds_ago:1
dest_client_buffer_len:0
source_repl_offset:2449159

label:remote_role,dest_host,dest_port,dest_state

dest

# Remote_replication
remote_role:dest
source_host:10.244.176.44
source_port:6379
source_link_status:up
source_last_io_seconds_ago:0
source_sync_in_progress:0
dest_repl_offset:151922

label:remote_role,source_host,source_port,source_link_status

源端指标

  • source端向dest端发送增量数据的缓冲区大小,堆积量增大预示网络延迟或tps过大

    直接获取info信息中的# Remote_replication段里的dest_client_buffer_len:0的值,代表着当前源端source端向dest端发送增量数据的缓冲区大小,堆积量增大预示网络延迟或tps过大

    指标:如下

    设计设计标签为通用的addr,alias字段,加上指标字段remote_role,dest_host,dest_port,dest_state

  • source端和dest端的offset的差值

    直接获取info信息中的# Remote_replication段里的source_repl_offset:149103的值,代表着当前源端offset的值

    指标:如下

    设计设计标签为通用的addr,alias字段。加上指标字段remote_role,dest_host,dest_port,dest_state

    通过聚合计算出它们的差值。

  • 缓存写、删除操作的总共次数

    直接获取info信息中的# Remote_replication段里的server_total_changes:0的值,代表着当前源端或者目的端缓存写、删除操作的总共次数

    指标:如下

    设计设计标签为通用的addr,alias字段。

    展示上一次数据和这一次数据的差值。通过函数计算获得。

目的端指标

  • dest端最后一次和source端通信后过去的时长,单位秒

    直接获取info信息中的# Remote_replication段里的dest_client_buffer_len:0的值,代表着当前目的端dest端最后一次和source端通信后过去的时长,单位秒

    指标:如下

    设计设计标签为通用的addr,alias字段。加上指标字段remote_role,source_host,source_port,source_link_status

  • source端和dest端的offset的差值

    直接获取info信息中的# Remote_replication段里的dest_repl_offset:151922的值,代表着当前目的端offset的值

    指标:如下

    设计设计标签为通用的addr,alias字段。加上指标字段remote_role,source_host,source_port,source_link_status

    通过聚合计算出它们的差值。

  • 缓存写、删除操作的总共次数

    直接获取info信息中的# Remote_replication段里的server_total_changes:0的值,代表着当前源端或者目的端缓存写、删除操作的总共次数

    指标:如下

    设计设计标签为通用的addr,alias字段。

    展示上一次数据和这一次数据的差值。通过函数计算获得。

验证

正常情况下都是一个节点一个角色,这边放在一起了。

获取指标如下:

# HELP redis_remote_replication_dest_client_buffer_len remote replication dest client buffer len
# TYPE redis_remote_replication_dest_client_buffer_len gauge
redis_remote_replication_dest_client_buffer_len{addr="10.244.176.44:6379",alias="",dest_host="10.244.176.46",dest_port="57093",dest_state="online",remote_role="source"} 0
# HELP redis_remote_replication_dest_last_io_seconds_ago remote replication dest last io seconds ago
# TYPE redis_remote_replication_dest_last_io_seconds_ago gauge
redis_remote_replication_dest_last_io_seconds_ago{addr="10.244.176.44:6379",alias="",dest_host="10.244.176.46",dest_port="57093",dest_state="online",remote_role="source"} 0
# HELP redis_remote_replication_dest_repl_offset remote replication dest repl offset
# TYPE redis_remote_replication_dest_repl_offset gauge
redis_remote_replication_dest_repl_offset{addr="10.244.176.46:6379",alias="",remote_role="dest",source_host="10.244.176.44",source_link_status="up",source_port="6379"} 7.541993e+06
# HELP redis_remote_replication_source_last_io_seconds_ago remote replication source last io seconds ago
# TYPE redis_remote_replication_source_last_io_seconds_ago gauge
redis_remote_replication_source_last_io_seconds_ago{addr="10.244.176.46:6379",alias="",remote_role="dest",source_host="10.244.176.44",source_link_status="up",source_port="6379"} 0
# HELP redis_remote_replication_source_repl_offset remote replication source repl offset
# TYPE redis_remote_replication_source_repl_offset gauge
redis_remote_replication_source_repl_offset{addr="10.244.176.44:6379",alias="",dest_host="10.244.176.46",dest_port="57093",dest_state="online",remote_role="source"} 7.541994e+06
# HELP redis_remote_replication_source_sync_in_progress remote replication source sync in progress
# TYPE redis_remote_replication_source_sync_in_progress gauge
redis_remote_replication_source_sync_in_progress{addr="10.244.176.46:6379",alias="",remote_role="dest",source_host="10.244.176.44",source_link_status="up",source_port="6379"} 0

指标的聚合使用