0

Docker LNMP Redis缓存配置:从安装到实战的完整指南

2026.05.23 | youres | 18次围观

前言

用Docker跑LNMP环境的人不少,但很多人装完就完事了——Nginx、MySQL、PHP-FPM跑起来,网站能访问就收工。殊不知,少了Redis这一层缓存,你的网站在面对真实流量时,数据库压力会非常大。今天这篇文章,手把手教你在Docker LNMP环境中集成Redis缓存,让网站响应速度和并发能力上一个台阶。

为什么LNMP需要加Redis

LNMP架构中,PHP每次处理请求都要查MySQL数据库。访问量一大,数据库就成了瓶颈。Redis作为内存级缓存,能把热点数据放在内存里,PHP直接从Redis读数据,不再每次都打数据库。

实际效果:

  • 数据库查询量减少70%~90%
  • 页面响应时间从几百毫秒降到几十毫秒
  • MySQL并发连接数压力大幅降低
  • 整体QPS提升明显

环境准备

在开始之前,确保你已经有一个跑起来的Docker LNMP环境。如果还没有,可以参考之前的Docker部署LNMP环境教程搭建基础环境。

本文基于以下环境:

  • 操作系统:Ubuntu 20.04/22.04
  • Docker + Docker Compose
  • 已有的LNMP容器:Nginx + MySQL 8.0 + PHP 8.x-FPM

第一步:修改docker-compose.yml添加Redis服务

在你的docker-compose.yml文件中,追加Redis服务定义:

version: '3.8'
services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./www:/var/www/html
    depends_on:
      - php

  php:
    image: php:8.2-fpm
    volumes:
      - ./www:/var/www/html
    depends_on:
      - mysql
      - redis

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: your_password
      MYSQL_DATABASE: your_database
    volumes:
      - mysql_data:/var/lib/mysql

  redis:
    image: redis:7-alpine
    container_name: lnmp-redis
    restart: always
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    command: redis-server --appendonly yes --requirepass your_redis_password

volumes:
  mysql_data:
  redis_data:

几个关键配置说明:

  • appendonly yes:开启AOF持久化,Redis重启后数据不丢失
  • requirepass:设置访问密码,不要在生产环境裸奔
  • redis_data:数据持久化到Docker卷,容器重建数据不丢
  • alpine:用alpine版镜像,体积小,启动快

第二步:PHP安装Redis扩展

PHP默认不带Redis扩展,需要手动安装。推荐做法是自定义PHP镜像:

创建文件 Dockerfile-php

FROM php:8.2-fpm
RUN apt-get update && apt-get install -y \
    libpng-dev \
    libzip-dev \
    && docker-php-ext-install pdo_mysql mysqli gd zip \
    && pecl install redis \
    && docker-php-ext-enable redis

然后在docker-compose.yml中,把PHP服务改成:

  php:
    build:
      context: .
      dockerfile: Dockerfile-php
    volumes:
      - ./www:/var/www/html

重新构建并启动:

docker-compose build php
docker-compose up -d

验证Redis扩展是否安装成功:

docker exec lnmp-php php -m | grep redis

输出 redis 就说明OK了。

第三步:PHP中连接Redis并使用

建一个测试文件 www/redis_test.php

<?php
$redis = new Redis();
$redis->connect('redis', 6379);
$redis->auth('your_redis_password');

// 写入测试
$redis->set('test_key', 'Hello Redis in Docker LNMP', 3600);
echo $redis->get('test_key');

// 测试性能
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
    $redis->set("bench_$i", "value_$i");
}
$end = microtime(true);
echo "\n写入10000条耗时: " . round(($end - $start) * 1000, 2) . "ms";
?>

访问 http://your-server/redis_test.php,如果能看到输出就说明Redis连接正常。

第四步:实战配置——数据库查询缓存

光能连Redis还不够,关键是把缓存用到实际业务里。下面是一个通用的数据库查询缓存封装:

<?php
class RedisCache {
    private $redis;
    private $prefix = 'cache:';
    private $ttl = 3600; // 默认缓存1小时

    public function __construct() {
        $this->redis = new Redis();
        $this->redis->connect('redis', 6379);
        $this->redis->auth('your_redis_password');
    }

    // 获取缓存,缓存未命中则查询数据库并写入
    public function remember($key, $callback, $ttl = null) {
        $cacheKey = $this->prefix . md5($key);
        $data = $this->redis->get($cacheKey);
        
        if ($data !== false) {
            return json_decode($data, true);
        }

        $result = $callback();
        $this->redis->setex($cacheKey, $ttl ?? $this->ttl, json_encode($result));
        return $result;
    }

    // 手动清除缓存
    public function forget($key) {
        $this->redis->del($this->prefix . md5($key));
    }

    // 按前缀批量清除
    public function flushByPrefix($prefix) {
        $keys = $this->redis->keys($this->prefix . $prefix . '*');
        if (!empty($keys)) {
            $this->redis->del($keys);
        }
    }
}

// 使用示例
$cache = new RedisCache();

// 文章列表缓存
$articles = $cache->remember('article_list_page_1', function() {
    global $pdo;
    $stmt = $pdo->query("SELECT * FROM articles ORDER BY id DESC LIMIT 20");
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
});

// 数据更新后清除缓存
$cache->forget('article_list_page_1');
?>

第五步:Session存储到Redis

PHP默认把Session存到文件,多容器环境下不好共享。改成Redis存储很简单:

在PHP配置中添加(php.ini 或代码中设置):

session.save_handler = redis
session.save_path = "tcp://redis:6379?auth=your_redis_password"

或者在你的PHP入口文件中动态设置:

<?php
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://redis:6379?auth=your_redis_password');
session_start();
?>

这样Session就存在Redis里了,多台PHP-FPM容器也能共享Session,方便后续做负载均衡。

Redis常用缓存策略

根据不同场景选择合适的缓存策略:

1. 主动缓存(Cache Aside)

最常用的模式。先查缓存,没有再查数据库,查到后写入缓存。上面的remember方法就是这个模式。适合读多写少的场景。

2. 过期时间策略

给缓存设TTL,到期自动失效。不同数据设不同过期时间:

  • 热点文章列表:5~15分钟
  • 用户信息:30分钟
  • 配置项:1~2小时
  • 统计数据:可适当延长

3. 主动失效

数据更新时主动删缓存,保证一致性。上面示例中的forget方法就是这样用的。

性能调优建议

Redis配置调优:

  • maxmemory:设置最大内存限制,防止Redis吃满内存。建议设为系统总内存的50%~70%,例如 --maxmemory 2gb
  • maxmemory-policy:内存满时的淘汰策略,推荐 allkeys-lru(删除最近最少使用的key)
  • tcp-keepalive:保持TCP连接,避免频繁重建连接,设为60秒
  • timeout 0:不主动断开空闲连接

docker-compose.yml中Redis的command改为:

command: >
  redis-server
  --appendonly yes
  --requirepass your_redis_password
  --maxmemory 2gb
  --maxmemory-policy allkeys-lru
  --tcp-keepalive 60

常见问题排查

1. PHP连不上Redis

检查容器网络:确保PHP容器和Redis容器在同一个Docker网络中。docker-compose默认会把所有服务放到同一个网络,通常不会有问题。如果连不上,检查container_name和连接地址是否一致。

2. Redis重启后数据丢失

确认appendonly已开启,且数据卷redis_data正常挂载。可以用 docker volume inspect 检查卷挂载情况。

3. 内存占用持续增长

设置maxmemory和maxmemory-policy,让Redis在内存满时自动淘汰旧数据。同时检查是否有设置过期时间的key没有正确设置TTL。

总结

在Docker LNMP环境中加入Redis缓存,改动不大但效果明显。核心就三步:加Redis服务、装PHP扩展、写缓存逻辑。做好持久化和内存管理,生产环境跑起来也很稳。如果你的网站已经开始有并发压力,Redis这一步建议尽早加上。

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论
881文章数 0评论数
作者其它文章