插件窝 干货文章 nginx读写分离怎么配置

nginx读写分离怎么配置

server 读写 3306 988    来源:    2025-04-23

Nginx读写分离配置指南

读写分离是一种常见的数据库优化策略,通过将读操作和写操作分发到不同的服务器来提高系统性能。以下是使用Nginx实现读写分离的几种方法:

1. 基于Nginx的HTTP反向代理实现读写分离

配置示例

http {
    upstream write_servers {
        server 192.168.1.101:3306;  # 主数据库(写)
    }

    upstream read_servers {
        server 192.168.1.102:3306;  # 从数据库1(读)
        server 192.168.1.103:3306;  # 从数据库2(读)
        server 192.168.1.104:3306;  # 从数据库3(读)
    }

    server {
        listen 80;

        # 写操作路由到主库
        location /write {
            proxy_pass http://write_servers;
        }

        # 读操作路由到从库
        location /read {
            proxy_pass http://read_servers;
        }
    }
}

2. 使用Nginx Stream模块实现TCP层读写分离

对于MySQL等数据库协议,可以在TCP层实现读写分离:

stream {
    upstream mysql_master {
        server 192.168.1.101:3306;  # 主库
    }

    upstream mysql_slaves {
        server 192.168.1.102:3306;  # 从库1
        server 192.168.1.103:3306;  # 从库2
    }

    server {
        listen 3306;

        # 根据SQL语句判断读写
        proxy_pass $upstream;

        # 简单的SQL解析(示例)
        set $upstream mysql_master;
        if ($query ~* "^SELECT") {
            set $upstream mysql_slaves;
        }
    }
}

3. 使用Nginx Plus的商业模块

Nginx Plus提供了更高级的数据库负载均衡功能:

stream {
    upstream mysql_cluster {
        zone tcp_mem 64k;

        server 192.168.1.101:3306;  # 主库
        server 192.168.1.102:3306;  # 从库1
        server 192.168.1.103:3306;  # 从库2
    }

    server {
        listen 3306;
        proxy_pass mysql_cluster;
        proxy_connect_timeout 1s;

        # 根据SQL语句路由
        health_check match=read_only;
    }

    match read_only {
        send "SELECT 1;\r\n";
        expect ~* "1";
    }
}

4. 结合Lua脚本实现智能路由

使用OpenResty可以编写更复杂的路由逻辑:

http {
    lua_package_path "/path/to/lua/scripts/?.lua;;";

    upstream backend_master {
        server 192.168.1.101:3306;
    }

    upstream backend_slave {
        server 192.168.1.102:3306;
        server 192.168.1.103:3306;
    }

    server {
        listen 80;

        location / {
            access_by_lua_file /path/to/router.lua;
            proxy_pass http://backend;
        }
    }
}

router.lua示例:

local method = ngx.req.get_method()
if method == "POST" or method == "PUT" or method == "DELETE" then
    ngx.var.backend = "backend_master"
else
    ngx.var.backend = "backend_slave"
end

注意事项

  1. 一致性保证:读写分离可能导致数据不一致,需要考虑主从同步延迟问题
  2. 故障转移:需要配置适当的健康检查机制
  3. 连接池管理:合理配置连接池大小和超时时间
  4. 事务处理:涉及事务的操作应该路由到主库

以上配置可以根据实际业务需求进行调整和扩展。对于生产环境,建议进行充分的测试和性能评估。