第2章:Windows、WSL2 与 Docker 环境搭建Redis 1. 项目背景1.1 业务场景团队技术栈多样运维老李的笔记本是 Ubuntu后端开发小王是 Windows 11 WSL2测试张姐用的是公司配的 MacBook。上周小王照着网上的教程直接下载了一个 Windows 版的redis-server.exe启动后发现版本是 5.0但项目要求用 Redis 8.6 的 Stream 消费组和字段级过期能力。更糟的是小王在 Windows 上能正常运行BGSAVE因为 Windows 版的 fork 实现不同但同样的命令在 Linux 生产环境却因为内存过大导致 fork 失败。张姐那边也有问题——她用 Docker 启动了 Redis连上 RedisInsight 后发现看不到数据排查了半天才发现 Docker 的网络模式让她从宿主机访问localhost:6379时走的是另一个网络命名空间。三个人折腾了一天愣是没让环境统一起来。1.2 痛点环境不一致是实战学习中最大的阻力来源问题表现后果Redis 版本不同Windows 版只到 5.0Linux 版到 8.6Stream、ACL v2、字段级过期等新能力无法验证配置不统一有人用默认配置无密码、无 AOF有人改了但没记录“我这里可以你那里不行”数据目录混乱持久化文件散落各处容器重启后数据丢失无法复现持久化恢复流程网络不通宿主机、容器、WSL2 的网络栈不同RedisInsight 连不上、redis-benchmark 报错缺少可视化工具只用 redis-cli 看文本输出无法直观观察 key 分布、内存占用、慢查询趋势1.3 本章目标不只装一个 Redis而是搭建一套可重复、可销毁、可扩展、接近生产的实验环境。这个环境将支撑后续所有章节的实战内容——从单机数据结构到 Sentinel 高可用、Cluster 集群、Prometheus 监控全程不需要重新折腾环境。具体交付物一份redis.conf最小但合理的配置文件带密码、AOF、数据目录。一份docker-compose.ymlRedis RedisInsight 可视化工具。掌握redis-cli、redis-benchmark、redisinsight的使用。一份环境故障排查清单端口冲突、认证失败、挂载异常、网络不通。2. 项目设计2.1 第一幕为什么不用 Windows 原生版小胖“我以前学 Redis直接官网下载一个redis-server.exe双击就启动了多简单。为什么还要装 DockerDocker Desktop 占好几 G 内存呢。”小白“Windows 原生版的 Redis 是微软维护的 fork最新版本只到 5.0.x。我们专栏要用的 Stream 消费组、ACL v2、字段级过期、Redis Functions、JSON 模块、Vector 检索这些在 5.0 上全都没有。难道你打算每个新功能都去网上找’降级方案’吗”小胖“那 WSL2 呢我听说 WSL2 可以直接用 Linux 版 Redis”大师“WSL2 确实可以用 Linux 版但它和 Docker Desktop 之间是互补关系。我从三方面总结一下”环境方案Redis 版本启动方式文件系统网络适合谁Windows 原生 .exe最高 5.0双击 exeWindows 路径Windows 网络栈不推荐——版本和生产差距大WSL2 直接安装可装 8.xapt installWSL2 虚拟磁盘WSL2 独立 IP适合习惯 Linux 命令行、想深入系统层的同学Docker Desktop (Windows)任意版本docker runWSL2 后端端口映射专栏首选——版本可控、配置挂载、环境可销毁重建Docker (WSL2 内)任意版本docker runWSL2 内目录端口映射到宿主机进阶推荐——更接近生产体验大师“就像去健身房。Windows 原生版是你家客厅的健身环——能出汗但和专业器械完全不同。WSL2 是社区健身房——器械齐全但你要自己带毛巾和水杯。Docker 是标准化的健身包——每次打开都是一套标准器械坏了换一包就行。”技术映射Docker 通过镜像固定 Redis 版本通过 Compose 固定启动参数、网络拓扑和数据卷。这是实现开发/测试/生产环境一致性最低成本的方式。小胖“那听你的用 Docker。但我有个小问题——Docker Desktop 和 WSL2 是啥关系我装了 Docker Desktop 之后好像自动装了一个 WSL2”大师“好问题。Docker Desktop for Windows 默认使用 WSL2 作为后端引擎。你在 Windows 上运行docker run实际是在 WSL2 的 Linux 内核里跑的。WSL2 里的/var/lib/docker存储镜像和容器数据你在 Windows 上是看不到的——也别去手动动它。”2.2 第二幕学习环境需要配密码和 AOF 吗小胖“学习环境配密码不是给自己添麻烦吗每次连 redis-cli 都要加-a redis123。还有 AOFAppend Only File我一台学习机数据丢了就丢了呗。”小白“我倒是觉得早点接触密码好。至少不会养成’Redis 无密码裸奔’的习惯。上次公司代码审查我发现有人把 Redis 密码硬编码在前端配置文件里——因为他从学习阶段就觉得’密码可有可无’。”大师“密码和 AOF 不是’生产才需要的东西’而是’理解 Redis 边界的东西’。”他画了一张对比图无密码的环境 带密码的环境 ┌─────────────────┐ ┌─────────────────┐ │ redis-cli │ │ redis-cli │ │ │ │ │ │ │ │ │ 直接连接 │ │ │ -a redis123 │ │ ▼ │ │ ▼ │ │ Redis Server │ │ Redis Server │ │ (无密码无安全) │ │ (ACL 校验) │ └─────────────────┘ └─────────────────┘ 无 AOF 的环境 带 AOF 的环境 ┌─────────────────┐ ┌─────────────────┐ │ 重启 → 数据全丢 │ │ 重启 → AOF 回放 │ │ Redis 不稳 │ │ 数据基本恢复 │ └─────────────────┘ └─────────────────┘大师“密码让你理解 Redis 的安全模型——它不是’内网就绝对安全’你后面会学到 ACL 用户体系、TLS 加密、命令权限。AOF 让你理解 Redis 的持久化模型——不是’内存数据库就是临时数据’Redis 可以选择性地持久化不同场景用不同策略。”技术映射学习环境的配置应该向生产靠近否则形成错误认知“Redis 不要密码”“Redis 重启数据就丢”后很难纠正。小白“那我追问一个问题——学习环境的数据挂载到宿主机有什么坑吗”大师“三个关键点。第一Windows 路径不能有中文、空格和特殊字符否则 Docker Desktop 的 WSL2 后端可能无法正确挂载。第二持久化文件RDB、AOF放在/data目录不要在外部手动修改这些文件。第三权限问题——某些 Docker 镜像的 Redis 以redis用户运行UID 999如果宿主机目录权限不对Redis 可能无法写入 AOF 文件。”2.3 第三幕RedisInsight 到底有多大用小胖“redis-cli 不就能看所有数据吗还要装一个 RedisInsight又是浏览器又是界面多麻烦。”小白“redis-cli 看单个 key 还行但你能一眼看出当前有多少 key、各类型分布、内存占用最大的 key 是哪个吗如果要分析慢查询日志的趋势redis-cli 只能一条一条SLOWLOG GET。”大师“RedisInsight 是 Redis 官方出的可视化管理工具。它不替代 redis-cli——redis-cli 是调试利器RedisInsight 是全景地图。我给你列几个用 redis-cli 做不到或者很麻烦的事情”操作redis-cliRedisInsight发现大 key需要redis-cli --bigkeys扫描一键查看 key 大小排行按类型筛选分析慢查询SLOWLOG GET 10手动查看图表展示慢查询趋势支持筛选时间范围内存分析需要MEMORY USAGE key逐个查看内存分布饼图按命名空间聚合批量操作需要写脚本可视化过滤、编辑、删除实时监控MONITOR是一条条刷屏图表展示 QPS、延迟、连接数大师“学习阶段RedisInsight 最大的价值是让你’看见’ Redis 里面发生了什么。比如你写入 100 个购物车 key它能用饼图展示 Hash 类型的占比你设置了不同 TTL 的 key它能直观显示哪些即将过期。”技术映射redis-cli 是命令行显微镜——精确但不直观RedisInsight 是运营仪表盘——帮你快速发现问题再决定去哪里放大观察。3. 项目实战3.1 准备项目目录在实验目录建议放在纯英文路径下创建以下结构redis-lab/ ├── docker-compose.yml # 编排文件 ├── redis.conf # Redis 配置文件 ├── data/ # 持久化数据目录RDB、AOF 文件 └── README.md # 环境说明可选# PowerShell (Windows)mkdirredis-labcdredis-labmkdirdata New-Item-ItemTypeFile-Namedocker-compose.yml New-Item-ItemTypeFile-Nameredis.conf3.2 编写 redis.conf# 网络配置 bind 0.0.0.0 port 6379 protected-mode yes timeout 300 tcp-keepalive 300 # 安全配置 requirepass redis123 # 持久化配置 # AOF appendonly yes appendfsync everysec auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # RDB save 900 1 save 300 10 save 60 10000 # 数据目录 dir /data # 内存配置 # 学习环境限制 512MB生产需按实际规划 maxmemory 512mb maxmemory-policy allkeys-lru # 慢查询日志 slowlog-log-slower-than 10000 slowlog-max-len 128 # 日志 loglevel notice logfile # 其他 databases 16关键配置解释配置项值说明bind 0.0.0.0绑定所有网卡容器内使用让宿主机能访问。生产环境应限制为内网 IPprotected-mode yes启用保护模式无密码时只允许本地连接。配合requirepass使用更安全requirepass redis123密码学习环境用简单密码生产必须用强密码且定期轮换appendfsync everysec每秒刷盘性能和安全的折中——最多丢 1 秒数据save 900 1900 秒内至少 1 个 key 变化则触发 bgsaveRDB 自动触发条件maxmemory 512mb最大内存容器无法获取宿主机的真实内存限制手动指定避免 OOMmaxmemory-policy allkeys-lru淘汰策略内存满时淘汰最近最少使用的 keyslowlog-log-slower-than 1000010 毫秒超过此时长的命令记录到慢查询日志loglevel notice日志级别学习环境用 notice生产调试时可用 verboselogfile 空字符串输出到 stdout方便docker logs查看3.3 编写 docker-compose.ymlversion:3.8services:redis:image:redis:8.6container_name:redis-labrestart:unless-stoppedports:-6379:6379volumes:-./redis.conf:/usr/local/etc/redis/redis.conf:ro-./data:/datacommand:[redis-server,/usr/local/etc/redis/redis.conf]healthcheck:test:[CMD,redis-cli,-a,redis123,ping]interval:10stimeout:5sretries:3start_period:10snetworks:-redis-netredisinsight:image:redis/redisinsight:latestcontainer_name:redisinsight-labrestart:unless-stoppedports:-5540:5540volumes:-./redisinsight-data:/dbnetworks:-redis-netnetworks:redis-net:driver:bridge编排说明配置说明restart: unless-stopped容器异常退出时自动重启除非手动 stop。学习环境防止误关后自动拉起volumes中的:roredis.conf 以只读模式挂载避免容器内误改healthcheckDocker 健康检查——每 10 秒发一次 PING连接失败视为不健康redisinsight-data目录RedisInsight 自己会管理连接配置挂载到宿主机方便反复创建networks两个容器在同一网络中RedisInsight 用redis-lab:6379即可连接3.4 启动并验证环境# 启动所有服务后台运行dockercompose up-d# 查看容器状态dockercomposeps# 期望输出:# NAME STATUS PORTS# redis-lab Up (healthy) 0.0.0.0:6379-6379/tcp# redisinsight-lab Up 0.0.0.0:5540-5540/tcp# 查看 Redis 日志dockerlogs redis-lab--tail20# 观察健康检查状态dockerinspect redis-lab--format{{json .State.Health}}|ConvertFrom-Json|Select-Object Status3.5 使用 redis-cli 连接带密码连接# 方式一命令行指定密码dockerexec-itredis-lab redis-cli-aredis123# 方式二先进入再认证dockerexec-itredis-lab redis-cli127.0.0.1:6379AUTH redis123 OK# 方式三通过环境变量redis-cli 6.0 支持 --pass 等价 -adockerexec-itredis-lab redis-cli--passredis123执行第一组验证命令127.0.0.1:6379PING PONG127.0.0.1:6379SET lab:envdocker-compose-v1OK127.0.0.1:6379GET lab:envdocker-compose-v1# 验证 AOF 已开启127.0.0.1:6379CONFIG GET appendonly1)appendonly2)yes# 验证 maxmemory 配置127.0.0.1:6379CONFIG GET maxmemory1)maxmemory2)536870912# 512 MB 536870912 字节# 验证数据目录127.0.0.1:6379CONFIG GETdir1)dir2)/data3.6 测试持久化数据在重启后是否还在# 写入一些测试数据dockerexecredis-lab redis-cli-aredis123 SET check:restorebefore-restartdockerexecredis-lab redis-cli-aredis123 SET check:counter42# 重启容器dockercompose restart redis# 等待 Redis 启动完成healthcheck 通过Start-Sleep-Seconds5# 读取之前的数据dockerexecredis-lab redis-cli-aredis123 GET check:restore# 期望输出: before-restartdockerexecredis-lab redis-cli-aredis123 GET check:counter# 期望输出: 42如果返回(nil)说明 AOF 或 RDB 没有正确加载。检查日志dockerlogs redis-lab|Select-String-PatternDB loaded|AOF3.7 配置 RedisInsight浏览器打开http://localhost:5540添加 Redis 数据库点击 “Add Redis Database”。填写连接信息Hostredis-lab容器间通信使用 Compose 的 service namePort6379Database Alias本地学习环境Username留空暂未配置 ACL 多用户Passwordredis123点击 “Test Connection”确认连接成功。点击 “Add Redis Database”。也可以在宿主机上使用不同方式连接连接来源Host说明RedisInsight 容器内redis-labDocker 内部 DNS 解析 service name宿主机浏览器 (RedisInsight UI)host.docker.internal或localhost取决于 RedisInsight 是连接宿主机端口还是内部网络推荐把 RedisInsight 和 Redis 放在同一个 Compose 网络中本章就是这么做这样 RedisInsight 直接通过 service nameredis-lab:6379连接不走宿主机端口映射。连接成功后在 RedisInsight 中浏览Browser查看和搜索 key支持按类型筛选。CLI内置命令行支持命令补全。Analysis→Memory Analyzer查看内存使用分布。Analysis→Slow Log查看慢查询记录和趋势。3.8 使用 redis-benchmark 基础压测# 在容器内执行压测dockerexec-itredis-lab redis-benchmark-aredis123-n100000-c50-tget,set-q# 输出示例# SET: 82345.67 requests per second, p500.247 msec# GET: 86956.52 requests per second, p500.233 msec# 测试不同并发数下的表现dockerexec-itredis-lab redis-benchmark-aredis123-n100000-c10-tget-qdockerexec-itredis-lab redis-benchmark-aredis123-n100000-c100-tget-qdockerexec-itredis-lab redis-benchmark-aredis123-n100000-c200-tget-q# 带延迟分位数的压测dockerexec-itredis-lab redis-benchmark-aredis123-n100000-c50--csv预期现象低并发时10-50P50 延迟通常在 0.2-0.3ms。高并发时200延迟略微增加主要瓶颈在客户端并发模型而非 Redis 本身。如果 QPS 远低于预期例如只有几万检查是否在虚拟机中运行或宿主机 CPU 资源不足。3.9 常见坑与解决坑1端口冲突# 现象Error starting userland proxy: listen tcp40.0.0.0:6379: bind: address alreadyinuse# 诊断netstat-ano|findstr :6379# 或Get-NetTCPConnection-LocalPort6379# 解决方式一停止占用端口的进程taskkill /PIDPID/F# 解决方式二修改 docker-compose.yml 端口映射ports: -6380:6379# 宿主机 6380 → 容器 6379坑2认证失败# 现象 127.0.0.1:6379 GET foo (error) NOAUTH Authentication required. # 原因连接时未提供密码 # 解决AUTH redis123 # 现象 127.0.0.1:6379 AUTH wrongpassword (error) WRONGPASS invalid username-password pair or user is disabled. # 原因密码不匹配 # 解决检查 redis.conf 中 requirepass 的值坑3数据卷挂载失败# 检查挂载是否生效dockerinspect redis-lab--format{{json .Mounts}}|ConvertFrom-Json# 预期输出包含# Source: /host_mnt/d/your/path/redis-lab/data# Destination: /data# 如果 Mounts 为空或路径不对检查# 1. docker-compose.yml 中是否使用了相对路径相对于 compose 文件所在目录# 2. Windows 路径中是否有中文或特殊字符# 3. Docker Desktop 的 Resources → File Sharing 是否包含实验目录坑4容器内 AOF 写权限问题# 现象Redis 启动后日志显示# Cant open the append-only file: Permission denied# 诊断dockerexecredis-labls-la/data# 如果输出为空目录或权限显示 nobody:# 原因Redis 容器内以 redis 用户UID 999运行宿主机 data/ 目录权限不足# 解决给 data 目录开放写权限Windows 上通常不需要额外处理# 如果问题持续可以尝试删除 data 目录后重新创建Remove-Item-Recurse-Force.\datamkdirdatadockercompose downdockercompose up-d坑5RedisInsight 连不上 Redis常见原因排查 1. Redis 是否在运行docker compose ps 2. RedisInsight 的 Host 写对了吗 - 如果 RedisInsight 和 Redis 在同一个 docker-compose 网络 → Host 填 redis-lab - 如果从宿主机浏览器通过端口映射访问 → Host 填 localhost 或 宿主机 IP 3. 密码是否匹配 redis.conf 中的 requirepass 4. 防火墙是否拦截了 5540 或 6379 端口坑6WSL2 内存占用过高Docker Desktop 基于 WSL2WSL2 默认会占用较多内存。可以限制在用户目录C:\Users\用户名\.wslconfig创建文件[wsl2] memory4GB processors2 swap2GB然后重启 WSLwsl--shutdown3.10 环境清理与重建当你需要从头开始时比如实验把数据搞乱了# 停止并删除容器数据卷保留dockercompose down# 停止并删除容器 数据卷彻底重置dockercompose down-v# 清理持久化数据Remove-Item-Recurse-Force.\data\*mkdirdata# 重新启动dockercompose up-d4. 项目总结4.1 交付物检查清单交付物验证方式docker-compose.yml 可正常启动docker compose up -d→docker compose ps显示 healthyredis.conf 密码生效redis-cli无密码连接报 NOAUTHAOF 持久化生效CONFIG GET appendonly返回 yes/data/下有 appendonly.aof 文件重启后数据保留写入 key →docker compose restart→ 读取 key 成功RedisInsight 可连接浏览器 http://localhost:5540添加数据库连接成功redis-benchmark 可运行输出 QPS 和延迟分位数4.2 优点与缺点方案特点详细说明优点1版本可控镜像redis:8.6固定版本团队所有人启动后获得完全相同的 Redis 环境和能力优点2配置透明redis.conf集中管理所有配置修改一处立即生效方便团队 Code Review优点3可销毁重建实验环境玩坏了不需要手动修复docker compose down -v docker compose up -d即可恢复优点4可视化加持RedisInsight 让学习者直观看见内存分布、key 类型和慢查询趋势优点5扩展方便后续加 Sentinel、Cluster、Prometheus 只需在 compose 文件加 service缺点1Docker Desktop 较重占用磁盘和内存但对学习来说利大于弊缺点2网络模型有差异Docker 的网络抽象增加了一层复杂度连接方式需要理解容器网络缺点3性能受限容器内的 Redis 性能略低于裸金属但学习场景完全够用缺点4WSL2 需要单独配置内存和处理器限制需手动配置否则可能占用过多资源4.3 适用与不适用场景适用场景本地学习和实验——后续 40 章全部基于此环境。团队新成员培训——一份 compose 文件交给新人10 分钟启动。功能验证——需要快速验证某个命令或配置的效果。故障演练——可以放心地制造崩溃、配置错误等场景。中小规模 Demo 开发——作为临时 Redis 依赖。不适用场景生产部署——需要 ACL、TLS、监控、备份、资源限制和高可用架构将在第 29-31 章展开。高并发压测——容器网络和资源限制会影响真实 QPS压测应在裸金属或 K8s 中进行。需要直连 Windows 进程的场景——如果你的应用是 Windows 原生进程且不方便改网络配置可能需要在 WSL2 中运行应用。4.4 常见踩坑经验案例表象根因解法团队新人启动失败docker compose up报错 “port already in use”本地已安装 MySQL 占用 6379 端口修改 compose 端口映射为 6380:6379环境文档注明AOF 文件把宿主机 C 盘写满电脑变卡发现data/目录下 AOF 文件超过 5GB开启了 appendonly 但没有配置 rewrite 阈值学习环境的压测数据被全部记录添加auto-aof-rewrite-min-size配置定期清理 data 目录RedisIninsight 连不上页面 “Connection refused”把 Host 写成 localhost但 RedisInsight 在容器内localhost 指向自己Host 使用 Compose service nameredis-labWindows 路径中文导致挂载失败容器内/data为空Docker Desktop 对包含中文的路径处理有 bug把实验目录移到纯英文路径下如 D:\projects\redis-labWSL2 内存占用过高任务管理器显示 vmmem 进程占用 8GBWSL2 默认不限制内存Docker 未使用的内存也不会释放给宿主机创建 .wslconfig 限制内存和处理器数量4.5 思考题环境题如果有一天你需要把本章的 Docker Compose 环境从 Windows 迁移到 Linux 生产服务器docker-compose.yml和redis.conf中分别需要修改哪些配置请至少列出 5 项。故障题你在本地执行docker compose up -d后docker compose ps显示redis-lab状态是Up (unhealthy)。请列出从最快到最深的排查步骤至少 4 步最终定位根因并修复。答案提示将在下一章末尾给出。上一章思考题答案提示第1章第1题key 格式建议为sms:daily:{userId}:{date}如sms:daily:1001:20260718。写入时执行INCR sms:daily:1001:20260718如果是首次递增则配合EXPIRE设置到当天 23:59:59 的剩余秒数。过期策略计算距离当天结束的剩余秒数作为 TTL确保 key 在跨天后自动清除。第2题至少 5 种根因① 上游服务调用量骤降业务侧问题② 网络故障导致客户端无法连接到 Redis但 connected_clients 显示旧连接未断开③ 客户端连接池耗尽新请求在客户端排队但未到达 Redis④ Redis 主线程被慢命令阻塞需看 slowlog⑤ 客户端连接未减少但都处于 IDLE 状态——优先排查慢查询日志和延迟监控。下一章预告第3章——字符串 String 实战验证码、计数器与分布式开关。延伸阅读与资源MongoDB 实战进阶与内核修炼python入门Rquests从菜鸟脚本到企业级SDK的网络实战圣经Milvus向量数据库实战修炼从 0 到 1精通向量检索与生产落地后端工程师的 AI 转型第一课Ollama 与私有化大模型实战10倍开发者的 Dify 魔法书从零构建全栈 AI 应用后端工程师转型AI第一课-Ollama 与私有化大模型实战大型语言模型(LLM) vLLM 高性能推理落地实战Agent开发之LlamaIndex 实战修炼与源码进阶大语言模型Transformers 实战修炼与源码剖析