在 1 核 1G(1 vCPU, 1GB RAM)的服务器上同时部署 MySQL 和 Redis,属于典型的“资源极度受限”场景。MySQL 默认配置通常远超此限制,而 Redis 虽然轻量,但两者争抢内存和 CPU 极易导致 OOM(内存溢出)或高延迟。
以下是针对该环境的核心优化策略,按优先级排序:
1. 内存分配与隔离(最关键)
1GB 内存非常宝贵,必须严格划分。
- Redis 内存限制:
- Redis 是单线程处理命令的,但内存占用大。建议将
maxmemory设置为 256MB – 300MB。 - 保留至少 200-300MB 给操作系统缓存和其他进程。
- 设置淘汰策略:
maxmemory-policy allkeys-lru(所有键空间下最近最少使用),防止内存爆满。 - 开启压缩:如果存储的是字符串类型,Redis 会自动压缩,无需额外配置。
- Redis 是单线程处理命令的,但内存占用大。建议将
- MySQL 内存限制:
- MySQL 的 InnoDB Buffer Pool 是最大开销来源。
- 修改
my.cnf(或mysql.cnf):[mysqld] # 总内存 1G,减去 OS 预留 300M,减去 Redis 预留 300M,留给 MySQL 约 400M innodb_buffer_pool_size = 256M # 关键:关闭不必要的内存消耗组件 table_open_cache = 200 thread_cache_size = 8 sort_buffer_size = 2M read_rnd_buffer_size = 2M join_buffer_size = 2M # 禁用不常用的日志以节省 IO 和内存(视业务需求而定) # sync_binlog = 0 (若数据安全性要求不高,可牺牲少量一致性换取性能) - 注意:不要开启
query_cache,它在现代 MySQL 版本中不仅无效且消耗内存。
2. 存储引擎与表结构优化
- 强制使用 InnoDB:确保所有表都使用 InnoDB 引擎,避免 MyISAM(MyISAM 在并发下锁表更严重,且缓冲池管理不如 InnoDB 灵活)。
- 精简索引:
- 1 核 CPU 无法承受过多的索引维护开销。
- 只为核心查询字段建立索引,删除冗余索引。
- 避免在大字段(如 TEXT/BLOB)上建立索引。
- 小表设计:尽量将大表拆分,或者对于非核心数据使用简单的扁平化存储(如 JSON 字段),减少 Join 操作(Join 极其消耗 CPU)。
3. 应用层架构调整(规避瓶颈的核心)
在硬件受限的情况下,软件架构优化比硬件调优更有效。
- 读写分离/缓存优先:
- 利用 Redis 缓存热点数据(如用户信息、配置项、Session),让 MySQL 只负责写操作和复杂统计。
- 设置合理的 TTL(过期时间),减少数据库读取压力。
- 批量操作:
- 应用层尽量将多次 SQL 合并为一次执行(Batch Insert/Update),减少网络往返和上下文切换。
- 异步处理:
- 对于非实时任务(如发送通知、生成报表),通过消息队列(甚至可以用 Redis List 模拟简易队列)异步处理,避免阻塞主线程。
4. 操作系统与内核参数调优
Linux 内核参数对 I/O 和连接数有巨大影响。
- 增加 Swap(虚拟内存):
- 虽然 Swap 会降低速度,但在 1G 内存下,没有 Swap 会导致服务直接崩溃(OOM Killer)。
- 建议创建 1GB – 2GB 的 Swap 分区或文件。
- 调整
vm.swappiness:建议设为10,让系统优先使用物理内存,只有实在不够时才用 Swap。 - 命令示例:
echo "vm.swappiness=10" >> /etc/sysctl.conf && sysctl -p
- 文件描述符限制:
- MySQL 和 Redis 在高并发下需要大量文件句柄。
- 修改
/etc/security/limits.conf:* soft nofile 65535 * hard nofile 65535 root soft nofile 65535 root hard nofile 65535
- I/O 调度器:
- 如果是 SSD,建议使用
deadline或none调度器;如果是机械硬盘,使用cfq。 - 检查当前调度器:
cat /sys/block/sda/queue/scheduler
- 如果是 SSD,建议使用
5. 监控与运维策略
- 开启慢查询日志:
- 在 MySQL 中开启
slow_query_log,阈值设为 1s 或 2s,定期分析并优化最慢的 SQL。
- 在 MySQL 中开启
- 监控工具:
- 安装轻量级监控(如 Prometheus Node Exporter + Grafana,或者简单的
htop+watch)。 - 重点监控指标:
MemAvailable(可用内存)、SwapUsed、InnoDB Page Read Rate、Redis Hit Rate。
- 安装轻量级监控(如 Prometheus Node Exporter + Grafana,或者简单的
- 定时清理:
- 定期清理 MySQL 的慢查询日志、错误日志,防止磁盘占满。
- 定期备份数据到外部存储(如对象存储 S3),释放本地空间。
总结配置清单参考
Redis (redis.conf)
maxmemory 256mb
maxmemory-policy allkeys-lru
timeout 300
tcp-keepalive 300
save "" # 如果数据允许丢失,关闭持久化可极大提升性能(生产环境慎用)
# 或者保留 AOF,但设置为每秒同步
appendonly yes
appendfsync everysec
MySQL (my.cnf)
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
port=3306
user=mysql
# 核心内存控制
innodb_buffer_pool_size = 256M
innodb_log_file_size = 64M
innodb_flush_log_at_trx_commit = 2 # 牺牲一点点数据安全性换取写入性能
# 连接与缓存
table_open_cache = 200
thread_cache_size = 8
sort_buffer_size = 2M
read_rnd_buffer_size = 2M
join_buffer_size = 2M
# 其他
skip-name-resolve # 禁止 DNS 解析,加快连接速度
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
最终建议
如果经过上述优化后,业务高峰期依然频繁出现超时或卡顿,说明 1 核 1G 确实无法满足当前的业务负载量。此时最经济的方案是:
- 升级配置:将服务器升级到 2 核 2G(成本增加很少,性能提升显著)。
- 云数据库:将 MySQL 迁移到云厂商的 RDS(按量付费),本地仅保留 Redis 和应用代码。
- 容器化隔离:使用 Docker Compose 或 K8s 限制资源配额,防止一个服务把另一个吃光。
轻量云Cloud