奋斗
努力

1核1G服务器上MySQL和Redis启动后系统负载很高,常见原因有哪些?

云计算

在1核1G的极低配服务器上,MySQL 和 Redis 同时运行后系统负载(Load Average)持续偏高(如 > 1.0 或远高于 CPU 核心数),是典型资源严重不足的表现。常见原因可从资源竞争、配置不当、行为异常、系统层面四个维度分析:


🔹 一、内存严重不足(最核心原因)

  • 物理内存仅1GB,但 MySQL + Redis 默认配置远超此限制
    • MySQL:innodb_buffer_pool_size 默认可能达 128MB~256MB(甚至更高),加上连接缓冲、排序缓存等,单个连接可能占用几MB;若并发连接数 > 10,极易触发 OOM。
    • Redis:默认不设 maxmemory,会无限使用内存;即使设了,若数据量大或存在内存碎片,也可能频繁触发淘汰/驱逐,加剧压力。
  • 后果
    • 频繁触发 Linux OOM Killer(杀进程)或 swap 交换(磁盘 I/O 爆增 → load飙升);
    • free -h 显示 available 内存接近 0,si/so(swap in/out)持续非零(vmstat 1 可见);
    • dmesg | grep -i "killed process" 可能看到 MySQL/Redis 被 OOM Kill。

对策
→ 严格限制内存:

  • MySQL:innodb_buffer_pool_size = 64M(不超过总内存 50%),关闭 query_cache(已弃用),调小 tmp_table_size/max_connections=32
  • Redis:必须配置 maxmemory 256mb + maxmemory-policy allkeys-lru
    → 禁用 swap(sudo swapoff -a)或彻底移除 swap 分区(避免假性“可用内存”导致更差性能)。

🔹 二、CPU 瓶颈(1核不堪重负)

  • MySQL 复杂查询、全表扫描、无索引 JOIN、慢日志未优化;
  • Redis 执行耗时命令:KEYS *FLUSHALL、大集合遍历(SMEMBERS)、Lua 脚本阻塞;
  • 持久化压力:
    • MySQL 的 innodb_flush_log_at_trx_commit=1 + 高频写入 → 每次事务刷盘;
    • Redis 的 save(RDB)或 aof_fsync=always 在 1核下 fork 子进程(bgsave/bgrewriteaof)会卡主进程,且 fork 本身在内存紧张时极慢(copy-on-write 开销大)。

对策
→ 关闭非必要持久化:Redis 设 save ""(禁用 RDB),AOF 设 appendonly noappendfsync everysec
→ MySQL 关键参数:innodb_flush_log_at_trx_commit=2(牺牲少量安全性换性能),sync_binlog=0(如无需主从);
→ 用 top -H / htop 查看线程级 CPU 占用,定位热点线程(如 mysqld 的 query thread、redis 的 io-thread)。


🔹 三、I/O 瓶颈(尤其机械盘或云盘性能差)

  • 小内存下大量 swap I/O;
  • MySQL redo log、binlog、数据文件随机读写;
  • Redis RDB/AOF 写入 + fsync;
  • 云服务器(如早期入门级 ECS)共享磁盘 IOPS 极低(< 100 IOPS),iostat -x 1 显示 %util ≈ 100%await > 100ms。

对策
→ 确保数据库目录在本地 SSD(非网络盘);
→ MySQL 日志与数据目录分离(如 /var/lib/mysql/var/log/mysql 不同磁盘);
→ Redis 使用 appendfsync everysec + no-appendfsync-on-rewrite yes


🔹 四、配置与行为陷阱

组件 常见问题 风险
MySQL max_connections=151(默认)→ 实际连接数超限,排队等待;table_open_cache 过大 → 文件描述符耗尽 Too many connectionsCan't create threadopen files limit exceeded
Redis 未设 timeout 300 → 客户端空闲连接堆积;tcp-keepalive 0 → 连接泄漏 连接数暴涨,内存/CPU 持续占用
共性 未限制服务启动用户资源(如 systemd 未设 MemoryLimit, CPUQuota 进程无约束抢占全部资源

对策
→ MySQL:max_connections=32table_open_cache=64,检查 ulimit -n(建议 ≥ 1024);
→ Redis:timeout 300tcp-keepalive 60
→ systemd 服务加资源限制(示例):

# /etc/systemd/system/mysqld.service.d/limits.conf
[Service]
MemoryLimit=768M
CPUQuota=80%

🔹 五、其他易忽略因素

  • 日志狂刷:MySQL slow_query_log=ON + long_query_time=0,或 Redis loglevel verbose → 磁盘写满 + I/O 饱和;
  • 监控/采集X_X:如 node_exportermysqld_exporter 频繁采样加重负载;
  • 时间同步服务chronydntpd 在低配下争抢 CPU;
  • 恶意扫描/攻击:Redis 未绑定 127.0.0.1 或弱密码被X_X;MySQL 暴露公网遭暴力破解。

✅ 快速诊断命令:

# 1. 内存与 swap
free -h && cat /proc/meminfo | grep -E "MemAvailable|SwapTotal|SwapFree"

# 2. I/O 压力
iostat -x 1 3 && iotop -oP  # 查看实际 I/O 进程

# 3. 进程级资源
top -b -n1 | head -20
ps aux --sort=-%cpu,-%mem | head -15

# 4. MySQL 状态
mysql -e "SHOW PROCESSLIST;"  # 查看长连接/慢查询
mysql -e "SHOW STATUS LIKE 'Threads_%';"  # Threads_connected, Threads_running

# 5. Redis 状态
redis-cli info memory | grep -E "used_memory|maxmemory|mem_fragmentation_ratio"
redis-cli info clients | grep "connected_clients"

✅ 终极建议(1核1G 场景)

不要同时运行 MySQL + Redis —— 这是根本矛盾。
✔️ 推荐方案

  • 仅需缓存 → 用 Redis(关持久化,maxmemory 256M);
  • 仅需关系存储 → 用 MySQL(极致精简配置);
  • 两者都需 → 升级到 2核2G 起步,或改用轻量替代:
    • MySQL → LiteSpeed MySQL 或 MariaDB with Aria engine;
    • Redis → KeyDB(多线程,1核利用率更高)或 Dragonfly(更省内存);
  • 开发/测试环境 → 直接用 SQLite(文件型)+ 内存缓存(如 Python functools.lru_cache)。

如需进一步优化,可提供:
cat /proc/meminfo 输出;
mysql --versionredis-server --version
top 截图或 ps aux --sort=-%cpu | head -10 结果;
我可帮你定制最小化配置文件 👇

是否需要我为你生成一份 1核1G 下安全共存的 MySQL + Redis 最小化配置模板

未经允许不得转载:云服务器 » 1核1G服务器上MySQL和Redis启动后系统负载很高,常见原因有哪些?