奋斗
努力

小型项目用1核1G服务器部署MySQL和Redis,如何优化避免性能瓶颈?

云计算

在 1核1G 的极小规格服务器上同时部署 MySQL 和 Redis,确实面临严峻挑战(内存严重受限、CPU单核易争抢、I/O 瓶颈突出)。这不是推荐的生产配置,仅适用于学习、本地测试或极低流量(<10 QPS)的个人项目。 但若必须如此,可通过「严控资源、极致精简、错峰协同、主动防御」四原则进行深度优化。以下是具体、可落地的优化方案:


⚠️ 前提:安全底线(必须先做!)

  • 禁用 swap(或设为 0)sudo sysctl vm.swappiness=0 + /etc/sysctl.conf 永久生效
    → 避免内存不足时频繁 swap 导致 MySQL/Redis 卡死(OOM Killer 更可能直接 kill 进程)。
  • 限制总内存使用上限(关键!):
    # 启动前检查可用内存(约 750MB 可用,预留 200MB 给系统+OS)
    free -h  # 确保 MySQL + Redis + OS ≤ 800MB

🐘 MySQL 优化(目标:内存占用 ≤ 400MB)

参数 推荐值 说明
innodb_buffer_pool_size 256M 最大内存消耗项!设为总内存的 1/3~1/2,绝不可 >400M
key_buffer_size 16M MyISAM 缓存(如不用 MyISAM,设为 4M)
query_cache_type 0 彻底禁用查询缓存(MySQL 8.0 已移除,5.7 建议关)
max_connections 32 默认 151 太高!show processlist 查看实际连接数,设为峰值×2
innodb_log_file_size 64M 日志文件不宜过大(避免启动慢),但太小(<48M)影响写性能
innodb_flush_log_at_trx_commit 2 安全性降级:每秒刷日志(非每次事务),提升写入速度(可接受短暂数据丢失风险)
skip_host_cache, skip_name_resolve ON 禁用 DNS 解析,提速连接建立

my.cnf 示例(精简版)

[mysqld]
innodb_buffer_pool_size = 256M
key_buffer_size = 16M
max_connections = 32
innodb_log_file_size = 64M
innodb_flush_log_at_trx_commit = 2
query_cache_type = 0
skip_host_cache
skip_name_resolve
table_open_cache = 64
sort_buffer_size = 256K
read_buffer_size = 128K

✅ 启动后验证:mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
✅ 监控内存:ps aux --sort=-%mem | head -10


🧠 Redis 优化(目标:内存占用 ≤ 256MB)

推荐配置 说明
最大内存 maxmemory 256mb 必须设置! 防止 OOM
淘汰策略 maxmemory-policy allkeys-lru 优先淘汰最近最少用的 key(比 volatile-lru 更可控)
持久化 禁用 RDB + AOF save "" + appendonly no → 内存和 CPU 双重节省(接受重启丢数据)
TCP 优化 tcp-keepalive 60 保持连接活跃,减少握手开销
Lua 脚本 禁用或严格审查 避免长时间阻塞单核 CPU

redis.conf 关键片段

maxmemory 256mb
maxmemory-policy allkeys-lru
save ""                    # 禁用 RDB
appendonly no              # 禁用 AOF
tcp-keepalive 60
lazyfree-lazy-eviction yes # 内存淘汰异步化(Redis 4.0+)

💡 若需持久化:仅开启 save 900 1(900秒内1次修改才保存),并确保磁盘有空间。


⚖️ 协同调度与资源隔离(关键!)

  • CPU 亲和性(避免争抢)
    # 让 MySQL 绑定到 CPU0(唯一核心)
    sudo taskset -c 0 mysqld_safe &
    # Redis 绑定到 CPU0(无法分核,但可错峰)
    sudo taskset -c 0 redis-server /path/to/redis.conf
  • 启动顺序 & 优先级
    # 先启动 MySQL(更吃内存),再启动 Redis
    # 降低 Redis 优先级,让 MySQL 优先获得 CPU
    nice -n 10 redis-server redis.conf
  • 定时清理(防内存泄漏)
    # 每小时清理 Redis 过期 key(自动,但可补充)
    # MySQL:定期优化表(仅对小表,且低峰期)
    mysql -e "OPTIMIZE TABLE your_table;" 2>/dev/null

🛡️ 主动防御:监控与熔断

  1. 基础监控(无需额外服务)
    # 每分钟检查内存(脚本放入 crontab)
    echo "$(date): $(free -m | awk 'NR==2{printf "Mem:%d%%", $3*100/$2}') $(ps aux --sort=-%mem | head -3)" >> /var/log/res-mon.log
  2. MySQL 连接数熔断(应用层配合)
    • 应用连接池最大连接数 ≤ 20(如 HikariCP maximumPoolSize=15
    • 检测 Too many connections 错误时,返回 503 并降级(如读缓存失败则查 DB,写失败则提示稍后重试)
  3. Redis 内存告警
    # 检查 Redis 内存使用率 >90%
    redis-cli info memory | grep "used_memory_human" | awk -F': ' '{print $2}' | sed 's/M//; s/G/*1024/; s/K//; s/ //g' | bc -l | awk '{if($1>230) print "ALERT: Redis memory >230MB"}'

✅ 替代方案(强烈建议考虑)

场景 推荐方案 优势
纯开发/学习 使用 Docker + SQLite(应用内嵌) 零运维、零内存开销
轻量 Web 项目 LiteSpeed Web Server + MariaDB 10.6+(更省内存) 同等配置下内存占用低 20%
需要 Redis 缓存 改用 KeyDB(多线程 Redis 兼容版) 单核利用率更高,相同负载下延迟更低
长期运行 升级至 2核2G(约¥50/月) 成本增加 100%,但稳定性提升 500%+,值得投资

🔚 总结:1核1G 双数据库生存法则

内存是红线:MySQL 256MB + Redis 256MB + 系统 200MB = 刚好压线,任何一项超限即雪崩
持久化是奢侈品:接受「重启丢数据」换性能,否则必卡死
监控是氧气:没有监控=盲人开车,至少实现内存/连接数告警
降级是本能:应用层必须支持缓存失效、DB 降级、请求限流

如项目已上线且出现卡顿,请立即执行:
1️⃣ free -h → 查内存是否爆满
2️⃣ mysqladmin processlist → 查长连接/慢查询
3️⃣ redis-cli info memory → 查 Redis 是否触发淘汰
4️⃣ top -Hp $(pgrep mysqld) → 查 MySQL 线程 CPU 占用

真正的优化不是压榨硬件,而是承认限制,并用架构设计绕过它。
如果业务增长,请把省下的钱花在升级服务器上——这是性价比最高的“优化”。

需要我帮你生成一键优化脚本、Docker Compose 配置,或针对你的具体应用(如 WordPress/Laravel/Django)定制配置,欢迎随时告诉我! 🌟

未经允许不得转载:云服务器 » 小型项目用1核1G服务器部署MySQL和Redis,如何优化避免性能瓶颈?