--- tags: [Redis, 缓存, 运维, 部署] create time: 2026-05-15 18:10 --- # Redis 安装与部署 ## 概述 本节介绍 Redis 的安装方式、关键配置和安全加固。无论使用官方二进制还是容器化方案,核心目标一致:**安全启动、合理分配内存、设置持久化策略**。 > [!QUESTION] 为什么安装步骤简单,生产部署却容易出问题? > > Redis 本质是一个单进程内存服务,安装只需几行命令。但一旦上线,内存超限导致 OOM Killer 介入、未设密码被外网扫描器写入大量脏数据、或 AOF/RDB 同时触发 fork 导致内存翻倍——这些才是真正需要关注的问题。 ## 选择安装方式 先根据场景确定合适的部署路径: ```mermaid flowchart LR A[开始:选择安装方式] --> B{运行环境?} B -->|macOS 本地开发| C[brew install redis] B -->|Ubuntu/Debian 服务器| D[apt install redis-server] B -->|需要指定特定版本| E[源码编译] B -->|本地开发 / 微服务| F[Docker Compose 推荐] B -->|高可用集群| G[[hhs/Redis/07-集群方案]] C --> Z[进入配置阶段 →] D --> Z E --> Z F --> Z ``` ### macOS — Homebrew ```bash brew install redis # 安装最新稳定版 brew services start redis # 注册为后台服务 redis-cli ping # 验证:应返回 PONG ``` > [!TIP] 安装后配置文件位于 `/opt/homebrew/etc/redis.conf`(Apple Silicon)或 `/usr/local/etc/redis.conf`(Intel)。 ### Linux — 包管理器 ```bash sudo apt update && sudo apt install redis-server sudo systemctl enable --now redis-server ``` 发行版默认安装的 Redis 版本可能落后于上游最新版。如果需要跟进特性或安全补丁,考虑源码编译或 Docker。 ### 源码编译(指定版本) ```bash wget https://download.redis.io/releases/redis-7.2.4.tar.gz tar xzf redis-7.2.4.tar.gz cd redis-7.2.4 make -j$(nproc) # 利用多核并行编译 sudo make install # 安装到 /usr/local/bin redis-server --version # 确认版本 ``` > [!NOTE] Redis 基于 C 开发,编译时无外部依赖(新版内置 jemalloc)。如果你的系统缺少 gcc/make,需提前安装构建工具链。 ### Docker(推荐本地开发) 将以下内容保存为 `docker-compose.yml`: ```yaml version: "3.9" services: redis: image: redis:7-alpine # Alpine 镜像仅 ~30MB,适合开发环境 container_name: redis-dev ports: - "6379:6379" volumes: - redis-data:/data command: > redis-server --requirepass ${REDIS_PASSWORD:-changeme} --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru restart: unless-stopped volumes: redis-data: ``` **启动、验证、连接一气呵成:** ```bash # 1. 在 docker-compose.yml 同目录下启动(-d 后台运行) docker compose up -d # 2. 查看容器状态和端口映射 docker compose ps # NAME STATUS PORTS # redis-dev Up 30s 0.0.0.0:6379->6379/tcp # 3. 通过容器内 redis-cli 验证连通性 docker exec redis-dev redis-cli -a changeme ping # 输出: PONG # 4. 本地 redis-cli 连接(如果本机已安装) redis-cli -h 127.0.0.1 -p 6379 -a changeme ``` > [!TIP] > - 通过 `${REDIS_PASSWORD:-changeme}` 引用环境变量,避免在仓库中硬编码真实密码。启动时可 `REDIS_PASSWORD=my-secret docker compose up -d` 覆盖默认值。 > - 开发环境建议限制 `maxmemory`,防止占满本机内存。 > - 生产环境不要使用 `redis:latest` 标签,锁定具体版本号以避免未知变更。 > [!QUESTION] 为什么用 `docker exec` 而不是直接 `redis-cli`? > > `docker exec` 不依赖本机是否安装了 redis-cli,任何装了 Docker 的机器都能直接执行——在 CI/CD 或同事的机器上尤其方便。而本机 `redis-cli` 的好处是支持命令历史补全和更丰富的交互体验。 > [!EXAMPLE] 常用运维命令速查 > ```bash > docker compose logs -f redis # 实时查看日志 > docker compose stop redis # 停止容器(保留数据卷) > docker compose down -v # 停止并删除数据卷(慎用,清空数据) > docker exec redis-dev redis-cli -a changeme INFO memory # 查看内存使用 > ``` ## 关键配置项 编辑 `redis.conf`(Docker 用命令行参数覆盖),以下是生产环境必看的核心选项: | 配置项 | 推荐值 | 说明 | |--------|--------|------| | `bind 127.0.0.1` | 内网 IP 或注释 | 限制监听地址;生产环境需配合防火墙规则 | | `protected-mode yes` | 保持默认 | 无密码时自动拒绝外部连接 | | `port 6379` | — | 自定义端口,但不要指望这算安全措施 | | `requirepass your-strong-pass` | 强密码 | **必须设置**,尤其对外暴露时 | | `maxmemory 2gb` | 物理内存的 60%~70% | 防止 OOM Killer 接管,给 OS 和子进程留余地 | | `maxmemory-policy allkeys-lru` | — | 内存满时的淘汰策略,见下方说明 | | `tcp-backlog 511` | 511~1024 | 三次握手已完成但未被 accept 的队列深度 | | `timeout 300` | 300 | 客户端空闲超时断开(秒),释放无效连接 | | `loglevel notice` | — | debug 级别会产生海量日志,影响性能 | | `databases 16` | — | 逻辑数据库数量,通常不改 | > [!IMPORTANT] maxmemory-policy 的选择直接影响业务语义 > > - `allkeys-lru`:对所有键做 LRU 淘汰。**通用场景首选**。 > - `volatile-lru`:仅对设置了过期时间的键做 LRU 淘汰。适合缓存+热数据混合的场景。 > - `noeviction`:不淘汰,空间不足时直接报错。适合纯缓存,应用层自行控制生命周期。 > > **选错策略的代价是什么?** 如果用 `noeviction` 而忘了设置过期时间,Redis 会在写操作时报 `OOM` 错误,而非优雅降级。 启动并验证配置: ```bash # 以自定义配置启动 redis-server /etc/redis/redis.conf # 逐项检查是否生效 redis-cli CONFIG GET maxmemory redis-cli CONFIG GET maxmemory-policy redis-cli CONFIG GET requirepass ``` > [!NOTE] 线上修改无需重启:大部分配置可以通过 `CONFIG SET key value` 动态调整,但退出后失效。持久化需在配置文件中修改。 ## Systemd 服务管理(Linux) 使用 systemd 管理能确保开机自启、崩溃自动恢复: ```ini [Unit] Description=Redis In-Memory Data Store After=network.target # 网络就绪后再启动 Redis [Service] Type=simple ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf ExecReload=/bin/kill -USR2 $MAINPID # USR2 触发配置重载(Redis 6.2+) Restart=on-failure # 崩溃后自动拉起 RestartSec=5 # 间隔 5 秒重试,避免频繁闪退 LimitNOFILE=65535 # 文件描述符上限,支持大量并发连接 [Install] WantedBy=multi-user.target # 多用户模式下的标准服务 ``` ```bash sudo systemctl daemon-reload # 读取新增/修改的服务文件 sudo systemctl enable --now redis # 启动 + 开机自启 sudo journalctl -u redis -f # 实时查看日志 ``` > [!QUESTION] 为什么 `Restart=on-failure` 还不够? > > 如果 Redis 因为配置错误(如 bind 地址不可达)反复崩溃,`on-failure` 会无限重试。配合日志告警或健康检查才能真正发现问题。 ## 内核级调优 Redis 是 IO 密集型单进程服务,操作系统层面的参数会直接影响吞吐量上限: ```bash echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf echo "net.core.somaxconn = 1024" >> /etc/sysctl.conf echo "vm.max_map_count = 262144" >> /etc/sysctl.conf sysctl -p # 立即生效 ``` ```mermaid flowchart LR A[客户端连接请求] -->|SYN| B["TCP 半连接队列
somaxconn"] B -->|三次握手完成| C["TCP 全连接队列
tcp-backlog"] C --> D[Redis accept] D --> E["分叉持久化
overcommit_memory"] style A fill:#e1f5fe style C fill:#fff3e0 style E fill:#f3e5f5 ``` | sysctl 参数 | 作用 | 为什么需要 | |-------------|------|-----------| | `vm.overcommit_memory = 1` | 允许 fork() 时内存过度分配 | RDB 和 AOF rewrite 都通过 fork 创建子进程,父子进程共享物理页;若无此设置,大内存实例 fork 可能被内核拒绝 | | `net.core.somaxconn = 1024` | TCP 全连接队列长度 | 高并发下队列满了会导致客户端 connect 超时,表现为"Redis 连不上" | | `vm.max_map_count = 262144` | mmap 区域上限 | Redis 在开启 LFU 等特性时会使用 mmap,默认值过小会被限制 | ## 部署架构演进 单机 → Sentinel → Cluster,不同阶段的架构差异: ```mermaid flowchart TB subgraph S1[阶段一:单机] C1[Client] --> M1[(Master)] end subgraph S2[阶段二:主从 + Sentinel] C2[Client] --> M2[(Master)] C2 -.-> S2a[Sentinel] M2 --> S2b[(Slave 1)] M2 --> S2c[(Slave 2)] end subgraph S3[阶段三:Cluster] C3[Client] --> P[Hash Slot 路由] P --> N1[Node 1: Slots 0-5460] P --> N2[Node 2: Slots 5461-10922] P --> N3[Node 3: Slots 10923-16383] end S1 ===>|数据量增长,需要高可用| S2 S2 ===>|单机内存瓶颈,需要水平扩展| S3 style S1 fill:#e8f5e9 style S2 fill:#fff3e0 style S3 fill:#fce4ec ``` > [!INFO] 本系列后续文档将深入每个阶段: > - [[hhs/Redis/04-RDB持久化]] — RDB 快照机制 > - [[hhs/Redis/05-AOF持久化]] — 追加日志机制 > - [[hhs/Redis/07-集群方案]] — Cluster 分片原理与部署 ## 快速检查清单 > [!CHECKLIST] 部署前核对 > - [ ] 已设置 `requirepass`(非默认或测试密码) > - [ ] `maxmemory` 不超过物理内存的 70%,预留 OS 和 fork 空间 > - [ ] 已启用持久化(至少 AOF `appendonly yes`) > - [ ] `bind` 指向内网地址,或通过防火墙限制访问来源 IP > - [ ] `vm.overcommit_memory` 已设为 1 > - [ ] 已配置合理的 `timeout` 和 `tcp-keepalive`,清理僵尸连接 > - [ ] 确认 `maxmemory-policy` 符合业务语义(推荐 `allkeys-lru`) > - [ ] Docker 部署时密码通过环境变量注入,未硬编码在 compose 文件中 ## 关联笔记 - [[hhs/Redis/02-核心数据类型]] — String / Hash / List / Set / ZSet 的使用场景 - [[hhs/Redis/04-RDB持久化]] — RDB 快照原理与配置 - [[hhs/Redis/05-AOF持久化]] — AOF 重写机制与 fsync 策略 - [[hhs/Redis/07-集群方案]] — Cluster 部署与迁移策略 - [[hhs/Redis/11-运维与性能调优]] — OOM、延迟 spike、连接数爆满的诊断思路