Nginx中TCP代理实现读写分离分发策略完全指南|Duuu笔记
Nginx 不原生支持 MySQL 协议解析,无法实现真正的读写分离;其 stream 模块仅能做四层 TCP 代理,路由逻辑须由后端 ProxySQL/MaxScale 或应用层完成,Nginx 仅承担接入、负载均衡与连接管理职责。
Nginx 本身不原生支持 MySQL 协议的解析与读写分离(如识别
SELECT
或
INSERT
语句),但自 1.9.0 起通过
stream
模块可实现基于 TCP 层的四层代理,配合合理后端部署,能间接支撑读写分离架构。关键在于:Nginx 只做连接转发,真正的读写判断和路由逻辑需由后端组件(如 MySQL Proxy、MaxScale、ProxySQL 或应用层)完成;Nginx 的角色是高可用接入、负载均衡与连接管理。
启用 stream 模块并配置基础 TCP 代理
Nginx 编译时需确保启用了
--with-stream
(多数预编译包已包含)。在主配置文件(如
nginx.conf
)顶层添加
stream
块:
stream {
upstream mysql_rw {
server 192.168.1.10:3306 weight=5; # 主库(可写)
server 192.168.1.11:3306 weight=3; # 从库1(只读)
server 192.168.1.12:3306 weight=3; # 从库2(只读)
}
server {
listen 3307;
proxy_pass mysql_rw;
proxy_timeout 1h;
proxy_responses 1;
}
}
该配置将客户端发往
:3307
的所有 TCP 流量,按权重轮询分发至后端 MySQL 实例。注意:
它不区分 SQL 类型,也不保证读请求落到从库
——这是四层代理的本质限制。
刺鸟创客
一款专业高效稳定的AI内容创作平台
下载
实现读写分离的两种可行路径
应用层路由 + Nginx 作为统一入口
:应用主动连接不同端口,例如写操作连
nginx_ip:3307
(指向主库),读操作连
nginx_ip:3308
(指向只读从库集群)。此时为每个用途单独定义
upstream
和
server
块,Nginx 仅做端口映射与健康检查。
前置协议感知中间件 + Nginx 做反向代理
:部署 ProxySQL 或 MaxScale 于后端,它们监听 MySQL 协议、解析 SQL 并路由到对应节点;Nginx 的
stream
模块则代理到这些中间件(而非直连 MySQL),提供 TLS 终止、连接池、限速等能力。此时 Nginx 不参与路由决策,只增强中间件的接入能力。
必要补充:健康检查与连接可靠性
stream
模块默认无主动健康检查,建议启用
ngx_stream_upstream_check_module
(需第三方模块或新版 Nginx 1.23+ 内置支持):
upstream mysql_rw {
check interval=3 rise=2 fall=3 timeout=1;
server 192.168.1.10:3306 weight=5;
server 192.168.1.11:3306 weight=3;
server 192.168.1.12:3306 weight=3;
}
同时设置合理的超时参数防止连接堆积:
proxy_timeout
控制空闲连接保持时间
proxy_responses 1
确保单次连接只转发一次(避免长连接复用引发状态混乱)
操作系统层面调大
net.core.somaxconn
和
fs.file-max
以支撑高并发连接
为什么不推荐纯 Nginx 实现读写分离?
MySQL 协议是全双工、带状态的二进制协议,不具备 HTTP 那样的明文方法字段。Nginx
stream
模块无法解析数据包内容,也无法维持事务上下文。若强行在 Nginx 层做 SQL 分析(如用 Lua + cosocket),会引入严重性能损耗、协议兼容风险及维护复杂度,违背其轻量高效的设计定位。真正可靠的读写分离应交由专业数据库代理层完成,Nginx 定位为稳定、可观测、易运维的流量入口网关。
