文章转载自:https://blog.csdn.net/n88Lpo/article/details/79608639

前言

在ProxySQL 1.4.2 之前,ProxySQL 单点的解决方法有配合keepalived 使用来实现ProxySQL 的主备,但是需要在主备上配置两份完全相同的路由或规则,如果再没有自动运维平台,同时维护两份配置的也是相当麻烦的。而且目前主流的云环境,均不支持keepalived 使用的 VRRP 协议,所以在云环境上就无法通过keepalived 来实现故障切换。从1.4.2 开始,ProxySQL 开始支持原生的 Cluster,这就有效的解决了之前需要借助第三方工具才能解决的单点问题。

另外:ProxySQL Cluster 对MySQL Group Replication 的支持,和任务调度功能,也正在开发中。

ProxySQL Cluster

ProxySQL安装后默认配置文件内容

# cat /etc/proxysql.cnf

#file proxysql.cfg

########################################################################################
# This config file is parsed using libconfig , and its grammar is described in:
# http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-File-Grammar
# Grammar is also copied at the end of this file
######################################################################################## ########################################################################################
# IMPORTANT INFORMATION REGARDING THIS CONFIGURATION FILE:
########################################################################################
# On startup, ProxySQL reads its config file (if present) to determine its datadir.
# What happens next depends on if the database file (disk) is present in the defined
# datadir (i.e. "/var/lib/proxysql/proxysql.db").
#
# If the database file is found, ProxySQL initializes its in-memory configuration from
# the persisted on-disk database. So, disk configuration gets loaded into memory and
# then propagated towards the runtime configuration.
#
# If the database file is not found and a config file exists, the config file is parsed
# and its content is loaded into the in-memory database, to then be both saved on-disk
# database and loaded at runtime.
#
# IMPORTANT: If a database file is found, the config file is NOT parsed. In this case
# ProxySQL initializes its in-memory configuration from the persisted on-disk
# database ONLY. In other words, the configuration found in the proxysql.cnf
# file is only used to initial the on-disk database read on the first startup.
#
# In order to FORCE a re-initialise of the on-disk database from the configuration file
# the ProxySQL service should be started with "systemctl start proxysql-initial".
#
######################################################################################## datadir="/var/lib/proxysql"
errorlog="/var/lib/proxysql/proxysql.log" admin_variables=
{
admin_credentials="admin:admin"
# mysql_ifaces="127.0.0.1:6032;/tmp/proxysql_admin.sock"
mysql_ifaces="0.0.0.0:6032"
# refresh_interval=2000
# debug=true
} mysql_variables=
{
threads=4
max_connections=2048
default_query_delay=0
default_query_timeout=36000000
have_compress=true
poll_timeout=2000
# interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
interfaces="0.0.0.0:6033"
default_schema="information_schema"
stacksize=1048576
server_version="5.5.30"
connect_timeout_server=3000
# make sure to configure monitor username and password
# https://github.com/sysown/proxysql/wiki/Global-variables#mysql-monitor_username-mysql-monitor_password
monitor_username="monitor"
monitor_password="monitor"
monitor_history=600000
monitor_connect_interval=60000
monitor_ping_interval=10000
monitor_read_only_interval=1500
monitor_read_only_timeout=500
ping_interval_server_msec=120000
ping_timeout_server=500
commands_stats=true
sessions_sort=true
connect_retries_on_failure=10
} # defines all the MySQL servers
mysql_servers =
(
# {
# address = "127.0.0.1" # no default, required . If port is 0 , address is interpred as a Unix Socket Domain
# port = 3306 # no default, required . If port is 0 , address is interpred as a Unix Socket Domain
# hostgroup = 0 # no default, required
# status = "ONLINE" # default: ONLINE
# weight = 1 # default: 1
# compression = 0 # default: 0
# max_replication_lag = 10 # default 0 . If greater than 0 and replication lag passes such threshold, the server is shunned
# },
# {
# address = "/var/lib/mysql/mysql.sock"
# port = 0
# hostgroup = 0
# },
# {
# address="127.0.0.1"
# port=21891
# hostgroup=0
# max_connections=200
# },
# { address="127.0.0.2" , port=3306 , hostgroup=0, max_connections=5 },
# { address="127.0.0.1" , port=21892 , hostgroup=1 },
# { address="127.0.0.1" , port=21893 , hostgroup=1 }
# { address="127.0.0.2" , port=3306 , hostgroup=1 },
# { address="127.0.0.3" , port=3306 , hostgroup=1 },
# { address="127.0.0.4" , port=3306 , hostgroup=1 },
# { address="/var/lib/mysql/mysql.sock" , port=0 , hostgroup=1 }
) # defines all the MySQL users
mysql_users:
(
# {
# username = "username" # no default , required
# password = "password" # default: ''
# default_hostgroup = 0 # default: 0
# active = 1 # default: 1
# },
# {
# username = "root"
# password = ""
# default_hostgroup = 0
# max_connections=1000
# default_schema="test"
# active = 1
# },
# { username = "user1" , password = "password" , default_hostgroup = 0 , active = 0 }
) #defines MySQL Query Rules
mysql_query_rules:
(
# {
# rule_id=1
# active=1
# match_pattern="^SELECT .* FOR UPDATE$"
# destination_hostgroup=0
# apply=1
# },
# {
# rule_id=2
# active=1
# match_pattern="^SELECT"
# destination_hostgroup=1
# apply=1
# }
) scheduler=
(
# {
# id=1
# active=0
# interval_ms=10000
# filename="/var/lib/proxysql/proxysql_galera_checker.sh"
# arg1="0"
# arg2="0"
# arg3="0"
# arg4="1"
# arg5="/var/lib/proxysql/proxysql_galera_checker.log"
# }
) mysql_replication_hostgroups=
(
# {
# writer_hostgroup=30
# reader_hostgroup=40
# comment="test repl 1"
# },
# {
# writer_hostgroup=50
# reader_hostgroup=60
# comment="test repl 2"
# }
) # http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-File-Grammar
#
# Below is the BNF grammar for configuration files. Comments and include directives are not part of the grammar, so they are not included here.
#
# configuration = setting-list | empty
#
# setting-list = setting | setting-list setting
#
# setting = name (":" | "=") value (";" | "," | empty)
#
# value = scalar-value | array | list | group
#
# value-list = value | value-list "," value
#
# scalar-value = boolean | integer | integer64 | hex | hex64 | float
# | string
#
# scalar-value-list = scalar-value | scalar-value-list "," scalar-value
#
# array = "[" (scalar-value-list | empty) "]"
#
# list = "(" (value-list | empty) ")"
#
# group = "{" (setting-list | empty) "}"
#
# empty =

当前版本的ProxySQL Cluster 有2个主要组件:

  • monitoring
  • re-configuration

这2个组件对原有的4个表都是支持的:

  • mysql_query_rules
  • mysql_servers
  • mysql_users
  • proxysql _servers

Monitoring

为了监控Cluster,ProxySQL Cluster 新加了部分表、命令和变量。

admin variables

1.同步有关的参数

参数 默认值 描述
admin-checksum_mysql_query_rules true =true时,每次执行LOAD MYSQL QUERY RULES TO RUNTIME时,proxy都会生成一个新的配置checksum。=false时,新的配置不会自动被广播,也不会其他节点同步。
admin-checksum_mysql_servers true =true时,每次执行LOAD MYSQL serversTO RUNTIME时,proxy都会生成一个新的配置checksum。=false时,新的配置不会自动被广播,也不会其他节点同步。
admin-checksum_mysql_users true =true时,每次执行LOAD MYSQL usersTO RUNTIME时,proxy都会生成一个新的配置checksum。=false时,新的配置不会自动被广播,也不会其他节点同步。

2.认证参数

集群间,Proxy 为了监控其他Proxy 实例需要认证参数:admin-cluster_username 和 admin-cluster_password。而且这2个参数指定的用户名/密码还必须配置到参数 admin-admin_credentials 中,否则会无法连接到其他proxy

admin_credentials="admin:admin;cluster1:secret1pass"

多个用户名/密码之间使用分号进行分割

3.检查间隔和频率相关参数

参数 默认值 描述
admin-cluster_check_interval_ms 1000 定义进行checksum的时间间隔。10~300000
admin-cluster_check_status_frequency 10

4.持久化相关参数

当有新的集群配置被同步到远端proxy ,并且load to runtime 后,可以控制是否立即将配置自动存盘。 query rules, servers, users 和proxysql servers 分别有admin-cluster_XXX_save_to_disk 相关的参数,默认是 true。

有些原因,可能造成多个ProxySQL 实例在同一时间发生reconfigured 的情况:

  • 所有proxy 实例都在监控一个MySQL 集群,并且都发现了MySQL 集群发生了failover。在很短的时间内(通常小于1s),所有proxy 实例都会发生同样的配置变更,并且不需要和其他实例进行同步
  • 所有实例都探测到网络异常或者MySQL DB 反应慢,那所有proxy 实例都会避开该节点。此时所有proxy 实例都会执行同样的动作,从而也不用从其他实例上同步配置。
  • 极端情况下,一个slave 由于lag 很大,并且主动从集群中退出。此时所有proxy 实例也都会发生相应的reconfiguration。

5.延迟同步

ProxySQL Cluster 可以定义达到多少个checksum 不同之后,才在集群内部进行配置同步。

query rules, servers, users 和proxysql servers 分别有admin-cluster_XXX_diffs_before_sync 相关的参数,取值范围0 ~ 1000,0 代表从不同步。默认3。

configuration table

1.proxysql_servers

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) )

注意: weight 在当前版本中还未正式启用。

2.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))

runtime_checksums_values 记录当 load to runtime 被执行时系统的信息。

  • epoch : 记录load to runtime 被执行的时间
  • checksum: 记录每个组件在load to runtime 时的checksum 值
  • version :记录load to run 的次数。每次重启实例后,该值都会被重置为 1

目前6个组件中只有4个可以生成checksum,不能生成的组件是:admin_variables,mysql_variables。 checnsum 只有在执行了load to run ,并且admin-checksum_XXX = true 时,才可以正常生成。

state tables

有三个表被加入到stat 表中。

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) )
  • changed_at :探测到发生checksum change 的时间
  • updated_at :上次更新checksum 的时间
  • diff_check :计数器,用来记录本地proxy 和远端proxy checksum 不同的次数,当达到参数cluster_*_diffs_before_sync 定义的阀值后,才能触发集群的同步动作。如果 diff_check 很大,但是又没触发同步动作,那远端的proxy 就不是一个可靠的数据源。

2.stats_proxysql_servers_metrics

该表用来显示群集模块在各个实例中执行 SHOW MYSQL STATUS 时,当前系统的部分指标。目前该表只是用来debug 的,在未来该表的各个指标将用来反映各个实例的健康状态。

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) )
  • weight: 和proxysql_servers.weight 一样,暂时未使用。
  • response_time_ms:单位毫秒。执行show mysql status 的响应时间。
  • uptime_s: 各个实例的启动时间。
  • queries:各个实例上已经执行的query 数量
  • last_check_ms:上一次执行 show mysql status 距今的时间,单位毫秒。
  • Client_Connections_connected :已经连接上来的客户端连接数
  • Client_Connections_created:被创建的客户端连接数

3.stats_proxysql_servers_status

在目前的1.4.6 版本中,该表还未启用。

Re-configuration

因为集群间,所有节点都是相互监控的。所以当配置发生变动时,它们可以立即发现。当其他节点的配置发生变动时,本节点会先去检查一次它自身的配置,因为有可能remote instance 和local instance 同时发生配置变动。如果不同:

  • 如果它们自身的 version = 1,就去找集群内 version >1,并且 epoch 最高的节点,并立即同步。
  • 如果version >1, 该节点开始统计和其他节点间的differ 数。
    • 当 differ 大于 cluster__name___diffs_before_sync , 并且cluster__name__diffs_before_sync > 0, 就去找集群内 version >1, 并且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;
  • 删除本地配置。例如:
DELETE FROM mysql_servers;
DELETE FROM mysql_replication_hostgroups;
  • 将新的配置insert 到本地表
  • 内部提交LOAD module_name TO RUNTIME。 对应的version 会增加,并且生成一个新的 checksum
  • 如果cluster__name__save_to_disk =true,还会内部执行 SAVE module_name TO DISK。

网络消耗

ProxySQL Cluster 中每个节点都在监控其他节点,是个很典型的点对点的网络。 为了减少网络开销,节点间并不总是交换所有的checksum 信息,而是将所有version 、所有checksum 相结合产生的单个新的 checksum 进行交换。所以一旦这个新的checksum 发生变动,那么得到详细的各个模块的checksum。 在一个200个节点的集群中,如果每个节点每 1000ms 去探测一次,每个节点需要 50KB 的带宽。

后续问题

  1. ProxySQL 目前实现的功能
  • 支持MySQL组复制(add support for MySQL Group Replication)
  • 支持Scheduler(add support for Scheduler)
  1. ProxySQL 未来可能要实现的功能

    未来可能要实现的Cluster不完整特性列表。这些特性目前都还未实现,且实现后有可能会与此处描述的有所区别。
  • 支持master选举:ProxySQL内部将使用master关键字替代leader
  • 只有master节点是可写/可配置的
  • 实现类似于MySQL复制的功能:从master复制到slave。这将允许实时推送配置内容,而非现在使用的主动pull机制
  • 实现类似于MySQL复制的功能:从master复制到候选master
  • 实现类似于MySQL复制的功能:从候选master复制到slave
  • 将候选master定义为法定票数节点,slave不参与投票

3) 问题:如果不同节点在同一时刻加载了不同配置会如何,最后一个才生效吗?

目前还未实现master和master选举的机制。这意味着多个节点上可能会潜在地同时执行load命令(就像是多个master一样),每个实例都会基于时间戳来检测配置冲突,然后再触发自动重新配置。如果所有节点在同一时刻加载的是相同的配置,则不会出现问题;如果所有节点在不同时刻加载了不同的配置,则最后一个配置生效。如果所有节点在同一时刻加载了不同配置,这些不同配置会正常进行传播。直到出现冲突,然后回滚。庆幸的是,每个ProxySQL节点都知道其它每个节点的checksum,因此很容易监控并探测到不同的配置。

4)谁负责向所有节点写入配置?

目前,ProxySQL集群使用拉取(pull)机制,因此当探测到节点自身需要重新配置时,会从拥有最新配置的节点处拉取配置到本地并应用。

5)何实现选举?Raft协议吗?

关于选举,正在实现计划中,但应该不会采用Raft共识协议。ProxySQL使用表来存储配置信息,使用MySQL协议来执行对端健康检查、配置信息的查询请求,以及使用MySQL协议实现心跳等等。所以对于ProxySQL来说,MySQL协议本身相比Raft协议要更多才多艺。

6)某些原因下,如果某个节点无法从远端抓取新的配置会发生什么?

配置更改是异步传播的。因此,某个ProxySQL节点可能暂时会无法获取新的配置,例如网络问题。但是,当该实例探测到新的配置时,它会自动去抓取新配置。

7)跨DC的ProxySQL集群是否实现?最佳实践是怎样的,每个DC一个ProxySQL集群吗?

ProxySQL集群没有边界限制,因此一个ProxySQL集群可以跨多个DC,一个DC内也可以有多个ProxySQL集群。这依赖于实际应用场景。唯一的限制是,每个ProxySQL实例只能属于单个ProxySQL集群。ProxySQL集群没有名称,为了确保ProxySQL实例不会加入到错误的集群中,可以让每个ProxySQL集群采用不同的集群认证凭据。

8)如何引导启动一个ProxySQL集群?

很简单:只需让proxysql_servers表中多于一个节点即可。

9)ProxySQL集群中的其它节点如何知道有新节点?

这个无法自动知道,这是为了防止新节点破坏集群。一个新节点在加入集群时,会立刻从集群中拉取配置,但不会将自己作为可信任的配置源通告出去。要让其它节点知道有一个新的节点,只需向这些节点的proxysql_servers中加入新的节点信息,然后执行load proxysql servers to runtime即可。

ProxySQL Cluster 概述的更多相关文章

  1. ProxySQL Cluster 高可用集群环境部署记录

    ProxySQL在早期版本若需要做高可用,需要搭建两个实例,进行冗余.但两个ProxySQL实例之间的数据并不能共通,在主实例上配置后,仍需要在备用节点上进行配置,对管理来说非常不方便.但是Proxy ...

  2. 重要参考步骤---ProxySQL Cluster 集群搭建步骤

    环境 proxysql-1:192.168.20.202 proxysql-2:192.168.20.203 均采用yum方式安装 # cat <<EOF | tee /etc/yum.r ...

  3. ProxySQL Cluster 高可用集群 + MySQL MGR环境部署 (多写模式) 部署记录

    文章转载自:https://blog.51cto.com/u_6215974/4937192 ProxySQL 在早期版本若需要做高可用,需要搭建两个实例,进行冗余.但两个ProxySQL实例之间的数 ...

  4. proxysql cluster 的搭建

    文章转载自:https://blog.51cto.com/lee90/2298804 官方文档: https://proxysql.com/blog/proxysql-cluster 环境架构 在一主 ...

  5. elasticsearch cluster 概述

    在源码概述中我们分析过,elasticsearch源码从功能上可以分为分布式功能和数据功能,接下来这几篇会就分布式功能展开.这里首先会对cluster作简单概述,然后对cluster所涉及的主要功能详 ...

  6. 【ProxySQL】ProxySQL Cluster的搭建

    文章转载自:https://blog.51cto.com/l0vesql/2104643 背景 早期的ProxySQL若需要做高可用,需要搭建两个实例,进行冗余.但两个ProxySQL实例之间的数据并 ...

  7. ProxySQL Cluster的搭建

    环境: proxysql-1.4.10-1-centos7.x86_64 db210 192.168.99.210 老节点,已经做成mysql配置和读写分离设置db211 192.168.99.211 ...

  8. MySQL Cluster配置概述

    一.     MySQL Cluster概述 MySQL Cluster 是一种技术,该技术允许在无共享的系统中部署“内存中”数据库的 Cluster .通过无共享体系结构,系统能够使用廉价的硬件,而 ...

  9. MySQL Cluster(MySQL 集群) 初试(转)

    作/译者:叶金荣(imysql#imysql.com>),来源:http://imysql.com,欢迎转载. 作/译者:叶金荣(Email: ),来源:http://imysql.cn,转载请 ...

随机推荐

  1. JAVA学习的第一周

    这是发表的第一篇博客,关于Java编程的学习体会如下 1.了解Java的产生与发展时机:1995左右出现Java语言,然后Java的最主要的特点是"跨平台".对于跨平台我不太理解, ...

  2. Java中运算符和方法的区别

    1.多数情况下,运算符是程序语言里固有的.比如+,-,*,/.可以直接被编译为机器语言而无需再调用其它方法编译. 2.运算符在被定义时会被规定运算的优先级.如4+3*3,会得到13.而不是21. 3. ...

  3. java---数组(重点概念)

    一.什么是数组 程序=算法+数据结构 数据结构:把数据按照某种特定的结构保存,设计一个合理的数据是解决问题的关键: 数组:是一种用于存储多个相同类型数据类型 的存储模型: 数组的特定结构:相同类型组成 ...

  4. 关于 Python 的 import

    好久以前就被 Python 的相对与绝对导入所困扰.去年粗浅探究后自以为完全理解,近来又因 sys.path[0] 和 os.getcwd() 的不一致而刷新了认知... Python 官方文档 5. ...

  5. 互联网界的IT巨变:从DOS的编辑器,到如今的无代码开发

    众所周知,Borland Pascal.Turbo Pascal.Turbo C等这类开发工具,都习惯自带IDE. 因此,我产生了一个大胆的想法. DOS时代下的Turbo C 如果说Anders这类 ...

  6. Hadoop - MapReduce 过程

    Hadoop - MapReduce 一.MapReduce设计理念 map--->映射 reduce--->归纳 mapreduce必须构建在hdfs之上的一种大数据离线计算框架 在线: ...

  7. ServerlessBench 2.0:华为云联合上海交大发布Serverless基准测试平台

    摘要:华为云联合上海交大重磅推出ServerlessBench 2.0,为社区提供涵盖12类基准测试用例.新增5大类跨平台测试用例.4大类关键特性指标.且多平台兼容的Serverless开放基准测试集 ...

  8. 前端(五)-Vue简单基础

    1. Vue概述 Vue (读音/vju/, 类似于view)是一套用于构建用户界面的渐进式框架,发布于2014年2月. 与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用. Vue的核心库只 ...

  9. 【Java面试】生产环境服务器变慢,如何诊断处理?

    "生产环境服务器变慢?如何诊断处理" 这是最近一些工作5年以上的粉丝反馈给我的问题,他们去一线大厂面试,都被问到了这一类的问题. 今天给大家分享一下,面试过程中遇到这个问题,我们应 ...

  10. axios post请求变为options请求的解决方法

    全局配置 axios.defaults.headers['Content-Type']='application/x-www-form-urlencoded' 注意:使用全局配置会导致所有请求头的'C ...