1 ProxySQL
集群版结构
ProxySQL
在早期版本若需要做高可用,需要搭建两个实例,进行冗余。但两个ProxySQL
实例之间的数据并不能共通,在主实例上配置后,仍需要在备用节点上进行配置,对管理来说非常不方便。
但是ProxySQL
从1.4.2版本后,ProxySQL
支持原生的Cluster
集群搭建,实例之间可以互通一些配置数据,大大简化了管理与维护操作。
为了实现ProxySQL
的高可用架构,有很多种方式。例如ProxySQL
+KeepAlive
+MySQL
的结构、 ProxySQL
+MySQL(MGR)
的结构。
1.1 ProxySQL
+KeepAlive
+MySQL(mgr集群)
KeepAlive
起初是为LVS设计的专门用来监控集群系统中各个服务节点的状态如果某个服务节点出现异常或者工作出现故障。KeepAlive
将检测到这个故障的服务节点,并将出现故障的服务节点从集群系统中剔除。
而在故障节点恢复正常后。KeepAlive
又可以自动将该服务节点重新加入集群中,这些工作全部自动完成。 后来又加入了VRRP的功能,VRRP(Virtual Router Redundancy Protocol),虚拟路由协议出现的目的是为了解决静态路由出现的单点故障问题,通过VRRP可以实现网络不间断稳定运行,因此KeepAlive
一方面具有服务器状态检测和故障隔离功能,另一方面也有HA Cluster
功能;这个功能可以用来实现各种中间件高可用(不只是ProxySQL
)。
例如配置
IP地址 主机名 部署角色
192.168.4.4 MySQL01 MySQL
192.168.4.5 MySQL02 MySQL
192.168.4.6 MySQL03 MySQL
192.168.4.7 `ProxySQL`01 `ProxySQL`、``KeepAlive``
192.168.4.8 `ProxySQL`02 `ProxySQL`、``KeepAlive``
之前的结构,ProxySQL
并没有主从/集群的概念,谁出故障了,会被KeepAlive
检测到,然后KeepAlive
会让另一个正常的ProxySQL
工作。
当然,ProxySQL
有了集群版之后,也能够通过KeepAlive
实现高可用架构。
🍁 结合
KeepAlive
,利用VIP资源漂移来实现ProxySQL
双节点的无感知故障切换,即对外提供一个统一的vip地址,并且在KeepAlive.conf
文件中配置ProxySQL
服务的监控脚本,当宕机或ProxySQL
服务挂掉时就将vip资源漂移到另一个正常的节点上,从而使ProxySQL
的代理层持续无感应地提供服务。
1.2 ProxySQL
目前已经支持集群-原生的集群
ProxySQL
从1.4.2版本后,ProxySQL
支持原生的Cluster
集群搭建。ProxySQL
原生集群。
ProxySQL
有两个主要的组件实现ProxySQL
集群:
-
monitoring (集群监控组件)
-
re-configuration (remote configuration,远程配置)
这两个组件中都有4张表:
-
📑
MySQL_query_rules
//sql读写分离规则 -
📑
MySQL_servers
//MySQL集群实例 -
📑
MySQL_users
//监控、读写的用户 -
📑
ProxySQL_servers
//ProxySQL的集群
1、Monitoring集群监控组件 为了监控Cluster
,ProxySQL
引入了几个新的表、命令、变量。
Admin variables类型变量 有几个和Cluster
相关的变量,它们是Admin变量,意味着修改它们需要使用load admin variables to runtime
使其生效。
*1) 用于同步的变量* admin-checksum_MySQL_query_rules //读写分离sql规则的checksum admin-checksum_MySQL_servers //MySQL集群实例的checksum admin-checksum_MySQL_users //操作MySQL用户的schecksum,如果有数百万的users,则建议禁用该特性且不要依赖于它,因为它会非常慢。(官方建议
)
这几个变量都是布尔值,其中:
-
admin-checksum_MySQL_query_rules
设置为true时,每次执行
"LOAD MySQL QUERY RULES TO RUNTIME"
时,ProxySQL
都会生成一个新的配置checksum校验码(configuration checksum)。如果为false时,新的配置不会自动被广播出去(被其他ProxySQLJ探测到),也不会从其它节点同步配置到本机;
-
admin-checksum_MySQL_servers
设置为true时,每次执行
"LOAD MySQL SERVERS TO RUNTIME"
时,ProxySQL
都会生成一个新的配置checksum。如果为false时,新的配置不会自动被广播出去,也不会从其它节点同步配置到本机;
-
admin-checksum_MySQL_users
设置为true时,每次执行
"LOAD MySQL USERS TO RUNTIME"
时,ProxySQL
都会生成一个新的配置checksum。如果为false时,新的配置不会自动被广播出去,也不会从其它节点同步配置到本机;
*2) 集群认证凭据相关的变量*
admin-Cluster_username 和 admin-Cluster_password:该凭据用于监控其它ProxySQL
实例。
#需要注意,这个用户/密码必须是admin-admin_credentials中已经存在的[在配置文件中配置这个变量,可以配置多个用户名和密码],否则将会连接失败。如果没有定义集群凭据,ProxySQL
集群将不会做任何检查。
在ProxySQL
Cluster
集群间,ProxySQL
为了监控其他ProxySQL
实例需要认证参数:admin-Cluster_username 和 admin-Cluster_password。而且这2个参数指定的用户名/密码还必须配置到参数 admin-admin_credentials 中,否则会无法连接到其他ProxySQL
。
#配置文件proxy.cnf
datadir="/var/lib/proxysql"
admin_variables =
{
#这个变量是配置文件中的(可以配置多个,用分号分隔开)
admin_credentials="admin:admin;Cluster1:secret1pass"
mysql_ifaces="0.0.0.0:6032"
cluster_username="cluster1"
cluster_password="secret1pass"
...........
}
...........
*3) 检查时间间隔/频率相关变量* admin-Cluster_check_interval_ms:
定义校验码检查(checksum check)时间间隔。默认值1000(即1秒),最小值10,最大值300000。
admin-Cluster_check_status_frequency:
该变量定义做了多少次checksum检查后,就执行一次状态检查(status check)。默认值10,最小0,最大10000。
*4) 同步到磁盘相关的变量* 在远程同步配置之后,通常最好的做法是立即将新的更改保存到磁盘。这样重启时,更改的配置不会丢失。 admin-Cluster_MySQL_query_rules_save_to_disk admin-Cluster_MySQL_servers_save_to_disk admin-Cluster_MySQL_users_save_to_disk admin-Cluster_ProxySQL_servers_save_to_disk
这几个变量都是布尔值。当设置为true(默认值)时,在远程同步并load到runtime后,新的MySQL_query_rules、MySQL_servers、MySQL_users、`ProxySQL_servers配置会持久化到磁盘中。
*5) 是否要远程同步的变量* 由于某些原因,可能多个ProxySQL
实例会在同一时间进行重新配置。 例如,每个ProxySQL
实例都在监控MySQL的replication,且自动探测到MySQL的故障转移,在一个极短的时间内(可能小于1秒),这些ProxySQL
实例可能会自动调整新的配置,而无需通过其它ProxySQL
实例来同步新配置。
类似的还有,当所有ProxySQL
实例都探测到了和某实例的临时的网络问题,或者某个MySQL节点比较慢(replication lag, 拖后腿),这些ProxySQL
实例都会自动地避开这些节点。这时各ProxySQL
实例也无需从其它节点处同步配置,而是同时自动完成新的配置。
基于此,可以配置ProxySQL
集群,让各ProxySQL
实例暂时无需从其它实例处同步某些配置,而是等待一定次数的检查之后,再触发远程同步。但是,如果本地和远程节点的这些变量阈值不同,则还是会触发远程同步。
admin-Cluster_MySQL_query_rules_diffs_before_sync: admin-Cluster_MySQL_servers_diffs_before_sync: admin-Cluster_MySQL_users_diffs_before_sync: admin-Cluster_ProxySQL_servers_diffs_before_sync:
分别定义经过多少次的"无法匹配(数据不一致)"检查之后,触发mysql_query_rules、MySQL_servers、MySQL_users、ProxySQL_servers配置的远程同步。默认值3次,最小值0,表示永不远程同步,最大值1000。
比如各实例监控MySQL_servers配置并做校验码检查,如果某实例和本地配置不同,当多次检测到都不同时,将根据load to runtime的时间戳决定是否要从远端将MySQL_servers同步到本地。
6) 延迟同步 在ProxySQL``Cluster
中可以定义达到多少个checksum 不同之后,才在集群内部进行配置同步。 query rules, servers, users 和ProxySQL servers 分别由admin-Cluster_XXX_diffs_before_sync 相关的参数,取值范围0 ~ 1000,0 代表从不同步。默认3。
*Configuration tables*配置相关的表
1) ProxySQL
_servers 表 ProxySQL
servers表定义了ProxySQL
集群中各ProxySQL
实例列表。ProxySQL
集群有哪些实例,可以查看ProxySQL
servers 表。在新增ProxySQL
实例时,也需要 insert 该表,或者修改cnf 文件中的 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) )
各字段的意义如下: - hostname:ProxySQL
实例的主机名或IP地址; - port:ProxySQL
实例的端口 (译注:这个端口是ProxySQL
示例的admin管理端口); - weight:目前未启用该功能。定义集群中各ProxySQL
的权重值; - comment:注释字段,可随意填写;
ProxySQL
servers的配置项可以从传统配置文件中加载,即支持配置文件。以下是传统配置文件中定义ProxySQL
servers的示例:
`ProxySQL`_servers =
(
{
hostname="172.16.0.101"
port=6032
weight=0
comment="`ProxySQL`1"
},
{
hostname="172.16.0.102"
port=6032
weight=0
comment="`ProxySQL`2"
}
)
*特别注意:*ProxySQL
只有在磁盘数据库文件不存在,或者使用了--initial选项时才会读取传统配置文件。 - 配置文件暂时还不支持该表。 - 因为该ProxySQL
Cluster
功能仍处于试验阶段,不会自动从磁盘配置文件中读取到该表中。也就是说,目前阶段,不支持在配置文件中配置ProxySQL
server表的内容!
*2) runtimeProxySQL
servers 表* 正如其它runtime表一样,runtimeProxySQL
servers表和ProxySQL
servers的结构完全一致,只不过它是runtime数据结构中的配置,也就是当前正在生效的配置。该表的定义语句如下:
CREATE TABLE runtime_`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) )
*3)runtime_checksums_values 表* runtime_checksums_values表是目前第一个不基于内存数据库中的runtime_表(译注:换句话说,没有checksums_values表)。该表的定义语句如下:
CREATE TABLE runtime_checksums_values (
name VARCHAR NOT NULL,
version INT NOT NULL,
epoch INT NOT NULL,
checksum VARCHAR NOT NULL,
PRIMARY KEY (name))
该表用于显示在执行load to runtime命令时的一些信息: - name:模块的名称 - version:执行了多少次load to runtime操作,包括所有隐式和显式执行的(某些事件会导致ProxySQL
内部自动执行load to runtime命令) - epoch:最近一次执行load to runtime的时间戳 - checksum:执行load to runtime时生成的配置校验码(checksum)
该表的一个实例
Admin> SELECT * FROM runtime_checksums_values;
+-------------------+---------+------------+--------------------+
| name | version | epoch | checksum |
+-------------------+---------+------------+--------------------+
| admin_variables | 0 | 0 | |
| MySQL_query_rules | 5 | 1503442167 | 0xD3BD702F8E759B1E |
| MySQL_servers | 1 | 1503440533 | 0x6F8CEF0F4BD6456E |
| MySQL_users | 1 | 1503440533 | 0xF8BDF26C65A70AC5 |
| MySQL_variables | 0 | 0 | |
| `ProxySQL`_servers | 2 | 1503442214 | 0x89768E27E4931C87 |
+-------------------+---------+------------+--------------------+
6 rows in set (0,00 sec)
*特别注意:* 目前6个组件中只有4种模块的配置会生成对应的校验码(checksum),不能生成的组件是:admin_variables,MySQL_variables。
checnsum 只有在执行了load to run ,并且admin-checksum_XXX = true 时,才可以正常生成。即: - LOAD MySQL QUERY RULES TO RUNTIME:当admin-checksum_MySQL_query_rules=true时生成一个新的MySQL_query_rules配置校验码 - LOAD MySQL SERVERS TO RUNTIME:当admin-checksum_MySQL_servers=true时生成一个新的MySQL_servers配置校验码 - LOAD MySQL USERS TO RUNTIME:当admin-checksum_MySQL_users=true时生成一个新的MySQL_users配置校验码 - LOAD ProxySQL
SERVERS TO RUNTIME:总是会生成一个新的ProxySQL
_servers配置校验码 - LOAD ADMIN VARIABLES TO RUNTIME:不生成校验码(不生成校验码) - LOAD MySQL VARIABLES TO RUNTIME:不生产校验码(不生成校验码)
New commands (新命令): - LOAD ProxySQL
SERVERS FROM MEMORY / LOAD ProxySQL
SERVERS TO RUNTIME 从内存数据库中加载ProxySQL
servers配置到runtime数据结构 - SAVE ProxySQL
SERVERS TO MEMORY / SAVE ProxySQL
SERVERS FROM RUNTIME 将ProxySQL
servers配置从runtime数据结构持久化保存到内存数据库中 - LOAD ProxySQL
SERVERS TO MEMORY / LOAD ProxySQL
SERVERS FROM DISK 从磁盘数据库中加载ProxySQL
servers配置到内存数据库中 - LOAD ProxySQL
SERVERS FROM CONFIG 从传统配置文件中加载ProxySQL
servers配置到内存数据库中 - SAVE ProxySQL
SERVERS FROM MEMORY / SAVE ProxySQL
SERVERS TO DISK 将ProxySQL
servers配置从内存数据库中持久化保存到磁盘数据库中
*state tables*状态表 最新的版本有三个表被加入到state 库中。
*1)stats_ProxySQL_servers_checksums 表* 该表记录集群中各个实例的组件checksum 信息。
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) )
各字段意义如下: - hostname:ProxySQL
实例的主机名 - port:ProxySQL
实例的端口 - name:对端runtime_checksums_values中报告的模块名称 - version:对端runtime_checksum_values中报告的checksum的版本 *注意*,ProxySQL
实例刚启动时version=1:ProxySQL
实例将永远不会从version=1的实例处同步配置数据,因为一个刚刚启动的ProxyQL实例不太可能是真相的来源,这可以防止新的连接节点破坏当前集群配置 - epoch:对端runtime_checksums_values中报告的checksum的时间戳epoch值 - checksum:对端runtime_checksums_values中报告的checksum值 - changed_at:探测到checksum发生变化的时间戳 - updated_at:最近一次更新该类配置的时间戳 - diff_check:一个计数器,用于记录探测到的对端和本地checksum值已有多少次不同 需要等待达到阈值后,才会触发重新配置。前面已经说明,在多个ProxySQL
实例同时或极短时间内同时更改配置时,可以让ProxySQL
等待多次探测之后再决定是否从远端同步配置。这个字段正是用于记录探测到的配置不同次数。如果diff_checks不断增加却仍未触发同步操作,这意味着对端不是可信任的同步源,例如对端的version=1。另一方面,如果某对端节点不和ProxySQL
集群中的其它实例进行配置同步,这意味着集群没有可信任的同步源。这种情况可能是因为集群中所有实例启动时的配置都不一样,它们无法自动判断哪个配置才是正确的。可以在某个节点上执行load to runtime,使该节点被选举为该类配置的可信任同步源。
*2)stats_ProxySQL_servers_metrics 表* 该表用来显示群集模块在各个实例中执行 SHOW MySQL STATUS 时,当前系统的部分指标。目前该表只是用来debug 的,在未来该表的各个指标将用来反映各个实例的健康状态。
用于显示ProxySQL内各种结构的内存使用情况。 在当前,只跟踪了很少的结构(SQLite, Auth module, Query Digests),但是将来会跟踪更多内部结构,导出更多指标。
Admin> SHOW CREATE TABLE stats.stats_mysql_servers_metrics\G
*************************** 1. row ***************************
table: stats_mysql_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) )
当执行show MySQL status语句时,显示一些已检索到的指标。字段意义如下: - hostname:ProxySQL
实例主机名 - port:ProxySQL
实例端口 - weight:报告结果同ProxySQL
servers.weight字段 - comment:报告结果同ProxySQL
servers.comment字段 - response_time_ms:执行show MySQL status的响应时长,单位毫秒 - Uptime_s:ProxySQL
实例的uptime,单位秒 - last_check_ms:最近一次执行check距现在已多久,单位毫秒 - Queries:该实例已执行query的数量 - Client_Connections_connected:number of client's connections connected - Client_Connections_created:number of client's connections created *注意:*当前这些状态只为debug目的,但未来可能会作为远程实例的健康指标。
*3)stats_ProxySQL_servers_status* 创建此表是为了显示与proxysql_servers表中配置的所有服务相关的一般统计信息。===>当前未使用,还在开发中。
还有其他的一些表,这些表中都统计了相关的信息。
2、Re-configuration 因为集群间,所有节点都是相互监控的。每个ProxySQL
节点都监控集群中的其它实例,它们可以快速探测到某个实例的配置是否发生改变。如果某实例的配置发生改变,其它实例会检查这个配置和自身的配置是否相同,因为其它节点的配置可能和本节点的配置同时(或在极短时间差范围)发生了改变。
由于相互监控,所以当配置发生变动时,它们可以立即发现。当其他节点的配置发生变动时,本节点会先去检查一次它自身的配置,因为有可能remote instance 和local instance 同时发生配置变动。 如果比较结果不同: - 如果它们自身的 version = 1,就去找集群内从version > 1的节点处找出epoch最大值的节点,并从该节点拉取配置应用到本地,并立即同步。 如果version >1, 该节点开始统计和其他节点间的differ 数。即开始对探测到的不同配置进行计数。 当 differ 大于 Cluster
name_diffs_before_sync , 并且Cluster
namediffs_before_sync > 0, 就去找集群内 version >1, 并且epoch 最高的节点,并立即同步。也就是说当探测到不同配置的次数超过Cluster
name_diffs_before_sync,且Cluster
name_diffs_before_sync大于0时,找出version > 1且epoch值最大的节点,并从该节点拉取配置禁用应用。
同步配置的过程如下: 用于健康检查的连接,也用来执行一系列类似于select _list_of_columns from runtime_module的select语句。例如:
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;
删除本地配置。例如:
DELETE FROM MySQL_servers;
DELETE FROM MySQL_replication_hostgroups;
向本地配置表中插入已从远端节点检索到的新配置。 在内部执行LOAD module_name TO RUNTIME:这会递增版本号,并创建一个新的checksum。 如果Cluster
_name_save_to_disk=true,再在内部执行SAVE module_name TO DISK。
3、 网络消耗 在上述描述的架构模式中,每个ProxySQL
节点都监控集群中其它所有节点,这是一个很典型并完整的点对点网络。 为了减少网络开销,节点间并不总是交换所有的checksum 信息,而是将所有version 、所有checksum (注意:是每个节点都有一个全局checksum,而不是所有节点共有一个全局checksum)。相结合产生的单个新的 checksum 进行交换。所以一旦这个新的checksum 发生变动,当全局checksum改变,将检索该全局checksum对应的checksum列表,那么得到详细的各个模块的checksum。 通过该技术,200个节点的ProxySQL
集群中,如果每个节点的监控时间间隔为1000ms,每个节点的进/出流量只需50KB的带宽
-
ProxySQL
目前实现的功能 - 支持MySQL组复制(add support for MySQL Group Replication) - 支持Scheduler(add support for Scheduler)[各种脚本支持] -
ProxySQL
未来可能要实现的功能 未来可能要实现的Cluster
不完整特性列表。这些特性目前都还未实现,且实现后有可能会与此处描述的有所区别。 - 支持master选举:ProxySQL
内部将使用master关键字替代leader - 只有master节点是可写/可配置的 - 实现类似于MySQL复制的功能:从master复制到slave。这将允许实时推送配置内容,而非现在使用的主动pull机制 - 实现类似于MySQL复制的功能:从master复制到候选master - 实现类似于MySQL复制的功能:从候选master复制到slave - 将候选master定义为法定票数节点,slave不参与投票
-
问题:如果不同节点在同一时刻加载了不同配置会如何,最后一个才生效吗? 目前还未实现master和master选举的机制。这意味着多个节点上可能会潜在地同时执行load命令(就像是多个master一样),每个实例都会基于时间戳来检测配置冲突,然后再触发自动重新配置。如果所有节点在同一时刻加载的是相同的配置,则不会出现问题;如果所有节点在不同时刻加载了不同的配置,则最后一个配置生效。如果所有节点在同一时刻加载了不同配置,这些不同配置会正常进行传播。直到出现冲突,然后回滚。庆幸的是,每个
ProxySQL
节点都知道其它每个节点的checksum,因此很容易监控并探测到不同的配置。 -
谁负责向所有节点写入配置? 目前,
ProxySQL
集群使用拉取(pull)机制,因此当探测到节点自身需要重新配置时,会从拥有最新配置的节点处拉取配置到本地并应用。 -
何实现选举?Raft协议吗? 关于选举,正在实现计划中,但应该不会采用Raft共识协议。
ProxySQL
使用表来存储配置信息,使用MySQL协议来执行对端健康检查、配置信息的查询请求,以及使用MySQL协议实现心跳等等。所以对于ProxySQL
来说,MySQL协议本身可能是一个更通用的解决方案。 -
某些原因下,如果某个节点无法从远端抓取新的配置会发生什么? 配置更改是异步传播的。因此,某个
ProxySQL
节点可能暂时会无法获取新的配置,例如网络问题。但是,当该实例探测到新的配置时,它会自动去抓取新配置。 -
跨DC的
ProxySQL
集群是否实现?最佳实践是怎样的,每个DC一个ProxySQL
集群吗?ProxySQL
集群没有边界限制,因此一个ProxySQL
集群可以跨多个DC,一个DC内也可以有多个ProxySQL
集群。这依赖于实际应用场景。唯一的限制是,每个ProxySQL
实例只能属于单个ProxySQL
集群。ProxySQL
集群没有名称,为了确保ProxySQL
实例不会加入到错误的集群中,可以让每个ProxySQL
集群采用不同的集群认证凭据。 -
如何引导启动一个
ProxySQL
集群? 很简单:只需让ProxySQL_servers
表中多于一个节点即可。 -
ProxySQL
集群中的其它节点如何知道有新节点? 这个无法自动知道,这是为了防止新节点破坏集群。一个新节点在加入集群时,会立刻从集群中拉取配置,但不会将自己作为可信任的配置源通告出去。要让其它节点知道有一个新的节点,只需向这些节点的ProxySQL_servers
中加入新的节点信息,然后执行loadProxySQL
servers to runtime即可。
2 ProxySQL
集群如何保证数据一致性
2.1 数据如何同步
三个proxy之间互相监控。
远程同步的变量、*正常时,当进行load to runtime时生成一个新的MySQL_servers/MySQL_query_rule.......配置校验码。当配置生效时,才触发sync线程,进行同步。数据差异检查是根据runtime进行检查的,只对memory和disk进行更改,并不触发同步操作。
校验码格式 [INFO] Cluster
: detected a new checksum for MySQL_servers from peer 192.168.1.209:6032, version 99434, epoch 1523986027, checksum 0x9AFEA97C6D622D69 . Not syncing yet ... #检测到209实例传来的新配置文件校验值。
主要包括了:version 、 epoch、 checksum。
2018-04-16 19:10:22 [INFO] Cluster
: detected a peer 192.168.1.209:6032 with MySQL_servers version 99434, epoch 1523986027, diff_check 3. Own version: 3, epoch: 1523876751. Proceeding with remote sync #根据传来的配置校验值,版本号,时间戳,与自己的版本进行比较,决定进行同步操作
ProxySQL
实例刚启动时version=1:ProxySQL
实例将永远不会从version=1的实例处同步配置数据,因为一个刚刚启动的ProxyQL实例不太可能是真相的来源,这可以防止新的连接节点破坏当前集群配置 - epoch:对端runtime_checksums_values中报告的checksum的时间戳epoch值 - checksum:对端runtime_checksums_values中报告的checksum值 - changed_at:探测到checksum发生变化的时间戳 - updated_at:最近一次更新该类配置的时间戳 - diff_check:一个计数器,用于记录探测到的对端和本地checksum值已有多少次不同 需要等待达到阈值后,才会触发重新配置。前面已经说明,在多个ProxySQL
实例同时或极短时间内同时更改配置时,可以让ProxySQL
等待多次探测之后再决定是否从远端同步配置。这个字段正是用于记录探测到的配置不同次数。如果diff_checks不断增加却仍未触发同步操作,这意味着对端不是可信任的同步源,例如对端的version=1。另一方面,如果某对端节点不和ProxySQL
集群中的其它实例进行配置同步,这意味着集群没有可信任的同步源。这种情况可能是因为集群中所有实例启动时的配置都不一样,它们无法自动判断哪个配置才是正确的。可以在某个节点上执行load to runtime,使该节点被选举为该类配置的可信任同步源。
这些值如何获取?通过监控的用户去查询
Admin> SELECT * FROM runtime_checksums_values;
+-------------------+---------+------------+--------------------+
| name | version | epoch | checksum |
+-------------------+---------+------------+--------------------+
| admin_variables | 0 | 0 | |
| MySQL_query_rules | 5 | 1503442167 | 0xD3BD702F8E759B1E |
| MySQL_servers | 1 | 1503440533 | 0x6F8CEF0F4BD6456E |
| MySQL_users | 1 | 1503440533 | 0xF8BDF26C65A70AC5 |
| MySQL_variables | 0 | 0 | |
| `ProxySQL`_servers | 2 | 1503442214 | 0x89768E27E4931C87 |
+-------------------+---------+------------+--------------------+
6 rows in set (0,00 sec)
由于相互监控,所以当配置发生变动时,它们可以立即发现。当其他节点的配置发生变动时,本节点会先去检查一次它自身的配置,因为有可能remote instance 和local instance 同时发生配置变动。 如果比较结果不同: - 如果它们自身的 version = 1,就去找集群内从version > 1的节点处找出epoch最大值的节点,并从该节点拉取配置应用到本地,并立即同步。 如果version >1, 该节点开始统计和其他节点间的differ 数。即开始对探测到的不同配置进行计数。 当 differ 大于 Cluster
name_diffs_before_sync , 并且Cluster
namediffs_before_sync > 0, 就去找集群内 version >1, 并且epoch 最高的节点,并立即同步。也就是说当探测到不同配置的次数超过Cluster
name_diffs_before_sync,且Cluster
name_diffs_before_sync大于0时,找出version > 1且epoch值最大的节点,并从该节点拉取配置禁用应用。
同步配置的过程如下: 用于健康检查的连接,也用来执行一系列类似于select _list_of_columns from runtime_module的select语句。例如:
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;
同步线程发现需要同步
删除本地配置。例如:
DELETE FROM MySQL_servers;
DELETE FROM MySQL_replication_hostgroups;
采用一种拉取的机制,拉取最新/需要改变的配置到本机。
向本地配置表中插入已从远端节点检索到的新配置。 在内部执行LOAD module_name TO RUNTIME:这会递增版本号,并创建一个新的checksum。 如果Cluster
_name_save_to_disk=true,再在内部执行SAVE module_name TO DISK。