跳转至

Docker Compose 部署与日常排障

先在本机部署一个隔离的学习实例,练习写入、过期、重启和恢复,再读高可用。这里的实例只绑定宿主机回环地址,使用独立目录与卷;它不代表已具备生产高可用。

文件放在哪里

redis-lab/
├── compose.yaml
└── redis.conf

Docker named volume → 容器 /data:RDB、AOF 等数据

compose.yaml

name: redis-learning
services:
  redis:
    image: redis:7.2
    restart: unless-stopped
    command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
    ports:
      - "127.0.0.1:16379:6379"
    volumes:
      - ./redis.conf:/usr/local/etc/redis/redis.conf:ro
      - redis-data:/data
    mem_limit: 1g
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3
volumes:
  redis-data:

redis:7.2 是功能演示用版本系列,并非固定不可变制品。正式环境选受维护、验证过的补丁版本并固定 digest。示例假设较新的 Docker Compose 插件支持这些字段。

redis.conf

bind 0.0.0.0
protected-mode yes
port 6379
daemonize no
dir /data
dbfilename dump.rdb
save 900 1
appendonly yes
appendfsync everysec
maxmemory 512mb
maxmemory-policy allkeys-lru
logfile ""

容器内部需要监听网络接口,宿主机发布端口则限制为 127.0.0.1:16379,避免与现有 6379 冲突。此实验未配置密码,不要改成公网绑定;同一 Docker 网络中的容器仍可能访问它。正式环境再按业务配置 ACL、网络边界和需要的加密连接。

1 GiB 容器、512 MiB maxmemory 为学习预算,后台重写与高写入时仍需观察峰值。allkeys-lru 适合此处缓存练习,不适合直接复制到重要任务或会话实例。

启动并确认

在上面的 redis-lab 目录执行:

docker compose config
docker compose up -d
docker compose ps
docker compose logs --tail=100 redis
docker compose exec redis redis-cli PING
docker compose exec redis redis-cli INFO server
docker compose exec redis redis-cli CONFIG GET maxmemory
docker compose exec redis redis-cli CONFIG GET maxmemory-policy

PING 返回 PONG 说明可以执行简单命令,再确认版本和有效配置。健康检查显示 unhealthy 不代表 Docker 一定自动重启该容器;这里的重启策略主要处理进程退出等情况。

进入交互命令行后练习前几页:

docker compose exec redis redis-cli

修改 redis.conf 后,在实验环境重启服务再核对生效值。CONFIG SET 属于运行时修改,不一定持久保存;本例配置文件只读,不能依靠 CONFIG REWRITE 回写,应该修改受管理的文件。

做一次重启实验

先写入一个测试 key,不设置 TTL,避免把过期与恢复混淆:

docker compose exec redis redis-cli SET learn:restart-check hello
docker compose exec redis redis-cli INFO persistence
docker compose restart redis
docker compose exec redis redis-cli GET learn:restart-check

预期返回 hello。这个实验验证正常重启与持久目录连接,不证明断电时零丢失,也不证明备份可以恢复。确认结果后可删除这一个实验 key。数据卷应保留;带 -v 的删除操作会同时删除卷,练习时不要误用。

六个日常检查入口

INFO memory
INFO stats
INFO clients
INFO persistence
INFO replication
SLOWLOG GET 10
位置 看什么 对应的问题
memory 已用内存、RSS、maxmemory、碎片 是否接近上限、实际内存是否明显超过数据量
stats 命中/未命中、expired_keys、evicted_keys 是 TTL 到期还是被淘汰,缓存是否有效
clients 连接、阻塞客户端 连接池是否失控;阻塞读客户端是否符合业务预期
persistence RDB/AOF 最近状态、后台任务 磁盘写入失败或重写是否异常
replication 角色、连接和复制进度 主从是否按预期连接、是否落后
slowlog 高耗时命令及参数线索 大 key、全量查询或 Lua 是否拖慢命令执行

SLOWLOG 主要衡量服务端命令执行耗时,不包含完整的网络等待和客户端排队。因此应用很慢而慢日志为空时,还要查网络、连接池、DNS、TLS、CPU 调度以及输出缓冲。相关机制见官方延迟排查

遍历 key 时别一次拿全库

SCAN 0 MATCH learn:* COUNT 100

返回结果包含新游标和一批 key,下一次使用新游标,直到返回 0。COUNT 是工作量提示,不保证返回恰好 100 条;一次可能没有匹配 key,遍历也可能重复,不能把它当成固定时间点快照。

KEYS * 会集中遍历全库,大实例上容易阻塞。redis-cli --bigkeys 会扫描并统计不同类型的较大 key,也需要评估负载,成员最多不一定字节数最大。先缩小排查范围,再结合 MEMORY USAGEHLENLLENSCARD 等检查具体 key。

故障发生时从哪里查

现象 排查顺序
连接不上 进程与日志 → 发布端口 → 网络/防火墙 → ACL、密码、TLS
NOAUTH / WRONGPASS / NOPERM 分别检查是否认证、凭据/用户状态、命令与 key 权限
WRONGTYPE 用 TYPE 检查数据类型,确认 key 命名是否冲突
OOM command not allowed... maxmemory、淘汰策略、是否缺少可淘汰候选;不等于进程已被内核杀死
容器 OOMKilled 容器上限、RSS、重写峰值、缓冲和主机内存
MISCONF 写入失败 查看持久化错误、磁盘容量/权限,不先关闭保护来掩盖原因
大量缓存未命中 重启冷缓存、TTL、淘汰、应用 key 或序列化规则变化
延迟突然升高 慢日志、大 key、重写/fork、CPU、网络、磁盘和客户端连接池
接口偶发超时 对齐应用与 Redis 时间线,注意写命令超时后结果可能未知

对结果未知的写操作,不应盲目无限重试。例如 INCR 重试可能多加一次,需要业务幂等或对账。MONITOR 会输出实时命令并增加负载,也可能暴露业务数据,不能当作长期默认监控。

接到一个生产 Redis,先确认什么

确认用途是缓存还是重要状态、单机还是 Sentinel/Cluster、应用连接方式、版本、内存上限、淘汰策略、持久化目录、备份恢复记录。再看连接池、超时和告警能否覆盖业务故障。

应用使用专门的 ACL 用户,限制命令及 key 范围;运维账号与业务账号分开。不要用多个逻辑数据库当成强隔离,也不要向公网直接开放 Redis。

上线后可以通过 Redis Exporter 等采集方式接入现有指标平台,重点跟踪延迟、错误、内存、淘汰、连接、持久化和复制状态。告警阈值按容量和业务基线设置,避免只告警进程是否活着。

下一步:主节点故障后如何接管