1. 为什么我推荐用 Docker Compose 部署 Redis先说结论如果你还在手动apt install redis-server或者裸机编译安装遇到多环境部署、版本切换、配置同步这些场景时大概率会折腾到怀疑人生。我最早也是在虚拟机里直接装 Redis后来项目和环境一多光维护不同版本的配置文件和启动参数就花了不少时间switch 到 Docker 之后才真正体会到什么叫一次编排、到处运行。用 Docker Compose 装 Redis核心解决的是这几个问题环境一致性问题开发、测试、生产环境下的 Redis 镜像版本、系统依赖、目录结构完全一致避免我本地能跑到服务器就崩的惨剧。配置管理问题Redis 的启动参数、持久化策略、密码认证全部写进docker-compose.yml和独立的redis.conf中可以通过 Git 统一管理变更可追溯、可回滚。资源隔离问题Redis 跑在容器里CPU、内存、网络都受 Docker 管控不会因为系统里其他进程争抢资源导致 Redis 响应抖动。快速扩展问题后续如果想搭主从、哨兵或者集群只需要在 Compose 文件里增加几个 service一条docker compose up -d就能拉起整套架构比手动在几台机器上敲命令要靠谱得多。这篇博文你会拿到一套完整、可直接上生产环境的 Docker Compose 部署 Redis 方案包括配置文件的每一项参数怎么调、持久化怎么做、数据备份怎么搞以及我踩过的坑和排查思路。无论你之前有没有用过 Compose跟着操作都能顺畅跑起来。2. 动手前的准备环境检查与目录规划2.1 Docker 与 Compose 环境要求Docker Compose 目前有两个版本分支需要区分以免安装时报错或者执行命令时不兼容Docker Compose V1旧版命令是docker-compose通过 Python 安装逐步被官方淘汰。Docker Compose V2新版命令是docker compose中间有空格作为 Docker CLI 插件分发是目前官方主推的版本。我这边统一基于 V2 语法讲解。如果你的系统还在用旧版本建议直接升级到 V2因为 V2 不仅构建速度更快还支持include多文件合并等实用特性。部署前用下面三条命令快速自检# 查看 Docker 版本 docker --version # 查看 Compose 插件版本 docker compose version # 确认 Docker 引擎正常运行 docker info | grep -i server version如果输出正常说明基础环境没问题。注意docker info里能看到 Server Version 才是 Docker 守护进程正常工作的标志如果卡在这步先排查 Docker 服务是否已经启动。2.2 目录结构与文件规划我不太建议把 Redis 的配置文件一股脑塞进宿主机随机位置项目多了以后会变成一锅粥。我习惯按下面结构组织redis-deploy/ ├── docker-compose.yml ├── redis.conf ├── data/ # 存放 RDB 快照和 AOF 日志 ├── logs/ # 存放容器日志 └── scripts/ # 备份、停止等辅助脚本data目录和logs目录不用事先手动mkdirDocker 在挂载卷时如果宿主机目录不存在会自动创建但要注意目录的属主和权限。Redis 容器默认以redis用户运行UID 是999如果宿主机目录的权限不对容器启动后 Redis 可能报Cant chdir to /data或者Cant open the log file这类权限错误。稳妥的做法是创建目录后设置权限mkdir -p redis-deploy/data redis-deploy/logs chown -R 999:999 redis-deploy/data redis-deploy/logs这里用的是 Redis 官方镜像内部的redis用户 UID/GID999。如果你不清楚 UID可以进容器执行id redis查看不同镜像版本可能会有差异以实际输出为准。3. docker-compose.yml 编写思路每个配置项背后的考量3.1 基础服务定义先看完整的docker-compose.yml后面逐行拆解services: redis: image: redis:7.2-alpine container_name: redis-server restart: always ports: - 6379:6379 volumes: - ./redis.conf:/usr/local/etc/redis/redis.conf:ro - ./data:/data - ./logs:/logs command: [redis-server, /usr/local/etc/redis/redis.conf] environment: - TZAsia/Shanghai privileged: false逐个解释为什么要这么写image: redis:7.2-alpine选用 Alpine 版本是因为它基于 Alpine Linux 构建镜像体积小约 35MB 左右运行性能与标准版几乎无差异。选择 7.2 是因为该系列已经过社区充分验证稳定性和兼容性都表现稳定适合作为生产基准版本。restart: always这个参数决定了容器异常退出时是否自动拉起。Redis 作为缓存/数据库服务挂了如果没人及时察觉业务方会炸锅所以必须自动重启。顺带一提restart: always还有一层作用服务器重启后 Docker 引擎启动时会自动恢复该容器实现开机自启动的效果省去手动start的麻烦。ports: 6379:6379宿主机 6379 映射到容器 6379。如果宿主机已经有其他 Redis 实例占用端口需要改成类似16379:6379的形式避免冲突。volumes配置文件、数据目录、日志目录分别挂载出来。配置文件用了:ro只读防止容器内部误改配置造成漂移。command覆盖镜像默认的启动命令显式指定要加载的配置文件路径。这一步很关键如果不写Redis 会以默认配置启动你挂载的redis.conf不会生效。privileged: false不授予特权模式。这是安全基线即使容器被攻破攻击者也无法直接操作宿主机设备。3.2 网络配置要不要用宿主机模式很多人在 Redis 容器网络配置上有两个极端一是完全不配置直接走默认桥接网络二是图省事直接network_mode: host。我的建议是除非你对性能有极致要求且有专业压测数据支撑否则不要用host模式。原因有三host模式下端口无法再做映射Redis 直接暴露在宿主机网络中安全管控粒度变粗。多套 Redis 环境无法共存因为端口被宿主全局占用。Compose 网络别名、服务发现等特性全部失效不利于后续扩展主从和集群。正确做法是使用 Compose 默认创建的桥接网络并通过ports只暴露必需的端口。如果同一台机器上跑多个 Compose 项目而它们需要互相通信才需要额外定义共享网络networks: redis-network: driver: bridge services: redis: networks: - redis-network3.3 资源限制参数Redis 是内存型数据库最怕的就是容器里的进程把内存吃满导致整个宿主机 OOM。虽然 Docker 本身有 OOM 保护机制但最好显式加资源限制services: redis: deploy: resources: limits: memory: 2G reservations: memory: 512Mdeploy.resources语法在docker compose up下同样生效部分旧版本可能忽略 limit 之外的字段注意验证。另一个备选方案是在 service 级别加mem_limitCompose V2 兼容但deploy是跨 Swarm 和单机通用的标准写法建议优先掌握。我这里给 2G 是因为后面的maxmemory 1gb设置。资源限制的数值最好比 Redis 自身的maxmemory多留出 20%~30%因为 Redis 除了数据内存外复制积压缓冲区、客户端输出缓冲区、AOF 重写时的临时内存都要靠额外空间兜底。如果maxmemory设得比容器限制还高Redis 在内存不足时可能没等触发淘汰策略就被 OOM Killer 干掉了数据一致性就无从谈起。4. redis.conf 配置详解生产环境参数逐项拆解挂载配置文件是 Docker Compose 部署 Redis 的核心环节。下面是一份我经过多轮生产验证的基础配置直接复制后按需修改就能用# Redis 配置文件基于 7.2 版本验证 bind 0.0.0.0 protected-mode yes port 6379 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize no supervised no pidfile /var/run/redis_6379.pid loglevel notice logfile /logs/redis-server.log databases 16 always-show-logo no # 持久化配置 save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir /data # AOF 相关 appendonly yes appendfilename appendonly.aof appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # 安全认证 requirepass your-strong-password masterauth your-strong-password # 内存管理 maxmemory 1gb maxmemory-policy allkeys-lru maxmemory-samples 5 # 慢查询日志 slowlog-log-slower-than 10000 slowlog-max-len 1284.1 网络与访问控制bind 0.0.0.0配合protected-mode yes的组合要重点说下。很多教程直接教你bind 127.0.0.1说这样更安全——这在裸机部署时没错但容器化环境下有个细节容易被忽略容器内的网络空间和宿主机不是同一个lo接口。如果你在容器里只 bind 127.0.0.1那么从宿主机通过映射端口访问 Redis 时会因为连接来源 IP 不是回环地址而被拒绝。我这里的做法是 bind 0.0.0.0 让容器内所有接口都能监听然后依赖protected-mode yes来拦截无密码的外部访问。同时宿主机防火墙只放行信任 IP 到 6379 端口这样层层设防比单纯 bind 一个地址要稳得多。requirepass和masterauth是必配项。前者是客户端认证密码后者是主从复制时从节点连接主节点用的认证密码。即使你现在只有单机 Redis也建议把masterauth一并配上否则未来你加从节点或者搭建哨兵时漏配masterauth会导致从节点一直在尝试全量同步却始终失败日志里会反复刷MASTER - REPLICA sync started和Master down的报错。4.2 持久化策略RDB 与 AOF 的取舍Redis 的持久化有 RDB 和 AOF 两种方式二者不是二选一的关系而是互补关系。RDB 是内存快照周期性生成二进制文件恢复速度快但保存点之间如果进程崩溃会丢失最后一次快照之后的数据。上面的默认配置save 900 1意思是 900 秒内至少有 1 次写操作就触发一次快照save 300 10是 300 秒内 10 次写操作save 60 10000是 60 秒内 10000 次写操作。这是官方默认的节奏兼顾了性能和可靠性。AOF 是追加日志把每一条写命令记录下来粒度更小、丢失数据更少。appendfsync everysec表示每秒将缓冲区数据刷到磁盘最多只丢一秒的写操作是生产环境最常用的折中方案。我强烈建议两个都开着AOF 保证崩溃时的最小丢失RDB 保证重启时的快速加载。Redis 优先加载 AOF 文件来恢复数据因为 AOF 数据更完整如果 AOF 文件不存在或异常Redis 才会尝试加载 RDB。有个常被忽略的坑dir /data这个配置决定了 RDB 和 AOF 文件存放的目录。在容器环境里你必须把/data挂载到宿主机否则容器一删数据跟着就没了。很多新手把dbfilename和appendfilename配得明明白白却忘了配dir结果数据文件写进了容器可写层升级镜像或删除容器后全部丢失。这里写挂载卷的时候./data:/data正好与dir /data对应整个链路就闭环了。4.3 内存管理maxmemory 和 maxmemory-policymaxmemory 1gb这个参数必须根据业务情况设置。如果 Redis 只是作为缓存可以设置一个合理的上限配合allkeys-lru策略让 Redis 在内存满时自动淘汰最少使用的 key。allkeys-lru的意思是对所有 key 执行 LRU最近最少使用近似算法来淘汰数据。如果你的 Redis 里有些业务数据不想被淘汰应该使用volatile-lru它只淘汰设置了过期时间的 key而保留那些永久 key。判断标准很简单如果全部数据都可以接受淘汰用allkeys-lru如果有不可丢失的数据依赖 Redis 存储用volatile-lru或者干脆不启用淘汰让写操作报错。maxmemory-samples 5是 LRU 算法取样的数量。提高这个值会让淘汰结果更接近理论最优 LRU但也会增加 CPU 消耗。默认 5 已经能满足绝大多数场景不需要动。4.4 慢查询与日志参数slowlog-log-slower-than 10000表示执行时间超过 10000 微秒10 毫秒的命令会被记录到慢查询日志。注意这里不是日志文件而是 Redis 内部的一个内存队列通过SLOWLOG GET命令查看。slowlog-max-len 128控制队列长度超过后最早的记录会被挤出。logfile /logs/redis-server.log把容器日志写到挂载的logs目录方便统一采集分析。这里同样要注意权限Redis 容器内用户需要对该目录有写权限否则启动时会报日志文件打不开的错误。我踩过坑一开始直接挂载了一个普通用户创建的logs目录Redis 起来后日志一直没动静排查半天才发现是权限问题。5. 实战部署一条命令拉起整个服务栈5.1 创建并启动容器配置文件和目录都准备好之后启动就一条命令cd redis-deploy docker compose up -d-d表示后台运行。启动后立刻看下容器状态docker compose ps正常情况下输出里STATUS列应该是Up从启动到现在没有重启过。如果看到Restarting或者Exited说明容器正在崩溃重启循环需要立刻查看日志定位。查看运行日志docker compose logs --tail200 -f redis能正常看到 Redis 启动的 Banner包括版本号、监听端口、持久化状态等信息说明启动成功了。注意-f会持续跟踪输出查看完后按CtrlC退出不会影响容器运行。5.2 连接验证三种入口逐一测试验证 Redis 是否可用光看容器状态还不够必须实际读写数据验证链路。入口一容器内直连docker exec -it redis-server redis-cli -a your-strong-password进去后执行PING如果返回PONG说明容器内部 Redis 正常工作。执行完用QUIT退出。入口二从宿主机访问映射端口redis-cli -h 127.0.0.1 -p 6379 -a your-strong-password PING这条命令验证的是宿主机到容器的端口映射是否通畅。如果使用 Docker DesktopmacOS/Windows这里也可以写成localhost。入口三通过自定义网络的服务名访问如果其他容器要访问 Redis例如你的后端 API 容器也在同一个 Compose 网络里直接使用服务名redis作为主机名连接。这个能力是 Docker 内置 DNS 提供的不需要额外配置。只要两个容器在同一个 Compose 项目创建的默认网络中它们就能通过 service 名称互相通信。运行一个一次性容器来模拟docker run --rm -it --network redis-deploy_default \ redis:7.2-alpine redis-cli -h redis -p 6379 -a your-strong-password PING看到PONG即确认服务名解析和跨容器访问都正常。5.3 数据持久化验证启动完成后立刻验证持久化配置是否生效。写入几条测试 keydocker exec redis-server redis-cli -a your-strong-password SET test:key hello docker docker exec redis-server redis-cli -a your-strong-password SET test:key2 hello compose然后查看宿主机挂载目录下是否生成了持久化文件ls -la redis-deploy/data/正常情况下应该能看到dump.rdb和appendonly.aof两个文件。如果只有dump.rdb而appendonly.aof一直没有生成别慌AOF 文件可能在 rewrite 之前不会主动落盘到磁盘需要确认appendonly yes配置是否真的被加载了执行redis-cli CONFIG GET appendonly查看运行时实际值。接着模拟容器删除再重新创建验证数据是否还在docker compose down docker compose up -d docker exec redis-server redis-cli -a your-strong-password GET test:key如果返回hello docker说明 RDB 或 AOF 恢复了数据整个持久化链路是通的。这一步务必做一次否则后续如果数据丢了才发现在出事前根本没验证过备份恢复就非常被动了。5.4 配置项生效验证很多人配置文件挂载了但运行时根本不生效这个问题非常隐蔽。因为 Redis 默认配置和你的配置差异可能很小而有些参数你不主动检查根本发现不了。我从一开始就习惯直接把运行时配置导出来对比docker exec redis-server redis-cli -a your-strong-password CONFIG GET maxmemory docker exec redis-server redis-cli -a your-strong-password CONFIG GET maxmemory-policy docker exec redis-server redis-cli -a your-strong-password CONFIG GET appendonly docker exec redis-server redis-cli -a your-strong-password CONFIG GET save也可以用一条命令拿到所有关心的项docker exec redis-server redis-cli -a your-strong-password CONFIG GET maxmemory*如果输出的值和你配置文件里写的不一致大概率是命令参数没有指定配置文件路径或者文件权限导致 Redis 拒绝加载。重新检查command的写法确保 redis.conf 路径正确。6. Redis 运维操作与端口映射注意点6.1 停止与删除容器docker compose down是停止并删除 Compose 项目里的全部容器和网络但不会删除挂载卷所以数据还在宿主机目录里。如果需要连同匿名卷一起清理要加-v参数但这里我们用的是绑定挂载down -v也不会删除./data目录下的文件这只是针对匿名卷。停止容器但保留容器可以用docker compose stop之后再启动docker compose start6.2 如何安全清空 Redis 数据如果业务上要清空 Redis 缓存优先用命令而不是直接删文件docker exec redis-server redis-cli -a your-strong-password FLUSHALL执行FLUSHALL后RDB 文件会被标记为需要重写AOF 文件也会记录截断操作。为了确保磁盘空间立刻释放可以手动触发一次持久化docker exec redis-server redis-cli -a your-strong-password BGSAVE注意BGSAVE是异步操作返回Background saving started表示已经触发。要等它完成可以看日志里的Background saving terminated或者用LASTSAVE命令检查时间戳是否更新。6.3 端口映射的坑生产环境里Redis 端口映射有个非常经典的问题云服务器安全组没放行端口。你在本机telnet 127.0.0.1 6379一切正常但其他机器连不上第一反应往往怀疑容器配置实际上八成是安全组策略拦了。排查顺序应该是宿主机本机连接是否正常验证容器层。同内网其他机器连接是否正常验证宿主机防火墙。跨公网连接验证云安全组和路由。检查 Redis 是否处于protected-mode它会在没有密码且监听所有接口时拒绝非回环地址的连接。这个排查顺序能帮你快速缩小问题范围省得在一个层面反复找茬。7. 安全加固Redis 暴露在公网前的底线操作7.1 为什么 Redis 绝对不能用默认配置裸奔Redis 的设计初衷是高可用的快速存取没有把安全作为第一优先级。默认配置下 Redis 不启用认证如果直接部署在公网互联网扫描工具几分钟内就能发现你的 6379 端口并尝试未授权访问。攻击者一旦进去除了读写你的缓存数据还可能利用 Redis 写文件功能获取服务器权限这类攻击在业内已经不是新闻了。所以容器化部署 Redis安全基线工作不能省。基础的几件事按顺序做完能挡住 99% 的扫描流量。7.2 必须做的五项安全操作第一强密码认证。密码不要用redis123这种弱口令建议用至少 16 位的随机字符串可以这样生成openssl rand -base64 24第二限制监听地址。如果 Redis 只给几个内网应用使用可以考虑不映射 6379 端口到宿主机让 Redis 只在 Compose 内网可访问。要实现这个效果直接把docker-compose.yml里的ports段删掉即可。这样宿主机所有接口上都没有 6379 端口对外暴露安全性最高。第三宿主机防火墙管控。如果你确实需要从宿主机外部访问 Redis用ufw或者iptables限制来源 IPufw allow from 192.168.1.0/24 to any port 6379 proto tcp第四容器不特权运行。docker-compose.yml 里已经设置了privileged: false另外可以加一层read_only: true把容器根文件系统设为只读防止攻击者写文件。但要注意Redis 运行需要写/data所以read_only配合/data挂载卷一起用才能两全其美services: redis: read_only: true volumes: - ./data:/data - ./logs:/logs第五关闭危险命令。有些 Redis 命令如CONFIG、EVAL、KEYS在生产环境容易被滥用或误操作可以通过rename-command把它们禁用或重命名rename-command CONFIG rename-command EVAL rename-command KEYS CONFIG和EVAL直接禁掉KEYS在生产环境也应该禁掉因为KEYS *在键数量多时会阻塞 Redis 主线程几秒甚至更久让整个服务卡死。排查问题需要扫描 key 时应该用SCAN命令替代。7.3 数据备份与恢复容器化部署下Redis 的数据备份不是直接备份容器而是备份挂载目录下的持久化文件。最简单可靠的方式是用宿主机 cron 定期把data目录打包#!/bin/bash # 保存路径 BACKUP_DIR/backup/redis DATA_DIR/opt/redis-deploy/data STAMP$(date %Y%m%d%H%M%S) mkdir -p $BACKUP_DIR cp $DATA_DIR/dump.rdb $BACKUP_DIR/dump-$STAMP.rdb cp $DATA_DIR/appendonly.aof $BACKUP_DIR/appendonly-$STAMP.aof # 保留最近 7 天的备份 find $BACKUP_DIR -name *.rdb -mtime 7 -delete find $BACKUP_DIR -name *.aof -mtime 7 -delete恢复时把备份文件拷贝回data目录然后重启容器cp /backup/redis/dump-20240101120000.rdb /opt/redis-deploy/data/dump.rdb cd /opt/redis-deploy docker compose restart注意恢复前最好先清空现有数据否则旧 key 可能与备份数据混合。最安全的做法是先docker compose down替换文件后再docker compose up -d。8. 常见问题与排查技巧实录8.1 容器启动后反复重启典型现象docker compose ps里看到 STATUS 为Restarting然后查询日志看到类似Fatal error loading the DB: Permission denied或者Cant open the log file: Permission denied。这是我遇到最多的启动失败原因十有八九是数据目录或日志目录的权限不对。我上面说过chown -R 999:999是解决手段但更根本的做法是理解容器用户的权限模型。Redis 官方镜像里用户是redisUID999所以宿主机挂载目录的属主要有写权限否则 Redis 无法创建和写入 RDB/AOF 文件。还有个隐蔽情况你改了宿主机目录权限但容器是之前启动的进程里已经缓存了错误的文件句柄状态。此时应该重启容器而不是只改权限docker compose down chown -R 999:999 data logs docker compose up -d8.2 配置不生效问题典型现象CONFIG GET maxmemory拿到的值和你redis.conf里写的不一样。第一次我遇到这个情况时整个人都懵了配置文件明明挂载了路径也对为什么参数不生效后来发现是command段把配置文件路径写错了Redis 启动时没找到配置文件就用默认配置跑起来了而默认配置里的参数当然和你想的不一样。排查方法很直接看启动日志docker compose logs redis | head -50正常配置加载时会打印类似这样的行Configuration loaded如果日志里这句之后紧跟着一个Warning: no config file specified, using the default config.说明配置文件没被正确加载。检查command里的路径是否与volumes里的容器内路径完全一致。8.3 内存被占满但数据没有按预期淘汰典型现象写入业务 key 时提示OOM command not allowed when used memory maxmemory但明明设置了maxmemory-policy allkeys-lru。这个问题出现的原因主要有两个第一触发条件未满足。Redis 的 LRU 淘汰只在内存达到maxmemory后才会触发如果内存还没到上限Redis 不会主动删任何 key这是正常行为。但如果你期望的内存快占满时自动清理没有发生前提条件就是内存没到阈值。第二某些场景下淘汰策略被绕过。例如大量使用了未设置过期时间的 key且策略是volatile-lru它们永远不会被淘汰内存就会持续上涨直到触顶报错。正确的排查路径是看INFO memory输出的关键指标used_memory和maxmemory的对比以及evicted_keys是否在增长。如果evicted_keys一直是 0说明淘汰策略压根没触发要考虑策略是否适合你的数据形态。8.4 客户端连接数过多导致拒绝服务典型现象业务侧出现Cannot assign requested addressRedis 日志里出现ERR max number of clients reached。Linux 和 Redis 各有一层连接数限制。Linux 层要调整文件描述符限制容器内进程默认可能受系统ulimit影响。Redis 层通过maxclients控制默认是 10000。如果业务确实需要更高的连接数在redis.conf里调大maxclients 20000同时要确认宿主机层面的ulimit满足要求ulimit -n如果这个值是 1024而maxclients配置了 10000那等于 Redis 往 10000 个连接去争取但文件描述符层先卡死了。需要同步调大系统限制在/etc/security/limits.conf里设置合适的值。在容器里还要注意ulimit继承自 Docker 守护进程必要时在 Docker 守护进程配置里调整默认值。8.5 主从同步一直失败典型现象从节点日志反复出现MASTER - REPLICA sync started和Master did not respond to PING。这个场景我在部署哨兵时踩过。排查重点有三第一认证配置。主节点开了requirepass从节点必须配置masterauth才能通过认证。很多人配了requirepass却漏了masterauth导致同步握手失败。第二网络连通。Compose 网络下从节点访问主节点要用服务名而不是宿主机 IP因为容器网络和宿主机网络不互通。如果从节点里配置主节点地址是127.0.0.1它连的是自己的容器回环地址永远连不上主节点。第三防火墙拦截。如果主从节点跨宿主机宿主机间要放行 6379 端口同时 Redis 配置文件里的bind 0.0.0.0必须保证主节点能从外部访问。8.6 慢查询问题的定位思路排查 Redis 性能问题时的第一步永远是看慢日志而不是猜。用SLOWLOG GET 20拉出最近 20 条慢命令重点看那些耗时的 key 属于哪些业务。我遇到过的典型案例是一个在列表里做全量遍历的HGETALL数据量从几千涨到几万后单次执行时间飙到几十毫秒直接拖慢了所有同实例上的业务。慢查询问题解决方向一般是优化数据结构、分批处理、或者把大 key 拆分。万不得已不推荐用KEYS命令去定位问题因为它的阻塞副作用会让情况更糟。用SCAN命令迭代扫描配合DEBUG OBJECT key查看大 key 的编码方式就能在线上定位到具体的异常数据。9. 进阶操作与性能调优建议9.1 调整内存分配策略在容器环境里由于内存受到 CGroup 限制Redis 的maxmemory与前文提到的deploy.resources.limits.memory配合至关重要。如果你设置了容器内存限制为 2G又给 Redis 配了maxmemory 2g那么 Redis 将无法在内存紧张时优雅地自行淘汰而是可能被系统 OOM Killer 杀死。正确的做法是让maxmemory略小于容器内存限制留出 15%~20% 的余量给复制缓冲区和 AOF 重写。比如容器限制 2Gmaxmemory设置 1536mb 或者 1.5g。这个余量不是拍脑袋定的Linux 下 Redis 的持久化相关缓冲区最大默认值是 256MB复制积压缓冲区再加上客户端输出缓冲和系统其他开销保守留出 20% 是合理的。9.2 CPU 绑定与性能提升空间对于延迟极度敏感的场景可以把 Redis 容器绑定到指定 CPU 核services: redis: cpu_quota: 50000 cpuset: 0,1cpuset把容器限制在两个 CPU 核上避免 CPU 上下文切换带来的性能抖动。cpu_quota限制相对 CPU 时间单位微秒50000 表示在每 100000 微秒周期内最多用 50000 微秒即 50% 的单核配额。这些都是单机部署层面的优化要更大程度提升性能建议把主从复制、哨兵模式铺开把读流量分散到多个从节点。这部分内容展开又是另外一篇长文今天先不做深入。9.3 日志轮转容器日志如果不做轮转时间久了会占满宿主机磁盘。Docker 配置文件/etc/docker/daemon.json里可以统一设置日志驱动参数{ log-driver: json-file, log-opts: { max-size: 50m, max-file: 3 } }修改后重启 Docker 守护进程sudo systemctl restart docker这个参数只对重启后新建的容器生效已有容器不受影响。如果你有已经运行很久的容器需要 recreate 才会用上新策略。max-size是单个日志文件最大 50MBmax-file是保留最多 3 个文件超过后最老的会被清理。10. 我对 Docker Compose 部署 Redis 的几点体会用 Docker Compose 跑 Redis 已经有段时间了最大的感受是这套方案的价值不在于省掉几条安装命令而是把 Redis 的整个生命周期部署、配置、扩展、备份、恢复都纳入了代码化管理的轨道。之前裸机安装时配置漂移、版本不统一这些问题是长期存在的隐患换到 Compose 之后一份docker-compose.yml加一份redis.conf就能在任何机器上复现一模一样的环境这种可预期性是运维体验的质变。一个小建议是生产环境的 Compose 编排最好把常用操作封装成脚本放进项目里比如备份脚本、重启脚本、状态检查脚本别依赖人脑记忆命令。状态检查脚本可以顺手把持久化文件大小变化、容器重启次数、慢日志条数这几个关键指标放在一起输出每次巡检一目了然。最后再说一个细节每次修改redis.conf后不要直接docker compose restart先检查配置文件语法docker run --rm -v $(pwd)/redis.conf:/usr/local/etc/redis/redis.conf:ro \ redis:7.2-alpine redis-server /usr/local/etc/redis/redis.conf --test-memory 64--test-memory会测试内存分配是否正常如果配置有错误Redis 会在启动阶段直接报错退出。这个前置检查看起来多了一步但能防止你把一个语法有问题的配置推进生产环境后整个服务因配置错误而短暂不可用。我自己因为跳过这步栽过一次之后就把这条规则定死了。