2核2G的服务器安装Docker并运行MySQL与Redis需要优化哪些参数?

在 2 核 CPU、2GB 内存的服务器上同时运行 Docker、MySQL 和 Redis,属于典型的资源受限环境。如果不进行针对性优化,极易出现内存溢出(OOM)导致服务被系统杀死,或者磁盘 I/O 瓶颈。

以下是针对该配置的关键优化方案,分为Docker 引擎层、操作系统层、MySQL 层和Redis 层四个维度:

1. Docker 引擎层优化

Docker 守护进程本身会占用一定内存,且容器默认的资源限制需要手动收紧。

  • 限制 Docker 守护进程内存:
    编辑 /etc/docker/daemon.json,限制 Docker 自身使用的内存上限,防止其挤占应用内存。

    {
      "default-ulimits": {
        "nofile": { "Name": "nofile", "Hard": 65535, "Soft": 65535 }
      },
      "log-driver": "json-file",
      "log-opts": {
        "max-size": "50m",
        "max-file": "3"
      }
    }

    注:日志文件必须限制大小,否则 2G 内存很快会被日志撑爆。

  • 设置容器资源限制(Cgroups):
    在启动 MySQL 和 Redis 容器时,务必通过 --memory 和 --cpus 参数硬限制资源,不要使用默认值(无限制)。

    推荐启动命令示例:

    # MySQL: 限制内存 800MB,CPU 1.0 核
    docker run -d --name mysql 
      --memory="800m" 
      --memory-swap="800m" 
      --cpus="1.0" 
      -e MYSQL_ROOT_PASSWORD=your_password 
      -v /data/mysql:/var/lib/mysql 
      mysql:8.0
    
    # Redis: 限制内存 400MB,CPU 0.5 核
    docker run -d --name redis 
      --memory="400m" 
      --memory-swap="400m" 
      --cpus="0.5" 
      redis:alpine

    计算逻辑:2G 总内存 – Docker 开销 (约 200M) – 预留给宿主机 (约 200M) = 1.6G 可用。MySQL 给 800M,Redis 给 400M,剩余 400M 作为缓冲。

2. 操作系统层优化

Linux 内核参数对数据库性能影响巨大,特别是 Swap 交换分区。

  • 禁用或严格限制 Swap(关键):
    在 2G 内存环境下,一旦触发 Swap,MySQL/Redis 的随机读写延迟会剧增,导致服务假死。

    • 方案 A(推荐):如果可能,完全关闭 Swap (swapoff -a)。因为一旦 OOM,直接杀掉进程比卡顿要好控制。
    • 方案 B(保守):如果必须保留 Swap,调整 vm.swappiness 为极低值(如 1),让系统优先使用物理内存。
      # 临时生效
      sysctl vm.swappiness=1
      # 永久生效
      echo "vm.swappiness=1" >> /etc/sysctl.conf
  • 调整 TCP/IP 参数:
    增加连接队列长度,防止高并发下连接重置。

    # 临时生效
    sysctl -w net.core.somaxconn=1024
    sysctl -w net.ipv4.tcp_max_syn_backlog=2048
  • 文件系统挂载选项:
    如果是云服务器的数据盘,挂载时添加 noatime 参数,减少磁盘写入元数据的开销。

    mount -o remount,noatime /dev/sdaX /mnt/data

3. MySQL 深度优化

MySQL 是内存大户,默认配置通常是为多核大内存设计的,必须大幅调低。

  • 核心参数修改 (my.cnf):
    建议将配置文件放在 /etc/my.cnf 或 Docker 卷映射的配置文件中。

    [mysqld]
    # 基础设置
    port = 3306
    datadir = /var/lib/mysql
    
    # 内存相关 (最关键)
    innodb_buffer_pool_size = 400M  # 建议设为可用内存的 25%-30%,此处留 400M 给 OS 和其他进程
    innodb_log_file_size = 64M      # 减小日志文件大小,加快崩溃恢复
    innodb_flush_method = O_DIRECT  # 绕过 OS 缓存,避免双重缓存浪费内存
    
    # 连接与线程
    max_connections = 100           # 根据业务量适当调整,2G 内存不宜过大
    thread_cache_size = 10          # 减少线程创建开销
    
    # 其他优化
    query_cache_type = 0            # MySQL 8.0+ 已移除 Query Cache,旧版本建议关闭
    skip-name-resolve               # 禁止 DNS 解析,提升连接速度
  • 字符集与存储引擎:
    确保使用 utf8mb4 但注意索引大小。InnoDB 是唯一推荐的引擎。

4. Redis 深度优化

Redis 依赖内存速度,需防止内存碎片和持久化带来的抖动。

  • 核心参数修改 (redis.conf):

    # 内存限制
    maxmemory 400mb                 # 必须与 Docker 启动时的 --memory 保持一致或略小
    maxmemory-policy allkeys-lru    # 当内存满时,淘汰最近最少使用的键,防止 OOM
    
    # 持久化策略 (AOF vs RDB)
    # 2G 服务器建议主要用 RDB 快照,AOF 频率设低或关闭,减少 IO 压力
    save 900 1                      # 15 分钟有 1 个 key 变化则保存
    appendonly no                   # 生产环境若对实时性要求不高,可关闭 AOF 以节省 IO
    aof-load-truncated yes
    
    # 网络
    tcp-backlog 511
    timeout 300
  • 内存碎片处理:
    开启自动碎片整理(Redis 4.0+):

    activedefrag yes
    active-dfrag-memory-limit 128mb

5. 监控与兜底策略

在如此小的资源池上,“预防”优于“修复”。

  1. 配置 OOM Killer 保护:
    虽然我们无法阻止 OOM,但可以观察日志。如果频繁发生,说明分配给容器的内存总和过高,需进一步压缩。

    dmesg | grep -i "killed process"
  2. 监控工具:
    安装轻量级监控(如 cAdvisor 或简单的 Shell 脚本),监控内存使用率。一旦超过 85% 立即报警。
  3. 备份策略:
    由于资源紧张,不要在高峰期执行全量备份。建议使用 mysqldump 配合 --single-transaction 并在低峰期运行,或者利用 MySQL 的 Binlog 增量备份。

总结配置清单

组件 关键动作 推荐数值/参数
OS 关闭 Swap 或降低优先级 vm.swappiness=1 或 swapoff
Docker 限制容器资源 MySQL: 800M RAM, 1.0 CPU; Redis: 400M RAM, 0.5 CPU
MySQL 缩小 Buffer Pool innodb_buffer_pool_size = 400M
Redis 设置最大内存策略 maxmemory 400mb, maxmemory-policy allkeys-lru
通用 限制日志大小 max-size: 50m, max-file: 3

最后建议:如果业务流量稍有增长,2 核 2G 将难以维持稳定。建议在初期就规划好升级路径(如升级到 4 核 4G),或者考虑将 MySQL 迁移到云数据库(RDS),本地仅保留 Redis 和应用代码,以减轻本地磁盘和内存压力。