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;
相关推荐
2501_944521592 小时前
Flutter for OpenHarmony 微动漫App实战:骨架屏加载实现
android·开发语言·javascript·数据库·redis·flutter·缓存
l1t2 小时前
将追赶法求连续区间的Oracle SQL改写成DuckDB
数据库·sql·oracle·duckdb
予枫的编程笔记2 小时前
【Java进阶】深度解析Canal:从原理到实战,MySQL增量数据同步的利器
java·开发语言·mysql
时艰.2 小时前
Redis 核心知识点归纳与详解
数据库·redis·缓存
莞理员2 小时前
新老数据库表同步问题
数据库
聆风吟º10 小时前
Oracle到KingbaseES数据库迁移:全流程实战指南与避坑总结
数据库·oracle·数据库迁移·kingbasees
哈__10 小时前
Oracle至KingbaseES数据库迁移全攻略:痛点拆解、配置实操与问题排查
数据库·oracle
JZC_xiaozhong11 小时前
电商ERP如何同步订单数据到MySQL?集成方案解析
数据库·mysql·数据分析·etl工程师·嵌入式实时数据库·电商erp集成·数据集成与应用集成
消失的旧时光-194311 小时前
第四篇(实战): 订单表索引设计实战:从慢 SQL 到毫秒级
java·数据库·sql