跳到主要内容

从安装到安全配置

本章目标是在 Linux 或 Docker 中得到一个“可连接、不会暴露公网、有内存上限、可恢复”的实例。先部署单机练习;高可用在后续章节再搭建。

完成后你将能够:

  • 规划 Redis 的配置、数据、日志和备份目录;
  • 使用 Docker Compose 启动一个持久化实例;
  • 看懂网络、AOF、内存和客户端相关配置;
  • 创建应用用户和运维用户并验证权限;
  • 重启实例后确认数据仍存在。

1. 先检查机器

Redis 的数据主要在内存中。maxmemory 不能等于物理内存,因为操作系统、复制缓冲区、RDB fork 的写时复制和内存碎片都需要空间。

free -h
df -h /var/lib/redis
sysctl vm.overcommit_memory
cat /sys/kernel/mm/transparent_hugepage/enabled

生产环境应预留内存、关闭 THP、设置 vm.overcommit_memory=1,数据目录使用可靠磁盘。不要把 Redis 与其他高内存服务随意混部。

1.1 一个简单的内存预算例子

一台 16 GiB 主机不应直接配置 maxmemory 16gb。初始可按下列思路评估:

用途示例预算
Redis 数据集上限10 GiB
fork 写时复制、复制缓冲与碎片3 GiB
操作系统、页缓存和守护进程3 GiB

这不是通用公式。写入越频繁、value 越大、持久化越频繁,fork 期间的额外内存越高,最终必须通过压测和监控校准。

2. 用 Docker Compose 完成可重复部署

建立独立目录:

mkdir -p ~/redis-tutorial/config
cd ~/redis-tutorial

创建 config/redis.conf

bind 0.0.0.0
protected-mode yes
port 6379
dir /data
appendonly yes
appendfsync everysec
maxmemory 256mb
maxmemory-policy allkeys-lru
loglevel notice

创建 compose.yaml

services:
redis:
image: redis:7.4-alpine
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
ports:
- "127.0.0.1:6379:6379"
volumes:
- redis-data:/data
- ./config:/usr/local/etc/redis:ro
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5

volumes:
redis-data:
docker compose config
docker compose up --detach --wait
docker compose ps
redis-cli -h 127.0.0.1 ping

预期 PING 返回 PONGdocker compose ps 显示容器为 healthy127.0.0.1:6379:6379 只允许本机访问;生产不要直接发布到公网。

2.1 验证数据卷真的有效

redis-cli SET tutorial:persist 'before-restart'
docker compose restart redis
redis-cli GET tutorial:persist

重启后仍应返回 before-restart。如果执行 docker compose down --volumes,命名卷会被删除,实验数据也会消失。

3. 看懂关键配置

# 网络与日志
bind 127.0.0.1 10.0.10.15
protected-mode yes
port 6379
tcp-keepalive 300
dir /var/lib/redis
logfile /var/log/redis/redis-server.log

# 持久化与内存
save 900 1
appendonly yes
appendfsync everysec
maxmemory 12gb
maxmemory-policy allkeys-lfu
activedefrag yes
maxclients 10000

everysec 通常是性能和可靠性的折中:主机异常时仍可能丢失约一秒写入。缓存常用 LRU/LFU 淘汰;不能淘汰的数据使用 noeviction,并让应用处理写入失败。

3.1 网络参数

  • bind 决定监听哪些本机地址;应填写环回或私网地址;
  • protected-mode yes 会在缺少明确安全配置时限制访问,但不能代替防火墙;
  • tcp-keepalive 用于发现失效连接;
  • tcp-backlog 需要与内核 somaxconn 一起看。

3.2 内存上限和淘汰策略

策略行为常见用途
noeviction内存满后写命令报错不能静默丢数据的场景
allkeys-lru从所有 key 中近似淘汰最近少用者通用缓存
allkeys-lfu从所有 key 中近似淘汰低频 key热点稳定的缓存
volatile-lru只从设置 TTL 的 key 中淘汰同实例混合缓存和不可淘汰数据时使用,但风险较高

不要等线上内存满了才第一次验证策略。可以在小容量实验实例写入数据,观察 INFO statsevicted_keys 是否增加。

4. 用 ACL 替代“一个万能密码”

config/redis.conf 中增加 ACL 文件路径:

aclfile /usr/local/etc/redis/users.acl

创建 config/users.acl

# users.acl,文件权限应为 0600
user default off
user app on >替换为随机密码 ~app:* +@read +@write -@dangerous
user ops on >替换为随机密码 ~* +@all
chmod 0600 config/users.acl
docker compose restart redis

ACL 启用后,原先无需认证的健康检查也要调整。在 compose.yaml 的 Redis 服务中增加与 ACL 文件一致的实验密码:

environment:
REDISCLI_AUTH: ${REDIS_OPS_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "redis-cli --user ops ping | grep -q PONG"]

将密码写入不提交 Git 的 .env,再执行 docker compose up --detach --wait。生产环境应使用 Secret 管理,环境变量方式仅用于本地实验。

应用用户只能访问自身前缀;运维用户才有管理权限。密码、ACL 和证书不要提交 Git。完成后使用专用用户验证:

export REDISCLI_AUTH='<ops 密码>'
redis-cli --user ops -h 127.0.0.1 ping
redis-cli --user ops CONFIG GET maxmemory

4.1 验证最小权限

配置 ACL 后重启 Redis,再分别验证:

# 应用用户可以访问 app:* key
REDISCLI_AUTH='<app 密码>' redis-cli --user app SET app:test ok
REDISCLI_AUTH='<app 密码>' redis-cli --user app GET app:test

# 应用用户访问其他前缀应返回 NOPERM
REDISCLI_AUTH='<app 密码>' redis-cli --user app GET secret:test

# 应用用户执行危险命令应返回 NOPERM
REDISCLI_AUTH='<app 密码>' redis-cli --user app FLUSHALL

4.2 ACL 配置不生效时怎么查

docker compose logs --tail 100 redis
REDISCLI_AUTH='<ops 密码>' redis-cli --user ops ACL LIST
REDISCLI_AUTH='<ops 密码>' redis-cli --user ops ACL WHOAMI

常见原因是 aclfile 路径未挂载、文件权限不允许 Redis 读取、配置文件未加载或用户规则语法错误。

5. Linux systemd 部署时的目录规范

生产服务器通常将配置、数据、日志和备份分开:

/etc/redis/redis.conf 配置
/etc/redis/users.acl ACL
/var/lib/redis/ RDB/AOF 数据
/var/log/redis/ 日志
/backup/redis/ 本机临时备份,不替代异地备份
sudo install -d -o redis -g redis -m 0750 /var/lib/redis /var/log/redis
sudo install -d -o root -g redis -m 0750 /etc/redis
sudo chmod 0600 /etc/redis/users.acl
sudo systemctl enable --now redis
sudo systemctl status redis --no-pager
sudo journalctl -u redis -n 100 --no-pager

不同发行版的软件包路径可能不同,先通过 systemctl cat redisredis-cli CONFIG GET dir 确认实际配置,不要照抄路径覆盖已有部署。

6. 本章验收与清理

确认以下结果:

  1. docker compose ps 显示 healthy;
  2. Redis 仅绑定本机或私网;
  3. CONFIG GET maxmemory 返回预期值;
  4. 应用 ACL 用户无法执行 FLUSHALL
  5. 容器重启后测试 key 仍存在。

保留环境继续后续章节,或清理:

docker compose down
# 确认不再需要实验数据时才删除卷
docker compose down --volumes