--- 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(推荐本地开发) ```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: ``` > [!TIP] > - 通过 `${REDIS_PASSWORD:-changeme}` 引用环境变量,避免在仓库中硬编码真实密码。 > - 开发环境建议限制 `maxmemory`,防止占满本机内存。 > - 生产环境不要使用 `redis:latest` 标签,锁定具体版本号以避免未知变更。 > [!EXAMPLE] 如何快速连接带密码的 Redis? > ```bash > export REDIS_PASSWORD="your-strong-pass" > redis-cli -a "$REDIS_PASSWORD" ping > # 输出: PONG > ``` ## 关键配置项 编辑 `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 半连接队列\nsomaxconn] B -->|三次握手完成| C[TCP 全连接队列\ntcp-backlog] C --> D[Redis accept()] D --> E[分叉持久化\novercommit_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/08-常见问题排查]] — OOM、延迟 spike、连接数爆满的诊断思路