257 lines
9.3 KiB
Markdown
257 lines
9.3 KiB
Markdown
|
|
---
|
|||
|
|
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、连接数爆满的诊断思路
|