在 VPS 上用 Docker 部署 Redis:缓存、会话管理与高可用配置

为什么选择 Redis?

Redis 是一个开源的(BSD 许可)内存数据结构存储系统,被广泛用作数据库、缓存和消息代理。无论是加速 Web 应用响应、管理用户会话还是实现实时消息队列,Redis 都是基础设施层不可或缺的一环。

Redis 的核心优势

  • 极速性能:基于内存操作,读写延迟通常在微秒级,每秒可处理数十万次请求
  • 📦 丰富数据结构:支持 String、Hash、List、Set、Sorted Set、Bitmap、HyperLogLog、Stream 等
  • 🔐 内置复制与高可用:主从复制 + Redis Sentinel 实现自动故障转移
  • 🛡 数据持久化:RDB 快照 + AOF 日志双保险,重启不丢数据
  • 🔌 生态完善:几乎所有编程语言都有成熟的 Redis 客户端库
  • 🧩 模块化扩展:Redis Stack 提供搜索、JSON、时间序列、图数据库能力

前置条件

在开始之前,确保你拥有:

  • 一台 VPS(推荐配置:1 核 CPU、1 GB RAM、10 GB SSD)
  • Docker 和 Docker Compose(已安装)
  • 基本 Linux 操作知识

💡 提示:Redis 本身非常轻量,即便是 512 MB 内存的 VPS 也能流畅运行。内存大小决定了你可缓存的数据量。

第一步:安装 Docker

如果你的 VPS 尚未安装 Docker,执行以下命令:

# 更新系统
apt update && apt upgrade -y

# 安装 Docker
curl -fsSL https://get.docker.com | bash

# 验证安装
docker --version
docker compose version

第二步:单机 Redis 部署(最简方式)

这是最常用的场景——部署一个独立的 Redis 实例用于缓存加速。

1. 直接运行 Redis 容器

docker run -d \
  --name redis \
  -p 6379:6379 \
  -v redis_data:/data \
  --restart unless-stopped \
  redis:7-alpine

2. 验证运行状态

# 查看容器状态
docker ps | grep redis

# 连接 Redis 测试
docker exec -it redis redis-cli ping
# 应该返回: PONG

# 写入和读取测试
docker exec -it redis redis-cli set hello "世界"
docker exec -it redis redis-cli get hello
# 应该返回: "世界"

3. 查看 Redis 信息

docker exec -it redis redis-cli INFO server

你会看到 Redis 版本、进程 ID、操作系统信息等:

# Server
redis_version:7.2.5
os:Linux
uptime_in_seconds:123
...

第三步:Docker Compose 部署(带密码和持久化)

对于生产环境,我们需要添加密码认证和更精细的配置管理。

创建项目目录

mkdir -p ~/redis && cd ~/redis

创建 docker-compose.yml

version: '3.8'

services:
  redis:
    image: redis:7-alpine
    container_name: redis
    restart: unless-stopped
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
      - ./redis.conf:/usr/local/etc/redis/redis.conf:ro
    command: redis-server /usr/local/etc/redis/redis.conf
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:-changeme}
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-changeme}", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5
    networks:
      - redis_network

  redis-commander:
    image: rediscommander/redis-commander:latest
    container_name: redis-commander
    restart: unless-stopped
    ports:
      - "8081:8081"
    environment:
      - REDIS_HOSTS=local:redis:6379:0:${REDIS_PASSWORD:-changeme}
    depends_on:
      redis:
        condition: service_healthy
    networks:
      - redis_network

volumes:
  redis_data:

networks:
  redis_network:
    driver: bridge

创建 Redis 配置文件

cat > redis.conf << 'EOF'
# Redis 配置文件

# 绑定地址
bind 0.0.0.0

# 保护模式(启用密码后会自动开启)
protected-mode yes

# 端口
port 6379

# 后台运行(Docker 中使用前台模式)
daemonize no

# 持久化:RDB 快照
save 900 1
save 300 10
save 60 10000
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /data

# 持久化:AOF 日志
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 连接限制
maxclients 10000

# 内存管理
maxmemory 256mb
maxmemory-policy allkeys-lru

# 慢查询日志
slowlog-log-slower-than 10000
slowlog-max-len 128

# 安全:密码认证(通过环境变量注入)
# requirepass 在 docker-compose 中通过 command 传入
EOF

创建环境变量文件

cat > .env << 'EOF'
# Redis 密码(请修改为强密码)
REDIS_PASSWORD=$(openssl rand -base64 16)
EOF

⚠️ 安全提示:请务必修改 REDIS_PASSWORD 为强密码。生产环境中建议使用 openssl rand -base64 32 生成随机密码。

启动服务

cd ~/redis
docker compose up -d

验证部署

# 检查服务状态
docker compose ps

# 使用密码连接测试
docker exec -it redis redis-cli -a "$(grep REDIS_PASSWORD .env | cut -d= -f2)" ping

# 查看数据持久化文件
docker exec -it redis ls -la /data/
# 应该看到 dump.rdb 和 appendonly.aof

第四步:Redis 主从复制部署

对于高可用场景,可以部署一主一从(或一主多从)架构。主节点处理写请求,从节点同步数据并处理读请求。

创建主从复制 docker-compose.yml

mkdir -p ~/redis-cluster && cd ~/redis-cluster

创建 docker-compose.yml

version: '3.8'

services:
  redis-master:
    image: redis:7-alpine
    container_name: redis-master
    restart: unless-stopped
    ports:
      - "6379:6379"
    volumes:
      - redis_master_data:/data
      - ./master.conf:/usr/local/etc/redis/redis.conf:ro
    command: redis-server /usr/local/etc/redis/redis.conf
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:-changeme}
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-changeme}", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5
    networks:
      - redis_cluster

  redis-slave:
    image: redis:7-alpine
    container_name: redis-slave
    restart: unless-stopped
    ports:
      - "6380:6379"
    volumes:
      - redis_slave_data:/data
      - ./slave.conf:/usr/local/etc/redis/redis.conf:ro
    command: redis-server /usr/local/etc/redis/redis.conf
    depends_on:
      redis-master:
        condition: service_healthy
    networks:
      - redis_cluster

  redis-sentinel:
    image: redis:7-alpine
    container_name: redis-sentinel
    restart: unless-stopped
    ports:
      - "26379:26379"
    volumes:
      - ./sentinel.conf:/usr/local/etc/redis/sentinel.conf:ro
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    depends_on:
      - redis-master
      - redis-slave
    networks:
      - redis_cluster

volumes:
  redis_master_data:
  redis_slave_data:

networks:
  redis_cluster:
    driver: bridge

创建主节点配置

cat > master.conf << 'EOF'
bind 0.0.0.0
protected-mode yes
port 6379
daemonize no

# 持久化
save 900 1
save 300 10
save 60 10000
rdbcompression yes
dbfilename dump.rdb
dir /data
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

# 内存管理
maxmemory 256mb
maxmemory-policy allkeys-lru

# 主节点密码(用于从节点认证)
requirepass ${REDIS_PASSWORD}

# 主从复制认证密码
masterauth ${REDIS_PASSWORD}
EOF

创建从节点配置

cat > slave.conf << 'EOF'
bind 0.0.0.0
protected-mode yes
port 6379
daemonize no

# 持久化
save 900 1
save 300 10
save 60 10000
rdbcompression yes
dbfilename dump.rdb
dir /data
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

# 内存管理
maxmemory 256mb
maxmemory-policy allkeys-lru

# 密码(需与主节点一致)
requirepass ${REDIS_PASSWORD}
masterauth ${REDIS_PASSWORD}

# 主节点信息
replicaof redis-master 6379

# 只读模式
replica-read-only yes
EOF

创建 Sentinel 配置

cat > sentinel.conf << 'EOF'
port 26379
daemonize no

# 监控主节点(最后一个数字表示判定故障所需票数)
sentinel monitor mymaster redis-master 6379 2

# Sentinel 连接的密码
sentinel auth-pass mymaster ${REDIS_PASSWORD}

# 判定主节点下线的时间(毫秒)
sentinel down-after-milliseconds mymaster 5000

# 故障转移超时时间
sentinel failover-timeout mymaster 60000

# 并行同步数量(故障转移后可同时向多少个从节点发起同步)
sentinel parallel-syncs mymaster 1
EOF

启动集群

cd ~/redis-cluster

# 生成随机密码
echo "REDIS_PASSWORD=$(openssl rand -base64 32)" > .env

# 启动所有服务
docker compose up -d

# 等待节点就绪
sleep 5

验证主从复制

# 查看主节点角色
docker exec -it redis-master redis-cli -a "$(grep REDIS_PASSWORD .env | cut -d= -f2)" ROLE
# 输出: master
#       0
#       (list of slaves)

# 查看从节点角色
docker exec -it redis-slave redis-cli -a "$(grep REDIS_PASSWORD .env | cut -d= -f2)" ROLE
# 输出: slave
#       redis-master
#       6379
#       ...

# 在主节点写入数据
docker exec -it redis-master redis-cli -a "$(grep REDIS_PASSWORD .env | cut -d= -f2)" set site "navbox.com.cn"

# 在从节点读取(验证复制)
docker exec -it redis-slave redis-cli -a "$(grep REDIS_PASSWORD .env | cut -d= -f2)" get site
# 应该返回: "navbox.com.cn"

# 确认从节点为只读(写入应失败)
docker exec -it redis-slave redis-cli -a "$(grep REDIS_PASSWORD .env | cut -d= -f2)" set test "fail"
# 应该返回: (error) READONLY You can't write against a read only replica.

验证 Sentinel 自动故障转移

# 查看 Sentinel 状态
docker exec -it redis-sentinel redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
# 输出: 192.168.x.x(主节点 IP)
#       6379

# 模拟主节点故障(停止主节点)
docker stop redis-master

# 等待 10 秒让 Sentinel 检测到故障
sleep 10

# 查看新的主节点(Sentinel 已自动将从节点提升为主节点)
docker exec -it redis-sentinel redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
# 输出: 192.168.x.x(从节点 IP,已提升为主)
#       6379

# 恢复原主节点
docker start redis-master

# 它会自动成为新主节点的从节点
sleep 5
docker exec -it redis-master redis-cli -a "$(grep REDIS_PASSWORD .env | cut -d= -f2)" ROLE
# 输出: slave(原主节点已降级为从节点)

第五步:部署 Redis Stack(扩展模块)

Redis Stack 是 Redis 的增强发行版,内置了 RediSearch、RedisJSON、RedisTimeSeries、RedisBloom 等模块。

docker run -d \
  --name redis-stack \
  -p 6379:6379 \
  -p 8001:8001 \
  -v redis_stack_data:/data \
  --restart unless-stopped \
  redis/redis-stack:latest

8001 端口是 RedisInsight Web UI,可以在浏览器中管理 Redis:

http://你的VPS_IP:8001

验证扩展模块是否加载:

docker exec -it redis-stack redis-cli MODULE LIST
# 应该看到 search、json、timeseries、bf 等模块

Redis Stack 功能演示

# JSON 操作
docker exec -it redis-stack redis-cli JSON.SET user:1 $ '{"name":"Navbox","url":"navbox.com.cn","tags":["AI","tools","setup"]}'
docker exec -it redis-stack redis-cli JSON.GET user:1
# 输出: {"name":"Navbox","url":"navbox.com.cn","tags":["AI","tools","setup"]}

# 全文搜索
docker exec -it redis-stack redis-cli FT.CREATE idx ON HASH PREFIX 1 doc: SCHEMA title TEXT content TEXT
docker exec -it redis-stack redis-cli HSET doc:1 title "Redis 教程" content "这是一个在 VPS 上部署 Redis 的教程"
docker exec -it redis-stack redis-cli FT.SEARCH idx "Redis 教程"
# 返回匹配的文档

第六步:配置 Nginx 反向代理 + HTTPS(推荐)

如果希望远程访问 Redis Commander 或 RedisInsight,建议通过 Nginx 反向代理加 HTTPS 访问。

sudo nano /etc/nginx/sites-available/redis
server {
    listen 80;
    server_name redis.你的域名.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name redis.你的域名.com;

    ssl_certificate /etc/letsencrypt/live/redis.你的域名.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/redis.你的域名.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8081;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

启用配置并申请证书:

sudo ln -s /etc/nginx/sites-available/redis /etc/nginx/sites-enabled/
sudo certbot --nginx -d redis.你的域名.com
sudo nginx -t && sudo systemctl reload nginx

常用管理命令

# 查看 Redis 内存使用
docker exec redis redis-cli INFO memory | grep used_memory_human

# 查看客户端连接
docker exec redis redis-cli CLIENT LIST

# 查看所有 Key
docker exec redis redis-cli KEYS '*'

# 清空所有数据(生产环境慎用!)
docker exec redis redis-cli FLUSHALL

# 查看 Redis 运行状态
docker exec redis redis-cli INFO stats

# 实时监控 Redis 命令
docker exec redis redis-cli MONITOR

# 手动触发 RDB 快照
docker exec redis redis-cli SAVE

# 手动触发 AOF 重写
docker exec redis redis-cli BGREWRITEAOF

# 更新 Redis 版本
docker compose pull redis
docker compose up -d --force-recreate redis

调优建议

1. 内存优化

# 查看内存碎片率
docker exec redis redis-cli INFO memory | grep mem_fragmentation_ratio

# 设置内存上限(已在配置文件中设置)
# maxmemory 256mb
# maxmemory-policy allkeys-lru

# 不同淘汰策略说明:
# - allkeys-lru: 淘汰最近最少使用的 key(推荐)
# - allkeys-lfu: 淘汰最不经常使用的 key
# - volatile-lru: 仅淘汰设置了 TTL 的 key
# - noeviction: 不淘汰,写入时报错

2. 调整 Linux 内核参数

# 优化网络性能
cat >> /etc/sysctl.conf << 'EOF'

# Redis 优化参数
net.core.somaxconn = 65535
vm.overcommit_memory = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_timestamps = 1
EOF

# 立即生效
sysctl -p

# 禁用透明大页(防止延迟抖动)
echo never > /sys/kernel/mm/transparent_hugepage/enabled

3. 使用 Redis 集群(生产环境推荐)

当单机内存不足或需要更高吞吐量时,使用 Redis Cluster 实现数据分片:

# 创建 6 个节点的集群目录
for i in 7000 7001 7002 7003 7004 7005; do
  mkdir -p ~/redis-cluster/$i
done

# 用 docker-compose 搭建 Redis Cluster(此处简化,详见官方文档)

安全加固

1. 禁止远程访问

如果 Redis 仅供本地应用使用,不要暴露 6379 端口:

# docker-compose.yml 中移除 ports 映射
# 仅让应用容器通过内部网络访问
networks:
  - redis_network

2. 防火墙规则

# 仅允许内网 IP 访问 Redis
ufw allow from 10.0.0.0/8 to any port 6379
ufw allow from 172.16.0.0/12 to any port 6379
ufw allow from 192.168.0.0/16 to any port 6379

3. 使用 ACL 控制(Redis 6+)

# 创建只读用户
docker exec -it redis redis-cli ACL SETUSER reader on >'your_password' ~* +@read

# 创建特定 Key 空间的用户
docker exec -it redis redis-cli ACL SETUSER app_user on >'app_password' ~cache:* +@all

# 查看 ACL 规则
docker exec -it redis redis-cli ACL LIST

常见问题

Q: Redis 容器不断重启怎么办?

A: 检查日志:

docker logs redis

常见原因:① 配置文件格式错误;② 端口被占用;③ 数据目录权限问题。

Q: 如何备份 Redis 数据?

A: 两种方式:

# 方式一:手动触发并复制 RDB 文件
docker exec redis redis-cli SAVE
docker cp redis:/data/dump.rdb ./backup_$(date +%Y%m%d).rdb

# 方式二:AOF 日志(已启用,自动持久化)
docker cp redis:/data/appendonly.aof ./backup_$(date +%Y%m%d).aof

Q: 如何恢复 Redis 数据?

A: 将备份的 RDB 或 AOF 文件放回数据卷:

# 停止 Redis
docker compose down

# 替换数据文件
cp ./backup_20260604.rdb ~/redis/redis_data/dump.rdb

# 重启 Redis
docker compose up -d

Q: 客户端连不上 Redis?

A: 检查以下几点:

  1. Redis 是否正常运行:docker ps | grep redis
  2. 密码是否正确:配置文件中的 requirepass
  3. 防火墙是否放行 6379 端口
  4. bind 0.0.0.0 是否已配置
  5. protected-mode 是否已关闭(启用密码后会自动关闭保护模式限制)

Q: 如何监控 Redis 性能?

A: 使用以下工具:

# 内置监控
docker exec redis redis-cli INFO all  # 查看全部指标
docker exec redis redis-cli --stat    # 实时统计

# RedisInsight 可视化(Redis Stack 自带)
# 访问 http://你的VPS_IP:8001

# Prometheus 集成(Grafana 展示)
# 使用 redis_exporter 导出指标
docker run -d --name redis-exporter \
  -p 9121:9121 \
  oliver006/redis_exporter \
  -redis.addr redis://你的VPS_IP:6379 \
  -redis.password 你的密码

总结

通过 Docker,你可以在 5 分钟内完成 Redis 的单机部署,并在 15 分钟内搭建一套主从复制 + Sentinel 高可用集群。Redis 带来的性能提升立竿见影——数据库查询从几十毫秒降至微秒级响应,Web 应用吞吐量提升数倍。

快速参考

场景推荐方案内存需求
个人项目/博客缓存单机 Redis(第2步)128 MB
生产环境 Web 应用Docker Compose + 密码 + 持久化(第3步)256 MB
高可用需求主从复制 + Sentinel(第4步)512 MB
高级数据结构Redis Stack(第5步)512 MB

动手试试吧!在你的 VPS 上部署 Redis,让应用体验飞一般的速度。

这篇文章对你有帮助吗?