Files
cs-note/hhs/Redis/01-安装与部署.md
T
2026-05-25 20:51:57 +08:00

283 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 半连接队列<br>somaxconn"]
B -->|三次握手完成| C["TCP 全连接队列<br>tcp-backlog"]
C --> D[Redis accept]
D --> E["分叉持久化<br>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、连接数爆满的诊断思路