linux-ProxyQSL读写分离

1.读写分离技术

|---------------------------|------------------------------|
| 主库(Master) | 从库(Slave) |
| 主要负责处理写操作(INSERT,UPADTE等) | 从主库复制数据,主要负责处理大量的读操作(SELECT) |
[读写分离的作用]

|---------|---------------------------------------|
| 1.提升性能 | 将读写负载分散到不同数据库服务器,避免单一服务器瓶颈 |
| 2.提高扩展性 | 可以添加更多从库来水平扩展读能力 |
| 3.提高可用性 | 当某个从库宕机时,读请求可以被路由到其他健康的从库或主库,保证服务不中断。 |
[读写分离的好处]

其他了解:

综合使用(推荐大多数公司):ProxySQL

它是目前MySQL读写分离领域事实上的标准。它在功能、性能、透明性和运维复杂度上取得了最佳平衡。

--- Java使用(推荐Java团队):ShardingSphere-JDBC

如果是纯Java技术栈,并且对性能有极致要求,或者明确需要分库分表,那么ShardingSphere-JDBC是不二之选。

--- 老版本使用:MyCat

新项目不推荐使用。除非正在维护一个基于MyCat的老系统,或者团队对MyCat有很深的技术积累。

---简单使用(推荐云上用户):云厂商服务

如果项目完全构建在阿里云、AWS等云平台上,并且预算充足,直接使用云厂商的读写分离功能是最省心的选择如阿里云`RDS MySQL读写分离`。代价是失去灵活性和可能更高的长期成本。

2.什么是ProxySQL

ProxySQL 是一个高性能、高可用性、基于 MySQL 协议的开源数据库中间件

|--------|----------------------------------------------------------|
| 1.连接池 | 有效管理后端数据库连接,避免大量短连接造成的性能开销。 |
| 2.查询路由 | 根据预定义的规则,将不同的 SQL 语句发送到不同的 MySQL 服务器组(例如,写操作到主库,读操作到从库)。 |
| 3.负载均衡 | 根据预定义的规则,将不同的 SQL 语句发送到不同的 MySQL 服务器组(例如,写操作到主库,读操作到从库)。 |
| 4.故障转移 | 自动检测后端数据库的健康状态,将故障节点从流量池中移除,实现高可用。 |
| 5.查询缓存 | 缓存查询结果,对重复的读请求直接返回结果,极大减轻数据库压力。 |
| 6.动态配置 | 绝大多数配置可以在运行时修改,并动态加载,无需重启服务。 |
[ProxySQL核心功能]

3.ProxySQL如何实现读写分离

ProxySQL 通过一套多层配置系统来实现读写分离
核心概念:

a. 后端服务器 (mysql_servers)

定义MySQL 数据库实例,例如:主库 (hostgroup_id: 10)、从库1 (hostgroup_id: 20)、从库2 (hostgroup_id: 20)。hostgroup_id 是一个逻辑分组ID。

b. 用户认证 (mysql_users)

定义应用程序连接 ProxySQL 时使用的用户名和密码。这些用户必须在后端 MySQL 服务器上真实存在。

c. 查询规则 (mysql_query_rules)

这是实现读写分离的大脑。通过定义规则来告诉 ProxySQL 如何路由 SQL 语句。

  • 规则匹配条件 :例如,匹配 SELECT 语句的正则表达式 (^SELECT.*),或者根据 SQL 指纹、模式名等。
  • 目标主机组 :匹配该规则的查询将被路由到指定的 destination_hostgroup
  • 应用/不应用缓存:可以指定某些查询是否启用缓存。
  • 启用状态 :规则可以设置为启用 (active=1) 或禁用 (active=0)。

d. 流量处理流程

应用程序使用标准 MySQL 协议连接到 ProxySQL 的监听端口(默认 6033)。

ProxySQL 接收 SQL 查询。

ProxySQL 按顺序检查 mysql_query_rules 表中的规则。

一旦找到匹配的规则,查询就会被发送到规则指定的 destination_hostgroup 中的某个服务器。

如果没有规则匹配,默认情况下,查询会被发送到用户默认的 default_hostgroup(通常设置为主库的 hostgroup)。

4.案例实战Proxysql读写分离

proxysql-读写分离,有四个端口
6032是管理员登录
6033普通用户登录
1.master

监控用户权限USAGE, REPLICATION CLIENT

应用程序用户权限ALL PRIVILEGES
2.proxysql

mysql -udamin -padmin -h 127.0.0.1 -P 6032
主库从库信息配置到mysql_servers表
字段:hostgroup_id,hostname,port,weight,max_connections

LOAD MYSQL SERVERS TO RUNTIME;

SAVE MYSQL SERVER TO DISK;
配置监控用户global_variables表
variable_name='mysql-monitor_username'变为监控用户名
variable_name='mysql-monitor_password'变为监控用户密码

LOAD MYSQL VARIABLES TO RUNTIME;

SAVE MYSQL VARIABLES TO DISK;
检查监控状态
monitor.mysql_server_connect_log
monitor.mysql_server_ping_log
读写分离规则mysql_query_rules表
字段:rule_id,active,math_digest,destinnation_hostgroup,apply

LOAD MYSQL QUERY RULES TO RUNTIME

LOAD MYSQL QUERY RULES TO DISK
验证用户使用-P6033

4.1安装ProxySQL(Centos9)

安装依赖
复制代码
sudo dnf install -y wget gnupg2
安装proxySQL
复制代码
sudo dnf -y install https://repo.proxysql.com/ProxySQL/proxysql-3.0.x/centos/9/proxysql-3.0.4-1-centos9.x86_64.rpm
启动ProxySQL
复制代码
sudo systemctl enable --now proxysql

sudo systemctl status proxysql
验证启动
复制代码
netstat -tnlp

4.2关闭防火墙

复制代码
systemctl disable --now firewalld

sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config

4.3配置读写分离

4.3.1在主库执行(MySQL-Master)

创建监控用户-proxysql
复制代码
CREATE USER proxysql@'192.168.189.%' IDENTIFIED BY 'Proxysql@123';

GRANT USAGE,REPLICATION CLIENT ON *.* TO proxysql@'192.168.189.%';
创建应用程序用户(http&nginx)
bash 复制代码
CREATE USER http@'%' IDENTIFIED BY 'Http@123';
bash 复制代码
GRANT ALL PRIVILEGES ON *.* TO http@'%';
bash 复制代码
CREATE USER nginx@'%' IDENTIFIED BY 'Nginx@123';
bash 复制代码
GRANT ALL PRIVILEGES ON *.* TO nginx@'%';

4.3.2在proxysql主机进行配置

|---------------------|-------------------|------------------------------------------|
| 字段名 | 值 | 说明 |
| hostgroup_id | 10 | 主机组ID |
| hostname | '192.168.189.129' | 服务器地址 :后端 MySQL 服务器的 IP 地址或主机名 |
| port | 3306 | 端口号 :MySQL 服务的监听端口(默认3306) |
| weight | 1000 | 权重 :负载均衡权重,值越高,该服务器接收的查询越多(相对比例) |
| max_connections | 1000 | 最大连接数 :ProxySQL 到该服务器的最大并发连接数 |
[mysql_servers字段]

登录proxysql
复制代码
 mysql -u admin -padmin -h 127.0.0.1 -P 6032 --prompt='ProxySQLAdmin>'
清空mysql_servers
bash 复制代码
DELETE FROM mysql_servers;
添加主库到mysql_servers(这里我设置主库hostgroup_id=10)
bash 复制代码
INSERT INTO mysql_servers(hostgroup_id,hostname,port,weight,max_connections) VALUES (10,'192.168.189.138',3306,1000,1000);
添加从库到mysql_servers(这里我设置从库hostgroup_id=20)
bash 复制代码
INSERT INTO mysql_servers(hostgroup_id,hostname,port,weight,max_connections) VALUES (20,'192.168.189.129',3306,1000,1000);
查看添加结果
bash 复制代码
SELECT hostgroup_id,hostname,port,weight,max_connections FROM mysql_servers;
加载配置到内存&磁盘
bash 复制代码
LOAD MYSQL SERVERS TO RUNTIME;
bash 复制代码
SAVE MYSQL SERVERS TO DISK;
配置监控用户(设置监控用户名&密码)
bash 复制代码
UPDATE global_variables SET variable_value='proxysql' WHERE variable_name='mysql-monitor_username';
bash 复制代码
UPDATE global_variables SET variable_value='Proxysql@123' WHERE variable_name='mysql-monitor_password';
bash 复制代码
select * from global_variables where variable_name='admin-admin_credentials' or variable_name='mysql-monitor_username' or variable_name='mysql-monitor_password';
复制代码
LOAD MYSQL VARIABLES TO RUNTIME;

SAVE MYSQL VARIABLES TO DISK;
检查监控状态
bash 复制代码
SELECT * FROM monitor.mysql_server_connect_log ORDER BY time_start_us DESC LIMIT 5;
bash 复制代码
SELECT * FROM monitor.mysql_server_ping_log ORDER BY time_start_us DESC LIMIT 5;
配置应用程序用户

-- 需要根据 Master服务器创建用户

#超级用户client@'192.168.189.%' 'Client@123';

#HTTP应用 http@'%' 'Http@123';

#Nginx应用 nginx@'%' 'Nginx@123';

注:先清空现有用户

bash 复制代码
DELETE FROM mysql_users;

1.添加应用程序用户

bash 复制代码
INSERT INTO mysql_users(username, password, default_hostgroup, transaction_persistent) VALUES
    -> ('client', 'Client@123', 10, 1),
    -> ('http', 'Http@123', 10, 1),
    -> ('nginx', 'Nginx@123', 10, 1);

2.查看用户

bash 复制代码
select username,password from mysql_users;

3.加载配置到内存&磁盘

bash 复制代码
LOAD MYSQL USERS TO RUNTIME;
bash 复制代码
SAVE MYSQL USERS TO DISK;

配置读写分离规则

mysql_query_rules(配置表)

1.这是持久化存储所有查询规则配置的表

2.存储在 ProxySQL 的磁盘数据库(通常是 SQLite)中

runtime_mysql_query_rules(运行时表)

1.这是内存中当前实际生效的规则表

2.ProxySQL 进程运行时使用这个表进行查询路由决策

3.内容从 mysql_query_rules 加载而来

4.重启 ProxySQL 服务后,会重新从配置表加载

|---------------------------|-------------------------------------|
| rule_id | 规则ID,决定规则匹配的顺序(从小到大) |
| active | 规则是否激活:1=激活,0=禁用 |
| match_digest | 基于 SQL 语句的摘要(规范化后的语句)进行匹配 |
| match_pattern | 基于 SQL 语句的原始文本进行正则匹配 |
| destination_hostgroup | 目标主机组ID,匹配后查询将被路由到该组 |
| apply | 是否应用此规则:1=匹配后立即应用并停止后续匹配,0=继续匹配后续规则 |
| comment | 规则的备注说明 |
[mysql_query_rules字段]

1.清空现有规则

bash 复制代码
DELETE FROM mysql_query_rules;

2.规则1:捕获 SELECT ... FOR UPDATE,发往写组 (10)

bash 复制代码
INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply)
VALUES (1, 1, '^SELECT.*FOR UPDATE', 10, 0);

3.规则2:捕获所有其他 SELECT,发往读组 (20),并停止匹配

bash 复制代码
INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply)
VALUES (1, 1, '^SELECT.*FOR UPDATE', 10, 0);

4.规则3:默认规则,将所有未匹配的语句发往写组 (10),并停止匹配

bash 复制代码
INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply)
VALUES (3, 1, '.*', 10, 1);

5.加载配置到内存&磁盘

bash 复制代码
LOAD MYSQL QUERY RULES TO RUNTIME;
bash 复制代码
LOAD MYSQL QUERY RULES TO DISK;

5.测试与验证

开启一台新机器连接有Proxysql的主机,执行读写操作

5.1登录到Proxysql主机数据库

bash 复制代码
mysql -uclient -p'Client@123' -h 192.168.189.133 -P6033
测试
bash 复制代码
SELECT * FROM user.user1;

CREATE DATABASE proxysql_test1;

5.2在Proxysql主机数据库监控

bash 复制代码
SELECT hostgroup,count_star,digest_text FROM stats.stats_mysql_query_digest ORDER BY count_star DESC LIMIT 10;
相关推荐
李广坤13 小时前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
Turnip12022 天前
深度解析:为什么简单的数据库"写操作"会在 MySQL 中卡住?
后端·mysql
爱可生开源社区2 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1772 天前
《从零搭建NestJS项目》
数据库·typescript
加号32 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏2 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐2 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再2 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip
WeiXin_DZbishe2 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5
tryCbest2 天前
数据库SQL学习
数据库·sql