ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Docker部署Redis全攻略:镜像、持久化与主从复制避坑实录

Docker部署Redis全攻略:镜像、持久化与主从复制避坑实录 去年年底线上 Redis 实例告警频繁我们干脆把整套缓存中间件迁到了 Docker 容器里统一管理。当时想着只是换一种部署方式而已结果真动手才发现——同样一个 Redis裸机装和容器里跑完全是两回事镜像标签怎么选、配置文件怎么挂载、持久化怎么落盘、主从怎么组网每一步都有坑。这篇文章我不讲官方文档里那种流水账式步骤只分享自己从 Docker 安装 Redis 一路摸过来的实操经验和踩坑实录。无论你是刚接触 Docker 的新手还是已经在生产环境维护 Redis 的老手都能找到可直接照抄的方案。刚开始接触这个组合的人最常见的问题是Redis 不是一条命令就能装吗为什么还要用 Docker 包一层等我逐步展开后就明白了。但在动手之前最好先理解容器化和裸机的底层差异这决定了你后面所有操作的正确性。1. 为什么我最终选择用 Docker 跑 Redis几条无法拒绝的理由很多人在学 Redis 的时候习惯直接在 Windows 或 Linux 上装一个原生版本。这种方式对学习很友好但一进入团队协作或多环境部署麻烦就来了你的机器上是 5.0同事那边是 6.2测试环境又变成 7.0版本不一致导致的主从复制协议差异、RDB 文件兼容性问题会在某个深夜毫无预兆地爆发。容器化的核心价值不是装得快而是环境一致性。镜像里带着 Redis 二进制、系统依赖、基础配置一起打包开发、测试、生产三套环境用的是同一个镜像从源头上消灭了版本漂移。1.1 Docker 方式相比裸机安装的三大优势第一部署效率有质的提升。以前我在 CentOS 上编译安装 Redis 源码要装 GCC、要 make、要配置 systemd 服务一套下来半小时起步。用 Docker 就一条docker pull加docker run五分钟不到就能把带密码、带持久化、带日志配置的完整实例拉起来。第二环境隔离做得更彻底。Redis 本身没有虚拟化能力裸机部署时它的文件、端口、配置和系统里其他服务共享同一份资源空间。容器则把 Redis 圈在独立的文件系统和网络命名空间里我可以在同一台机器上用不同端口和不同数据目录跑多套互不干扰的 Redis 实例这在中间件多环境共享服务器时特别有用。第三弹性扩展和回收非常轻松。集群要扩容docker run一个新容器挂到集群里就行要缩容把所有副本指向切走直接docker rm把这个容器删了不会像裸机那样残留一堆配置文件和服务注册信息。1.2 先搞懂镜像标签RELEASE 版本为什么比 latest 更安全第一次拉 Redis 镜像的人十有八九会直接docker pull redis拿到的是 latest 标签。这是更新最频繁的滚动版本但恰恰不适合生产环境。问题在于 two points一是 latest 没法保证确定性今天拉和明年拉可能得到完全不同的版本出问题之后想复现现场都难二是 Redis 大版本之间比如 6.x 升级到 7.x很多行为发生了变化比如 ACL 机制的大改、多线程 I/O 的引入盲目跟着 latest 走意味着随时可能被不兼容变更波及。我的习惯是锁定具体的小版本。比如redis:7.0.12-alpine既锁定了主版本又锁定了补丁版本还锁定了基础镜像为 alpine。这里的 alpine 很有讲究基础镜像体积从 Debian 版的 100MB 左右直接缩到 30MB 左右对磁盘和镜像仓库传输都是实打实的优化。如果遇到需要 gdb 调试或者必须用 glibc 的场景再用redis:7.0.12-bookworm这类标准镜像平时跑业务 alpine 足够。提示镜像版本的选择直接决定了你后续踩不踩坑。确认拉取版本前先到 Docker Hub 上redis官方仓库看 Tags 列表把 digest摘要值也记下来方便日后做供应链追踪。严格说Docker 安装 Redis 的难度不在跑起来而在跑得稳。接下来我把每一步的细节拆开讲照着做就能少走弯路。2. 从零开始Docker 安装 Redis 的标准操作流程先把准备工作说清楚。宿主机器如果有 Docker可以直接跳到 2.2 节如果没有先装好 Docker 引擎。Windows 用户建议直接用 WSL 2 后端配合 Docker Desktop记得在 BIOS 里把虚拟化VT-x/AMD-V打开否则 Docker Desktop 经常报 virtualization support not detected具体处理方式我在第五部分展开。2.1 准备环境Windows 和 Linux 下的差异其实比想象中大Linux 服务器我这里以 Ubuntu 22.04 为例安装 Docker 比较顺官方提供了一键脚本但更推荐手动添加仓库安装方便后续锁定版本# 添加 Docker 官方 GPG key 和仓库 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 安装 Docker 引擎和 compose 插件 sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-pluginWindows 上的 Docker Desktop 本质上还是靠 WSL 2 里的 Linux 内核来跑容器因此 WSL 内核版本太老也会引发一堆莫名其妙的问题。装上 Docker Desktop 后先别急着拉镜像去 PowerShell 跑一下wsl --update把内核升级到最新的稳定版能提前规避很多玄学故障。装好 Docker 后验证一下是否就绪docker version docker compose version如果docker version显示 Client 和 Server 两段信息都正常说明 Docker 引擎已经在运行。这里有个新手常犯的错误——以为只要装好了 Docker服务就一定在跑Windows 上 Docker Desktop 没启动就执行命令会报 Cannot connect to the Docker daemon重启 Docker Desktop 就好。2.2 拉取镜像与首次创建容器一条命令和一个坑准备工作完成开始拉镜像。我以 Redis 7.0 为例这个版本在稳定性和新特性间取得了很好的平衡docker pull redis:7.0.12-alpine然后跑起来最简单的开发版容器docker run --name dev-redis -p 6379:6379 -d redis:7.0.12-alpines-d参数让它后台运行-p 6379:6379把容器的 6379 端口映射到宿主机这样宿主机上其他程序也能通过localhost:6379访问这个 Redis。这个最简单的命令确实能跑通但千万不要直接拿它当生产模板。原因有两个容器默认没有持久化配置Redis 进程一旦重启数据全部归零。没有设置密码和访问控制6379 端口暴露在公网上的话等同于把密钥放在门口垫子下面。验证容器是否正常运行docker ps docker exec -it dev-redis redis-cli ping如果返回PONG容器就跑通了。开发环境到这里其实已经够了但为了不让你在后续使用中碰壁我强烈建议第一步就把数据目录和配置都挂载出来一步到位。下面这个命令是我在实际项目里用的标准版docker run -d --name my-redis \ -p 6379:6379 \ -v /data/redis/redis.conf:/etc/redis/redis.conf \ -v /data/redis/data:/data \ --restartalways \ redis:7.0.12-alpine \ redis-server /etc/redis/redis.conf这条命令干了几件重要的事。第一宿主机/data/redis/redis.conf文件挂载进容器作为 Redis 配置保证配置在宿主机侧可以随时修改和备份第二/data/redis/data目录挂载成容器的/dataRDB 或 AOF 持久化文件都写到这个目录删容器不删数据第三--restartalways让 Docker 守护进程在容器意外退出或宿主机重启后自动拉起容器提升可用性。注意挂载配置文件时宿主机上的redis.conf必须先存在。如果文件不存在Docker 会默认创建一个空目录挂进去Redis 启动时会把它当成配置目录处理直接启动失败。我就有过这种经历——明明看着命令没问题容器一直在重启查日志才发现宿主机路径没建好。2.3 配置密码和开启持久化别等数据丢了才后悔分辨是否真正改好了 Redis 配置可以用一个土办法——执行docker exec my-redis redis-cli info persistence看loading是 0再看rdb_last_bgsave_status是不是ok。下面我把生产必需的配置项列成一张速查表每一项我都会解释为什么需要它配置项推荐值作用与说明requirepass强密码设置访问密码客户端连接时需要 AUTHappendonlyyes开启 AOF 持久化降低数据丢失风险appendfsynceverysec每秒钟刷盘一次平衡性能与可靠性maxmemory按实际内存设防止 Redis 吃光宿主机内存maxmemory-policyallkeys-lru内存满时按 LRU 淘汰旧数据save900 1 / 300 10 / 60 10000配置 RDB 快照触发的条件关于持久化这就多说几句。Redis 官方提供了 RDB 和 AOF 两种机制RDB 是定期对整个数据集做二进制快照恢复速度快但最多可能丢最后一次快照之后的数据AOF 则是记录每条写命令按策略刷盘最多丢 1 秒甚至更少的数据。生产环境我基本都开启appendonly yes并且把appendfsync设为everysec。这样既不会像always那样让写入性能明显下滑又能把数据丢失窗口压缩到一秒以内。自定义一个精简的redis.conf放到宿主机bind 0.0.0.0 protected-mode yes port 6379 timeout 0 tcp-keepalive 300 daemonize no supervised no pidfile /var/run/redis_6379.pid loglevel notice logfile 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 requirepass YourStrongPassword123 appendonly yes appendfsync everysec maxmemory 1gb maxmemory-policy allkeys-lru这里重点解释daemonize no。Docker 容器里没有完整的 init 系统进程管理器就是容器本身Redis 必须以前台进程方式运行否则容器会觉得我这个应用已经跑完退出了然后立刻把容器关掉。在裸机上我们习惯daemonize yes让 Redis 后台化在容器里必须反过来。这个细节是容器部署和裸机部署最大的认知差异之一忘掉这一点容器启动几秒后就退出怎么看日志都找不着原因。3. 把容器化 Redis 当成生产服务对待网络、安全与性能优化我接触过很多团队Docker 里 Redis 能跑通就算完事了直到被渗透、或者大促时 Redis 拖垮了整台机器才回头补课。容器不是隔离一切的魔法该做的网络安全和主机安全措施一项都不能少。3.1 端口映射与容器网络为什么不能用-p 6379:6379裸奔默认的 Redis 配置只监听127.0.0.1但我在 2.2 节里给的那个生产命令还没改配置直接把所有网络接口都暴露了。docker run -p 6379:6379的含义是把宿主机所有网卡上的 6379 都映射到容器如果宿主机有公网 IP就相当于把 Redis 端口直接暴露到公网。正确的做法是只映射到内网接口或者干脆不映射端口通过 Docker 内部网络让其他容器访问。例如只监听本机回环只在宿主机本机调试时才暴露docker run -d --name my-redis \ -p 127.0.0.1:6379:6379 \ ...但更推荐的方式是让需要访问 Redis 的业务容器和 Redis 容器处在同一个 Docker 自定义网络中通过容器名互相解析访问docker network create app-network docker run -d --name my-redis \ --network app-network \ -v /data/redis/redis.conf:/etc/redis/redis.conf \ -v /data/redis/data:/data \ --restartalways \ redis:7.0.12-alpine \ redis-server /etc/redis/redis.conf docker run -d --name my-app \ --network app-network \ -p 8080:8080 \ my-app-image这样一来my-app容器里连接 Redis 时只需要写redis://my-redis:6379完全不需要依赖宿主机 IP 和端口映射。端口只在需要从外部调试时才临时暴露用完即删。这里也顺便说明一下Docker 容器默认用的 bridge 网络容器重启后 IP 很可能会变。如果业务代码里写死了 Redis 的 IP容器一重建就崩——这就是很多人抱怨容器网络不通的高频原因。用 Docker 内置 DNS 和容器名来解决 IP 漂移问题是标准答案。3.2 安全加固密码、ACL 和防火墙三条防线缺一不可Redis 历史上爆出过多次高危漏洞最著名的就是未授权访问配合特定版本反序列化漏洞直接被打穿主机。所有云上部署的 Redis 都必须做下面三件事强制密码requirepass设置强密码。虽然 Redis 性能极高密码本身不怎么影响吞吐但弱密码比没有密码好不了多少。最小权限 ACLRedis 6.0 以后支持 ACL 机制可以给不同客户端建不同用户比如只读用户、指定 key 前缀的用户。不要把管理员的全部权限交给每个业务方。宿主防火墙配合即使 Docker 做了端口映射也应该在宿主机层面把 6379 的访问限制在可信源 IP。ACL 简单示例在 redis.conf 里追加user default on nopass ~* all user readonly on ReadOnlyPass123 ~readonly:* get mget exists ttl这意味着默认用户仍然全权限适合管理者而 readonly 用户只能访问readonly:前缀的 key并且只能执行查询命令无法写入和删除。对于后端应用只读场景这种隔离能有效降低误操作风险。3.3 性能参数与资源限制maxmemory 一定要设一个很反直觉的事实是Redis 本身很快但如果宿主机的物理内存被 Redis 耗尽性能会瞬间从天堂跌到地狱甚至拖垮整个 Docker 宿主。原因很简单Redis 的数据存在内存里不设maxmemory时它会一直写下去直到触发 Linux 的 OOM Killer。给每个 Redis 容器加上内存限制双保险docker run -d --name my-redis \ --memory2g \ --memory-swap2g \ ...--memory2g限制容器最多使用 2GB 物理内存--memory-swap2g表示不分配交换分区swap避免进程被换页拖到极慢。容器内部再把maxmemory 1.5gb配好预留 500MB 给操作系统的页缓存和连接缓冲确保 Redis 不会碰到容器硬上限。关于线程和连接数我也提一句。Redis 6.0 之后引入了多线程 I/O默认是关闭的。如果你在 8 核以上的机器跑 Redis可以开一点 I/O 线程提升吞吐但注意CPU 密集场景反而不要开因为 Redis 本身的命令执行依然是单线程开了多线程只加速网络读写具体开多少建议用redis-benchmark实测docker exec -it my-redis redis-benchmark -h 127.0.0.1 -p 6379 -a YourStrongPassword123 -c 50 -n 100000 -t set,get这个命令会模拟 50 个并发客户端连续执行 10 万次 set 和 get输出的requests per second就是当前实例的吞吐上限参考值。多加一个-t参数可以只测特定命令比如热点命令hset、lpush等。4. 更进一步Redis 主从复制与哨兵切换的容器化落地单机 Redis 始终有单点风险。容器世界里主从复用镜像启动两个新容器就能搭起来比裸机简单不少。但组网细节有一点必须留心——容器重启后从节点怎么自动重连主节点。4.1 Docker 网络下的主从配置方式假设已经有一个主节点my-redis在app-network网络中运行。从节点配置只需要增加一行replicaof my-redis 6379。为了让从节点配置独立我会再复制一份配置文件或者在一个新容器里用命令参数直接覆盖docker run -d --name redis-replica-1 \ --network app-network \ -v /data/redis/replica1.conf:/etc/redis/redis.conf \ -v /data/redis/replica1-data:/data \ --restartalways \ redis:7.0.12-alpine \ redis-server /etc/redis/redis.conf从节点的replica1.conf在主机和端口部分改成这样replicaof my-redis 6379 replica-read-only yes最开始我们用的是主节点 IP比如replicaof 172.18.0.2 6379。后来主节点容器因为机器重启换了 IP从节点一重新连接就找不到主节点了。虽然docker network的 DNS 解析可以帮助服务间用名字互访但 Redis 从节点的replicaof配置会自己解析主机名并缓存一旦解析结果变化重连就出问题。稳妥的办法是让主节点使用固定容器名并且在配置文件中用容器名而不是 IP同时在 Docker 网络里为主节点配置静态 IPdocker network create --subnet172.20.0.0/16 app-network docker run -d --name my-redis \ --network app-network \ --ip 172.20.0.10 \ ...这样主节点的 IP 固定为172.20.0.10从节点的replicaof 172.20.0.10 6379即使重启也稳定。不过真要追求高可用还是得上哨兵Sentinel或 Redis Cluster这里不展开简单提一下 Sentinel 容器化也建议走独立网络并配置好sentinel monitor mymaster 172.20.0.10 6379 2这种故障切换探测配置。4.2 如何验证主从复制真的同步了验证主从复制状态进主节点执行docker exec -it my-redis redis-cli -a YourStrongPassword123 info replication输出中重点看两处role:master或role:slave是否符合预期从节点的master_link_status:up如果这里是down说明主从没连上优先检查网络和replicaof配置。再往从节点里写一个测试 key然后到从节点用redis-cli查docker exec -it redis-replica-1 redis-cli -a YourStrongPassword123 -p 6379 get test-key从节点默认只读能查出主节点写入的 key说明同步正常。我遇到过一种隐蔽问题——日志一直显示同步正常但实际从节点数据一直停留在几天前后来查了配置文件才发现从节点没打开 AOF 持久化期间重启过一次所有同步到内存里的数据全丢了。记住容器里的从节点照样要配持久化它不只是缓存的备胎更是故障切换时的新主节点。4.3 配合 Docker Compose 一键拉起主从集群手动执行多条docker run容易漏参数维护性也差。Docker Compose 把整个主从拓扑写成一个 YAML 文件一条命令就能拉起全部节点这也是现在团队里更加通行的管理方式。这个docker-compose.yml是我精简过的版本services: redis-master: image: redis:7.0.12-alpine container_name: redis-master restart: always command: redis-server /etc/redis/redis.conf volumes: - /data/redis/master.conf:/etc/redis/redis.conf - /data/redis/master-data:/data networks: app-network: ipv4_address: 172.20.0.10 redis-replica-1: image: redis:7.0.12-alpine container_name: redis-replica-1 restart: always depends_on: - redis-master command: redis-server /etc/redis/redis.conf volumes: - /data/redis/replica1.conf:/etc/redis/redis.conf - /data/redis/replica1-data:/data networks: app-network: ipv4_address: 172.20.0.11 networks: app-network: driver: bridge ipam: config: - subnet: 172.20.0.0/16启动命令docker compose -f docker-compose.yml up -dCompose 相比裸命令的好处是启动顺序由depends_on控制、网络由声明式配置自动创建、重启策略统一写在配置里、新增节点只需复制一个 service 块。如果一个项目里同时还有 MySQL 等中间件也建议把它们的容器编排都收进同一个 compose 文件集中管理状态一目了然。每次修改 compose 文件后用docker compose config先做一次配置校验确认没有语法和缩进错误再真正执行up能省下不少排查时间。5. 高频故障排查实录从容器启动失败到性能瓶颈这部分是我最想写的因为这些坑都是我在真实环境里踩过、并且一行一行日志排查出来的。每一类问题背后都是一个看起来没毛病但实际就是不对的经典场景。5.1 容器反复重启CrashLoopBackOff的原因与排查路径表现docker ps看到容器状态一直是Restarting通过docker logs或docker inspect能看到退出码和错误信息。高频原因依次是配置文件挂载成目录宿主机/data/redis/redis.conf不存在或实际是个目录容器里读配置文件失败。Redis 进程后台化配置文件里写了daemonize yesRedis fork 到后台后容器认为主进程已结束直接退出。目录权限不足Redis 对/data目录没有写权限RDB 保存失败。端口被宿主机占用宿主机 6379 已有其他进程监听端口映射失败。排查固定流程是# 看容器当前状态和退出码 docker inspect -f {{.State.ExitCode}} {{.State.Status}} my-redis # 看最近日志 docker logs --tail 100 my-redis # 如果有退出码从 exit code 反推原因日志里最有价值的是这两行# Cant open the log file: Permission denied # Bad directive or wrong number of arguments前者基本就是目录权限问题后者多半是 redis.conf 里出现了不兼容的配置指令要对照镜像版本语法检查。配置文件最好是先用redis-server /path/redis.conf --test在测试环境验证过避免把笔误带上生产。5.2 Redis 连接超时容器内外网和宿主机防火墙的共同作用出现 command timed out 这类 LinkedIn 报错或者客户端持续连接超时排查重点是链路。我按从近到远的顺序排一个清单Redis 进程是否真的活着docker exec -it my-redis redis-cli ping日志里有没有明显报错或反复重启记录端口是否映射docker port my-redis宿主机防火墙是否放行Linux 检查iptables -L -n | grep 6379从业务容器内部能否解析 Redis 容器名docker exec -it my-app ping my-redis或getent hosts my-redis有一个非常常见的场景是Redis 容器在 A 网络业务容器在 B 网络两边都启得正常但业务连接 Redis 走的是默认 bridge 网络里的一个随机 IP容器一重启 IP 变了连接全部超时。判断方法很简单进业务容器看它连接的 IP 是不是docker network inspect里 Redis 实际分配的 IP不一致就说明网络拓扑错了。这个问题的标准解法和我在 3.1 节说的一样把两个容器放在同一个自定义网络里并用容器名通信。redis-cli 连接时如果走了代理或端口映射注意-h要用宿主机可路由的地址容器内连接往往用localhost反而不通因为 Redis 默认有 bind 配置这点在跨宿主机调试时最容易忽略。5.3 Docker Desktop 在 Windows 上启动失败的专项排查Windows 上启动 Docker Desktop 报virtualization support not detected或者Docker Desktop failed to start because virtualisation support wasnt detected属于检索量极大的一类问题。原因几乎都是三个方向BIOS 没开虚拟化、Windows 的 Hyper-V/VBS 没启用、WSL 2 没装。逐一处理# 以管理员身份运行 PowerShell检查虚拟化支持 systeminfo | findstr /i Hyper-V # 启用 WSL 和虚拟机平台 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart # 更新 WSL 内核 wsl --update wsl --set-default-version 2改完设置后必须重启操作系统让内核组件生效再打开 Docker Desktop。如果重启后还是报错去 Windows 功能里手动勾选Windows 虚拟机监控程序平台和适用于 Linux 的 Windows 子系统。少数情况是 Docker Desktop 版本和 Windows 版本不匹配尤其是老版本 Windows 10 的 LTSC直接去下载对应支持版本的 Docker Desktop 就好。这类兼容性问题没有统一解法只能结合 Windows 版本号去 Docker 官方 release notes 里查支持矩阵。5.4 性能排查容器里 Redis 为什么比裸机慢如果你发现容器里的 Redis 吞吐明显不如裸机先别怀疑 Docker 本身绝大多数情况是下面几个因素在拖后腿存储驱动差异Docker 的默认存储驱动 overlay2 对大量小文件写入有额外开销尤其是 RDB 快照频繁写盘时。内存限制和 swap--memory-swap没设置时Linux 可能给容器分配 swap 空间Redis 内存被换页后性能跌得惨不忍睹。网络转发模式默认 bridge 网络的 NAT 转发有一定 CPU 开销在万兆网卡和高 PPS 场景下比较明显。CPU 配额如果容器被设置了严格的--cpus限制CPU 密集型命令如keys *、大 sorted set 范围查询会被明显限速。我调优时最常做的三个操作设置--memory-swap2g与--memory2g相同值禁用 swap把数据盘改用更快的 SSD 或用 Docker 的 volume 而不是 bind mount宿主机文件系统缓存差异确认save策略不要过分激进不然 RDB 快照会频繁抢占 CPU。如果能接受写延迟的微小上升还可以把 AOF 的刷盘策略改回everysec这比always性能好得多。对 Redis 本身还要注意慢日志。容器里查慢日志很方便docker exec -it my-redis redis-cli -a YourStrongPassword123 slowlog get 20它能列出最近 20 条执行时间超过慢日志阈值的命令看到满屏KEYS *或SMEMBERS时就该考虑改用SCAN或把数据放到合适的数据结构里了。这套方法论放到容器内外都通用。6. 运维向的补充经验备份、监控与升级的容器化实践文章到这里Redis 在 Docker 里已经能稳定跑起来了。但能跑和能长期跑好之间还有一截差距这部分我把运维相关的压箱底经验一并整理。6.1 数据备份的最佳姿势别只靠镜像层面的快照Redis 的 RDB 文件就写在宿主机的挂载目录里但不要觉得目录在宿主机就等于备份了。宿主机磁盘挂掉、目录被误删、容器重建时-v参数写错路径分分钟数据全没。我维护项目的备份策略是三层结构本地文件保留RDB 和 AOF 文件保留在宿主机挂载目录沿用 Redis 自带的轮转机制。定期全量快照用定时任务把/data/redis/data整个目录压缩后上传到对象存储或另一台机器。关键数据双写对于订单状态这类极端重要的数据业务层再写一份到 MySQLRedis 只做加速层这是最终的兜底。写一个简单的备份脚本配合 crontab 每天凌晨执行#!/bin/bash # redis-backup.sh BACKUP_TIME$(date %Y%m%d%H%M%S) tar -czf /backup/redis-$BACKUP_TIME.tar.gz -C /data/redis/data . find /backup -name redis-*.tar.gz -mtime 7 -delete脚本把整个数据目录打成 tar 包并保留 7 天内的备份。如果在云上把tar之后再加一步同步到对象存储的命令即可。注意不要用docker commit去实现备份那只是容器文件系统层的内存快照很难确保 Redis 数据的写一致性。6.2 看监控指标和日志的几个实用命令容器化环境下监控是三层宿主机指标、容器资源指标、Redis 自身指标。宿主机和容器指标用docker stats快速看docker stats --format table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}这个命令能看到每个容器的 CPU 和内存实时占用。但它是断点式的想看历史趋势还得接 Prometheus 等时序数据库。Redis 自身的监控指标用INFO命令# 看内存和命中率 docker exec -it my-redis redis-cli -a YourStrongPassword123 info memory docker exec -it my-redis redis-cli -a YourStrongPassword123 info stats重点关注三个数字used_memory实际使用内存、redis_hit_rate如果命中率长期低迷排查业务层的缓存策略、connected_clients连接数是否逼近最大连接数上限。日志层面把容器日志标准化输出到宿主机是一件性价比很高的事。用--log-driverjson-file --log-opt max-size50m --log-opt max-file3可以控制日志文件大小轮转防止日志无限膨胀把宿主磁盘填满。6.3 版本平滑升级先备后切别在高峰期动刀容器升级 Redis 版本的核心优势是换容器比换进程干净但步骤不能鲁莽。我的升级套路是准备新镜像先拉新版本镜像用备份目录启动一个临时容器导入现有 RDB 文件验证业务查询正常。停止写入在低峰期把应用切换到只读模式或者直接把主节点切断写入确保数据静止。最后一次备份确认 RDB/AOF 文件是最新状态。切换容器停掉旧容器用新镜像启动新容器挂载同样的数据目录和配置端口映射保持一致。逐步回放流量先放少量流量观察日志和监控指标再逐步全量放通。这里有个容易被忽视的点大版本升级后RDB 文件格式可能不同。Redis 7.0 默认的 RDB 格式Redis 6.2 的实例可能读不了。所以升级前一定要在新实例上redis-check-rdb和debug reload验证数据完整性不要想当然。如果你只是在同一主版本内升级补丁版本这个风险会小很多这也是我坚持用7.0.12而不是7.2这类大版本的原因之一。7. 写在最后的几点个人体会容器化部署 Redis 的这个轮子我前前后后推了快三年。如果只让我说一条最想分享的经验那就是——容器只是打包和调度的手套Redis 本身的运维常识依然适用。很多人在 Docker 里出了问题就想怪 Docker但事实上 90% 的问题往前排查几步都能落到 Redis 配置、网络拓扑、资源限制这些老问题上。还有一个小技巧调试阶段给 Redis 容器加--network host模式会让你少操心很多网络问题容器直接共享宿主机的网络栈端口不用映射localhost:6379直接可用适合临时排查。但它是双刃剑——容器和宿主机网络完全平等安全隔离基本失效所以只建议在开发和应急修复时用生产环境老老实实回到自定义网络或 bridge 模式。最后分享一个我在迁移中受益非常大的操作每改一个配置就用docker diff对比容器启动前后内部文件系统的变化再配合docker exec进入容器逐个目录检查慢慢地你对 Redis 容器内外的文件布局会形成肌肉记忆。以后无论是排障还是做安全审计这份熟悉度都能帮你省下大把时间。如果你是刚开始接触 Docker 和 Redis 的读者照着这篇文章把开发环境和主从集群搭一遍再故意制造几次故障比如拔掉网络、停掉主节点、删掉数据目录看着 Redis 和 Docker 如何反应比看十篇教程都管用。
返回列表