zl程序教程

您现在的位置是:首页 >  工具

当前栏目

proxysql集群

2023-09-11 14:21:08 时间

【1】集群的核心概念

(1.1)集群能达到什么效果?

参考转自官网:https://proxysql.com/documentation/ProxySQL-Cluster/

ProxySQL 是一个去中心化代理,如果可能,通常建议将其部署在与应用程序相同的服务器上。这种方法可以很好地扩展到数百个节点,并且可以在运行时轻松重新配置。

为了管理一组 ProxySQL 实例,您需要单独配置每个主机,使用配置管理工具,如 Ansible/Chef/Puppet/Salt(按字母顺序)或服务发现工具,如 Consul/ZooKeeper。

因此,虽然 ProxySQL 是高度可定制的,并且可以使用任何已经实现的配置管理工具技术在任何环境中进行部署和管理,但这种方法有一些缺点:

  • 它需要并依赖于外部软件(配置管理软件本身)
  • 前一点意味着这种方法本身不受支持
  • 收敛时间不可预测
  • 没有针对网络分裂的保护

因此,从 ProxySQL 1.4.x 开始,本机支持配置集群。

集群只是类似于组复制的操作,互相同步下面的5个表

目前 ProxySQL 集群解决方案中有两个主要组件:

  • 监控
  • 重新配置

两个组件(监控和远程重新配置)都可用于 4 个表:

  • global_variables (Supported from ProxySQL 2.1.x)
  • mysql_query_rules
  • mysql_servers
  • mysql_users
  • proxysql_servers

(1.2)集群管理变量

添加了几个与集群解决方案相关的新变量。它们都是 Admin 的变量,这意味着加载它们LOAD ADMIN VARIABLES TO RUNTIME需要命令。

定义同步内容的变量:

  • admin-checksum_mysql_query_rules: 布尔变量。true(默认)ProxySQL 每次LOAD MYSQL QUERY RULES TO RUNTIME执行时都会生成一个新的配置校验和。如果设置为false,新配置不会自动传播,也不会从远程节点同步;

  • admin-checksum_mysql_servers: 布尔变量。true(默认)ProxySQL 每次LOAD MYSQL SERVERS TO RUNTIME执行时都会生成一个新的配置校验和。如果设置为false,新配置不会自动传播,也不会从远程节点同步;

  • admin-checksum_mysql_users: 布尔变量。true(默认)ProxySQL 每次LOAD MYSQL USERS TO RUNTIME执行时都会生成一个新的配置校验和。

    •   如果设置为false,新配置不会自动传播,也不会从远程节点同步。如果您有数百万用户,请禁用此功能并且不要依赖它,因为它可能会很慢;

定义凭据的变量:

  • admin-cluster_username 和 admin-cluster_password: 使用此凭证来监控其他 ProxySQL 实例。

    •   请注意,用户名/密码对也应该存在于 中 admin-admin_credentials,否则连接将失败。如果 admin-cluster_username 未定义,则聚类不执行任何检查;

定义检查间隔/频率的变量:

  • admin-cluster_check_interval_ms:此变量定义校验和检查之间的间隔。

    默认值:1000。最小值:10,最大值:300000

  • admin-cluster_check_status_frequency:如果大于 0,则此变量定义在多少次校验和检查后执行状态检查。

    默认值:10。最小值:0 ,最大值:10000

远程同步后,立即将新更改保存到磁盘通常是个好主意。这样,重新启动后,配置将已经同步。

与同步到磁盘相关的变量:

  • admin-cluster_mysql_query_rules_save_to_disk: 布尔变量。true(默认)远程同步并加载到运行时,新的mysql查询规则也保存到磁盘;

  • admin-cluster_mysql_servers_save_to_disk: 布尔变量。true(默认)在远程同步并加载到运行时,新的 mysql 服务器也保存到磁盘;

  • admin-cluster_mysql_users_save_to_disk: 布尔变量。true(默认)在远程同步并加载到运行时,新的 mysql 用户也被保存到磁盘;

  • admin-cluster_proxysql_servers_save_to_disk: 布尔变量。true(默认)在远程同步并加载到运行时,新的 proxysql 服务器也被保存到磁盘;

 

由于不同的原因,可能同时重新配置多个 ProxSQL 实例。

  例如,可能每个 ProxySQL 实例都在监视 MySQL 复制拓扑并自动检测故障转移,并且在很短的时间内(可能不到一秒)它们将全部收敛到相同的配置,而无需与每个实例同步其他。

  同样,可能会自动避开节点的所有代理检测到临时网络问题或缓慢的 MySQL 实例。所有代理都将采取相同的操作,而无需相互同步。

  或者,作为最后一个示例,如果从属服务器由于复制滞后而滞后并自动回避,则所有代理将彼此独立地采取相同的操作。

因此,ProxySQL Cluster 可以配置为不立即与远程节点同步,而是在触发远程同步之前等待一定数量的检查。

如果在这样的阈值之后本地和远程配置仍然不同,则触发同步:

  • admin-cluster_mysql_query_rules_diffs_before_sync定义有多少不匹配检查触发mysql_query_rules

    默认同步:3。最小值:0(从不同步)。最大:1000

  • admin-cluster_mysql_servers_diffs_before_sync定义有多少不匹配检查触发mysql_servers

    默认同步:3。最小值:0(从不同步)。最大:1000

  • admin-cluster_mysql_users_diffs_before_sync定义有多少不匹配检查触发mysql_users

    默认同步:3。最小值:0(从不同步)。最大:1000

  • admin-cluster_proxysql_servers_diffs_before_sync定义有多少不匹配检查触发proxysql_servers

    默认同步:3。最小值:0(从不同步)。最大:1000

【2】集群配置表与统计表

(2.1)配置表 proxysql_servers

相关表:runtime_proxysql_servers,这是基表的运行时表示

表定义如下:

CREATE TABLE proxysql_servers (
    hostname VARCHAR NOT NULL,
    port INT NOT NULL DEFAULT 6032,
    weight INT CHECK (weight >= 0) NOT NULL DEFAULT 0,
    comment VARCHAR NOT NULL DEFAULT '',
    PRIMARY KEY (hostname, port) )

该表是一个配置表,定义了 ProxySQL 对等点的列表。

  • hostname: 对等方的主机名/IP
  • port: 对等端口
  • weight:目前未使用,但在未来增强的路线图中
  • comment: 自由形式的评论字段

也支持配置文件

proxysql_servers可以从配置文件中加载条目。

以下是如何proxysql_servers从配置文件进行配置的示例:

proxysql_servers =
(
    {
        hostname="172.16.0.101"
        port=6032
        weight=0
        comment="proxysql1"
    },
    {
        hostname="172.16.0.102"
        port=6032
        weight=0
        comment="proxysql2"
    }
)

(2.2) 配置表 runtime_checksums_values

表  runtime_checksums_values 是第一个runtime_ 但不是基表的运行时表示的表。

表定义:

CREATE TABLE runtime_checksums_values (
    name VARCHAR NOT NULL,
    version INT NOT NULL,
    epoch INT NOT NULL,
    checksum VARCHAR NOT NULL,
    PRIMARY KEY (name))

表 runtime_checksums_values 是第一个runtime_不是基表的运行时表示的表。

表 runtime_checksums_values 显示了 LOAD TO RUNTIME 命令执行时间的信息:

  • name: 模块名称

  • version: 显式或非显式执行了多少次LOAD TO RUNTIME(由于其他事件在内部执行)

  • epoch:LOAD TO RUNTIME执行时间的时间戳

  • checksum:内部存储器结构的校验和,由LOAD TO RUNTIME

案例:

  

 

 

注意:
目前 6 个模块中只有 4 个生成校验和。

    • LOAD MYSQL QUERY RULES TO RUNTIME admin-checksum_mysql_query_rules: 如果为真,则生成新的校验和

    • LOAD MYSQL SERVERS TO RUNTIME admin-checksum_mysql_servers: 如果为真,则生成新的校验和

    • LOAD MYSQL USERS TO RUNTIME admin-checksum_mysql_users: 如果为真,则生成新的校验和

    • LOAD PROXYSQL SERVERS TO RUNTIME: 总是生成一个新的校验和

    • LOAD ADMIN VARIABLES TO RUNTIME: 还没有生成校验和

    • LOAD MYSQL VARIABLES TO RUNTIME: 还没有生成校验和

(2.3)集群配置加载保存=》新命令

    • LOAD PROXYSQL SERVERS FROM MEMORY/LOAD PROXYSQL SERVERS TO RUNTIME

        将 ProxySQL 服务器从内存数据库加载到运行时数据结构

    • SAVE PROXYSQL SERVERS TO MEMORY/SAVE PROXYSQL SERVERS FROM RUNTIME

        将 ProxySQL Server 从运行时数据结构持久保存到内存数据库

    • LOAD PROXYSQL SERVERS TO MEMORY/LOAD PROXYSQL SERVERS FROM DISK

        将 ProxySQL Server 从磁盘数据库加载到内存数据库

    • LOAD PROXYSQL SERVERS FROM CONFIG

        将 ProxySQL Server 从配置文件加载到内存数据库

    • SAVE PROXYSQL SERVERS FROM MEMORY/SAVE PROXYSQL SERVERS TO DISK

        将 ProxySQL Server 从内存数据库持久化到磁盘数据库

(2.4)统计表 stats_proxysql_servers_checksums

表定义:

Admin> SHOW CREATE TABLE stats.stats_proxysql_servers_checksums\G
*************************** 1. row ***************************
       table: stats_proxysql_servers_checksums
Create Table: CREATE TABLE stats_proxysql_servers_checksums (
    hostname VARCHAR NOT NULL,
    port INT NOT NULL DEFAULT 6032,
    name VARCHAR NOT NULL,
    version INT NOT NULL,
    epoch INT NOT NULL,
    checksum VARCHAR NOT NULL,
    changed_at INT NOT NULL,
    updated_at INT NOT NULL,
    diff_check INT NOT NULL,
    PRIMARY KEY (hostname, port, name) )
1 row in set (0,00 sec)

下表显示了其他代理的校验和,以及它们的状态:

    • hostname: 对等方的主机名

    • port: 对等端口

    • name:在对等方报告的模块名称runtime_checksums_values

    • version: 校验和模块的版本,如 peer 的runtime_checksums_values.

      请注意,刚刚启动的 ProxySQL 实例将具有version=1: 因此,ProxySQL 实例将永远不会与具有 的另一个实例同步version=1,因为刚刚启动的 ProxyQL 实例不太可能是事实的来源。这可以防止新的加入节点破坏当前的集群配置。

    • epoch:校验和模块的纪元,如对等体中报告的那样runtime_checksums_values

    • checksum:校验和的模块,如对等报告中的runtime_checksums_values

    • changed_at:检测到校验和更改的时间戳

    • updated_at:上次刷新此条目的时间戳

    • diff_check:一个计数器,用于定义远程对等方的校验和与本地校验和不同的检查次数。

重新配置算法将在触发重新配置之前等待达到阈值。

这在同一配置同时应用于多个代理的情况下很有用,或者当代理在故障转移的情况下重新配置自己并且它们可能会在不需要重新同步的情况下收敛。

另见变量 cluster_*_diffs_before_sync

  如果 diff_check 在没有触发同步的情况下增加很多,这意味着远程对等点不是可靠的事实来源,例如  version=1

  另一方面,如果远程对等点不与集群的其余部分同步,则意味着集群没有可靠的事实来源。

  当集群中的所有代理都以不同的配置开始时,就会发生这种情况,并且它们无法自动决定哪个是正确的配置。

  在其中一个节点上运行 LOAD module TO RUNTIME 将自动“选择”它成为该特定模块的真实来源。

(2.5)统计表 stats_proxysql_servers_metrics

表定义:

Admin> SHOW CREATE TABLE stats.stats_proxysql_servers_metrics\G
*************************** 1. row ***************************
       table: stats_proxysql_servers_metrics
Create Table: CREATE TABLE stats_proxysql_servers_metrics (
    hostname VARCHAR NOT NULL,
    port INT NOT NULL DEFAULT 6032,
    weight INT CHECK (weight >= 0) NOT NULL DEFAULT 0,
    comment VARCHAR NOT NULL DEFAULT '',
    response_time_ms INT NOT NULL,
    Uptime_s INT NOT NULL,
    last_check_ms INT NOT NULL,
    Queries INT NOT NULL,
    Client_Connections_connected INT NOT NULL,
    Client_Connections_created INT NOT NULL,
    PRIMARY KEY (hostname, port) )
1 row in set (0,00 sec)

SHOW MYSQL STATUS此表显示了集群模块在其对等节点中执行时检索到的一些指标。列:

  • hostname: 对等方的主机名

  • port: 对等端口

  • weight: 与中报道的相同proxysql_serversweight

  • comment: 与中报道的相同proxysql_serverscomment

  • response_time_ms: 运行时的响应时间SHOW MYSQL STATUS,以毫秒为单位

  • Uptime_s: 对等体的正常运行时间(以秒为单位)

  • last_check_ms: 最后一次执行检查的时间,以毫秒为单位

  • Queries:对等方执行的查询数

  • Client_Connections_connected: 连接的客户端连接数

  • Client_Connections_created: 创建的客户端连接数

注意:
所有状态变量都由对等方检索,但只有少数被监控以检查对等方是否启动并运行并处理流量。
目前此功能仅用于调试目的,但未来版本将使用这些指标来了解远程对等点的健康状况。

(2.6)重新配置

因为代理相互监视,所以它们可以立即知道配置的校验和何时发生变化,这意味着配置本身发生了变化。

  如果配置发生更改,则会根据自己的配置对其进行检查,因为远程对等方的配置和自己的配置可能同时或在短时间内发生了更改。

如果它们不同:

  • 如果自己的version为 1 ,则找到version > 1具有最高 epoch 的对等体,并立即同步

  • 如果 ownversion大于 1,则开始计算它们有多少不同的检查

    • 当它们不同的检查次数大于cluster__name___diffs_before_synccluster__name__diffs_before_sync本身大于0时,找到version > 1具有最高epoch的peer,并立即同步(注意:有可能检测到不同的节点,但同步是针对不同的节点执行的。因为同步是与具有最高 epoch 的节点完成的,所以预计所有节点都会收敛)

同步过程执行如下:

    • 用于执行健康检查的同一连接用于SELECT执行SELECT _list_of_columns_ FROM runtime_module例如:SELECT hostgroup_id、hostname、port、status、weight、compression、max_connections、max_replication_lag、use_ssl、max_latency_ms、comment FROM runtime_mysql_servers;SELECT writer_hostgroup、reader_hostgroup、comment FROM runtime_mysql_replication_hostgroups;

    • 删除本地配置表。例如:从 mysql_servers 中删除;从 mysql_replication_hostgroups 中删除;

    • 将已从远程对等方检索到的内容插入本地配置表

    • 发出内部LOAD module_name TO RUNTIME:这将增加版本号并创建一个新的校验和

    • 如果cluster__name__save_to_disktrue,则发出内部SAVE module_name TO DISK

(2.7)构造搭建总结

前提:我们已经搭建到单实例

 

【3】集群搭建实践

注意,集群只同步这些

  • global_variables (Supported from ProxySQL 2.1.x)
  • mysql_query_rules
  • mysql_servers
  • mysql_users
  • proxysql_servers

所以,我们的 monitor 账户、 cluster_login 账户要自己弄好,新建好,且集群节点全要一样;

(3.0)架构

192.168.191.149  、192.168.191.176 

proxysql、mysql 均有

proxysql 已经搭建好单实例,mysql 搭建好了主从关系

(3.1)初始化单实例上关于集群的配置

#-- 集群之间互相连接的账户
update global_variables set variable_value='admin:admin;cluster_admin:1234' where variable_name='admin-admin_credentials';
update global_variables set variable_value='cluster_admin' where variable_name='admin-cluster_username';
update global_variables set variable_value='1234' where variable_name='admin-cluster_password';

#-- proxysql 监控 mysql的账户(monitor 已经在mysql中建立过了)
update global_variables set variable_value='monitor' where variable_name='mysql-monitor_username';
update global_variables set variable_value='123456' where variable_name='mysql-monitor_password';

#-------- 配置变量
update global_variables set variable_value=1000 where variable_name='admin-cluster_check_interval_ms';
update global_variables set variable_value=10 where variable_name='admin-cluster_check_status_frequency';
update global_variables set variable_value='true' where variable_name='admin-cluster_mysql_query_rules_save_to_disk';
update global_variables set variable_value='true' where variable_name='admin-cluster_mysql_servers_save_to_disk';
update global_variables set variable_value='true' where variable_name='admin-cluster_mysql_users_save_to_disk';
update global_variables set variable_value='true' where variable_name='admin-cluster_proxysql_servers_save_to_disk';
update global_variables set variable_value=3 where variable_name='admin-cluster_mysql_query_rules_diffs_before_sync';
update global_variables set variable_value=3 where variable_name='admin-cluster_mysql_servers_diffs_before_sync';
update global_variables set variable_value=3 where variable_name='admin-cluster_mysql_users_diffs_before_sync';
update global_variables set variable_value=3 where variable_name='admin-cluster_proxysql_servers_diffs_before_sync';


#-- 装载、保存、应用
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;

LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;

LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;

LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;

LOAD ADMIN VARIABLES TO RUNTIME;
SAVE ADMIN VARIABLES TO DISK;

#-- LOAD PROXYSQL SERVERS TO RUNTIME;
#-- SAVE PROXYSQL SERVERS TO DISK;

 

(3.2)配置集群主机信息

INSERT INTO proxysql_servers(hostname,port,weight,comment) VALUES ('192.168.191.149',6032,0,'p1');
INSERT INTO proxysql_servers(hostname,port,weight,comment) VALUES ('192.168.191.176',6032,0,'p2');
LOAD PROXYSQL SERVERS TO RUNTIME;
SAVE PROXYSQL SERVERS TO DISK;

需要预先的将这个集群中的PROXYSQL 进行一个配置,

以上的(3.1)(3.2)操作需要在每个PROXYSQL中操作;

  先一起做 (3.1),然后再随便先后一起做(3.2)

(3.3)查看同步信息

可以看到两个proxysql实例中'mysql_query_rules', 'mysql_servers', 'mysql_users', 'proxysql_servers'四个表的checksum都是一致的。

select * from stats_proxysql_servers_checksums order by name,hostname;

   

查看连接、存活、启动相关信息:

select * from stats_proxysql_servers_metrics;

  

 

 

 check_sum值一样表示同步完成;

(3.4)构建 mysql_servers 、mysql_users、mysql_query_rules、mysql_replication_hostgroups 

所有节点都执行:

#--  mysql_replication_hostgroups
insert into mysql_replication_hostgroups ( writer_hostgroup, reader_hostgroup, comment) values (1,10,'test_reader_write_hostgroup');

现在节点  192.168.191.149 上运行

#-- mysql_servers

INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (1,'192.168.191.149',3306);
INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (1,'192.168.191.176',3306);


#--  mysql_users
INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('proxysql','123456',1);


#-- mysql_query_rules
insert into mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply) values (2,1,'^select.*LOCK IN SHARE MODE$',1,1);
insert into mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply) values (100,1,'^select',10,1);

load mysql servers to runtime;
save mysql servers to disk;

load mysql users to runtime;
save mysql users to disk;

load mysql query rules to runtime;
save mysql query rules to disk;

LOAD PROXYSQL SERVERS TO RUNTIME;
SAVE PROXYSQL SERVERS TO DISK;
 

结果就是: 这傻活根本就不同步啊;

  

但要是用 176 运行 mysql server等表的操作就可以正常同步;真奇了怪了;

  

(3.5)不建议使用集群

垃圾集群,问题很多,很多表还不能同步,几个小表不如直接写个脚本操作,维护复杂度还更低;

查询还不路由,垃圾的很!

【集群使用注意事项】

1. 如果需要集群支持mysql group replication(MGR)的监控。

那么需要在集群的所有机器上在表mysql_group_replication_hostgroups插入记录:

insert into mysql_group_replication_hostgroups(writer_hostgroup,backup_writer_hostgroup,reader_hostgroup,offline_hostgroup,active) values(10,20,30,40,1);
save mysql servers to disk;
load mysql servers to runtime;

2. 如果监控用户名,密码; 以及 cluster 用户名,密码和凭证修改也需要在集群内的所有机器上执行。

3. 新的机器加入proxysql cluster的时候,需要保证 监控用户名,密码; 以及 cluster 用户名,密码和凭证与集群内的机器一致,

如果不一致,则需要先进行一致化操作。另外在同步完数据(即执行:insert into proxysql_servers,save proxysql servers to

disk;load proxysql servers to runtime;)之后。才能对表mysql_group_replication_hostgroups进行操作。且对表mysql_group_replication_hostgroups操作时需要保证满足注意事项1.

【问答疑惑】

如果在每个 ProxySQL 服务器上同时加载不同的配置,需要将哪个配置“传播”到所有其他节点会怎样?最后一个?

master和master选举的概念还没有实现。这意味着一个LOAD命令可能同时在多个节点上执行(多主节点,打个比方),并且每个节点都会触发基于时间戳的冲突解决的自动重新配置。
如果在多个 ProxySQL 实例上同时加载相同的配置,它们应该会自动收敛。
如果在不同时间在多个 ProxySQL 实例上加载了不同的配置,则最后一个将获胜。
如果同时在多个 ProxySQL 实例上加载不同的配置,则这两个配置将开始传播,直到它们不会收敛,因为无法解决冲突。
好消息是每个 ProxySQL 都知道每个其他节点的配置校验和,因此很容易检测和监控不匹配。

谁将这个配置写入所有这些节点?

目前使用的是拉取机制,因此检测到它的节点需要重新配置自己,它将从具有最新配置的节点中拉取配置并在本地应用它。

你将如何实施选举?Raft 共识协议 ?

选举的实现在路线图中,但可能不是 Raft 共识协议。
ProxySQL 使用表来存储配置,它使用 MySQL 协议向其对等方执行请求,查询它们的健康状况和配置,它使用 MySQL 协议来实现心跳等等:出于这些原因,对于 ProxySQL,MySQL 协议与 Raft 协议相比,它本身可能是一个更通用的解决方案。

如果由于某种原因其中一个节点在重新配置时无法获取新配置,会发生什么情况?

更改是异步传播的。因此,其中一个节点可能无法获取新配置,例如在网络问题或 ProxySQL 重新启动的情况下。然而,当 ProxySQL 实例检测到其对等节点之一具有较新的配置时,它会自动抓取它。

那么crossdc呢?最佳实践是什么,在每个 DC 中都有一个集群?

集群没有边界,因此可以有一个跨多个 DC 的集群,或者在同一个 DC 中有多个集群,或者跨多个 DC 有多个集群。这实际上取决于具体的用例。
唯一的限制是每个 ProxySQL 实例都需要属于一个集群。
集群没有名称,为了确保节点不会错误地加入错误的集群,确保每个集群使用不同的凭据很重要。admin-admin_credentials_admin-cluster_usernameadmin-cluster_password

以某种方式复制配置 crossdc 可能是一个不错的功能,但更喜欢与本地 proxysql 服务器最近的后端服务器的流量。我现在正在使用重量。

对于这种特定情况,我认为为每个 DC 创建不同的集群更有意义,因为配置会有所不同。

新的 ProxySQL 将如何加入集群?

Bootstrap 非常简单:从proxysql_servers.

所有其他 ProxySQL 服务器如何知道有一个新节点?

他们不会自动知道,这是为了防止新节点可能损坏集群。
换句话说,新节点一加入就可以拉取配置,但不能将自己宣传为事实来源。
要让其他 ProxySQL 实例知道有一个新节点,只需将新节点添加到proxysql_servers当前集群的任何节点中并发出LOAD PROXYSQL SERVERS TO RUNTIME.

 

【参考文档】

实践参考:https://blog.csdn.net/liuhuayang/article/details/109064319

理论参考:https://proxysql.com/documentation/ProxySQL-Cluster/

超级详细的 proxysql集群+MGR:https://www.cnblogs.com/kevingrace/p/10411457.html