转载来自 骏马金龙 https://www.junmajinlong.com
多层次配置系统概述
ProxySQL使用复杂但易于使用的配置系统以便满足以下几个需求:
- 能够简单地动态更新配置文件(主要是为了让ProxySQL在大型生产环境下实现0宕机时间)。兼容MySQL的管理接口可以实现这个目标。
- 能够动态修改尽可能多的配置项,无需重启ProxySQL。
- 能够轻松地回滚无效的配置项。
通过一个多级配置系统,将配置从运行时环境移到内存,并在有需求时持久化到磁盘上,这样就能实现上面的需求。
这3个层次的组成如下:
+-------------------------+
| RUNTIME |
+-------------------------+
/|\ |
| |
[1] | [2] |
| \|/
+-------------------------+
| MEMORY |
+-------------------------+ _
/|\ | |\
| | \
[3] | [4] | \ [5]
| \|/ \
+-------------------------+ +-------------------------+
| DISK | | CONFIG FILE |
+-------------------------+ +-------------------------+
RUNTIME 表示的是ProxySQL线程处理请求时使用的数据结构。
runtime类变量包含:
- 在全局类变量中定义的实际值。
- 后端服务器节点分组后,组中的服务器节点列表。
- 允许连接到ProxySQL的MySQL用户列表。
注意:无法直接修改 RUNTIME 的配置内容,它们总是从下面的层次一层一层应用到runtime上的。
MEMORY (有时也称为 main) 表示的是通过MySQL兼容接口公开的内存数据库。用户可以用MySQL的客户端连接到该接口,并查询ProxySQL的各种配置表或库。
通过该接口可获得的配置表包括:
- mysql_servers -- ProxySQL需要连接的后端服务器节点列表。
- mysql_users -- 连接到ProxySQL的用户及对应密码的列表。注意,ProxySQL也会按照该列表中的用户配置去连接后端服务器节点。
- mysql_query_rules -- ProxySQL根据这些规则将请求路由到后端服务器。这些规则有时会重写查询语句或者将已执行的结果进行缓存。
- global_variables -- ProxySQL使用的全局变量列表,以及允许谁可以在runtime环境下进行调整。
例如:
mysql> select * from global_variables limit 3;
+----------------------------------+----------------+
| variable_name | variable_value |
+----------------------------------+----------------+
| mysql-connect_retries_on_failure | 5 |
| mysql-connect_retries_delay | 1 |
| mysql-connect_timeout_server_max | 10000 |
+----------------------------------+----------------+
- mysql_collations -- ProxySQL可用的MySQL排序规则列表。它们是直接从客户端库中提取出来的。
- [debug版本专有] debug_levels -- ProxySQL发出的调试语句的类型列表及其详细级别。这允许我们在运行时轻松配置日志中有哪些语句,以便调试不同的问题。这只在调试版本中可用,因为它会影响性能。
DISK 和 CONFIG FILE
DISK 表示的是一个在磁盘上的SQLite3数据库,默认位置为$(DATADIR)/proxysql.db。重启时,那些没有持久化到磁盘的内存配置会丢失,因此有必要将内存中的配置持久化到 DISK 。 CONFIG 文件是传统的配置文件,下一节我们将看到其它和配置层的关系。
下面,我们将描述一些对ProxySQL的基本操作时,每个层次的生命周期。例如:第一次启动ProxySQL(startup)、startup、restart、shutdown等基础操作。
Startup
对于一次普通的启动,ProxySQL会读取它的配置文件(如果存在的话)来决定它的datadir。至于下一步会发生什么,取决于在datadir下是否存在它的数据库文件(即那个SQLite3库)。
如果数据库文件存在,则ProxySQL根据该数据库文件中的内容初始化它的内存配置。如果数据库文件不存在,但配置文件存在,将解析配置文件内容并加载到内存数据库中,然后将它持久化到数据库文件中,最后加载到runtime环境。需要注意的是,如果存在数据库文件,则不会解析传统的配置文件。因此,对于普通的ProxySQL启动行为,ProxySQL只从数据库文件来初始化它的运行环境。
注意:ProxySQL 1.4.4引入了两个新的通用变量(general variables),它们一定会从配置文件中解析。以下是一定会从传统配置文件中解析的变量,即使数据库文件已经存在。
-
datadir
:该变量定义ProxySQL的数据目录,数据库文件、日志以及其它一些文件都会存放到这个目录下。 -
restart_on_missing_heartbeats
:(1.4.4版本引入)如果MySQL线程丢失了心跳,ProxySQL将发送一个SIGABRT
信号并重启这个线程。默认值为10。(见https://github.com/malongshuai/proxysql/wiki/Watchdog)。 -
execute_on_exit_failure
:(1.4.4版本引入)如果设置了该变量,ProxySQL父进程将在每次ProxySQL崩溃的时候执行已经定义好的脚本。建议使用它来生成一些崩溃时的警告和日志。注意,ProxySQL的重启速度可能只有几毫秒,因此很多其它的监控工具可能无法探测到ProxySQL的一次普通故障,此时可使用该变量。
第一次startup (或者使用--initial选项)
第一次启动ProxySQL时,会从传统配置文件中加载配置项来初始化memory和runtime的配置。然后将内存中的配置持久化到SQLite数据库中。可使用--initial选项来强制初始化ProxySQL,这会将SQLite数据库重置为最原始状态(即和传统配置文件里的配置保持一致的状态),并在必要时重命名已存在的SQLite数据库文件名。
Reload(或--reload flag)
如果proxysql使用--reload选项,则将尝试对传统配置文件和数据库文件进行合并,然后进入普通的启动过程。
ProxySQL无法保证在两个配置源存在冲突时能成功合并,因此用户应该去验证合并行为是否达到预期合并结果。
在runtime下修改配置
要修改runtime的配置,需要使用ProxySQL的管理接口,端口号默认6032。连接后,可用通过查询来获取相关表:
mysql> show tables;
+-------------------+
| tables |
+-------------------+
| mysql_servers |
| mysql_users |
| mysql_query_rules |
| global_variables |
| mysql_collations |
| debug_levels |
+-------------------+
6 rows in set (0.01 sec)
管理接口中的每个表是根据它们的角色进行定义命名的:
- mysql_servers:包含ProxySQL需要连接的后端服务器节点列表。
- mysql_users:包含ProxySQL用来连接后端节点时使用用户凭证列表。
- mysql_query_rules:包含ProxySQL将请求路由到后端节点、缓存、重写SQL时使用的规则。
- global_variables:包含ProxySQL进行初始化时所定义的MySQL变量以及管理变量。
- debug_levels:只在debug版本中才有效。
这些表代表的是上面图中(本文最前面的多层次配置系统图)的内存数据库部分,它们可使用标准的SQL查询来配置。为了将此处配置上移(即应用到runtime)、或下移(即持久化到disk上),请看下面的内容。
这些表中的详细信息,请参阅它们专门的文档说明。
在不同层级间移动配置
为了将配置持久化到磁盘或者应用到runtime,在管理接口下有一系列管理命令来实现它们。当你理解了这3个层次是如何产生作用的,它们的意义就会变得很明朗。在下面每个命令的解释中,还使用了一个数字序号,这个序号对应的是上面图中(本文最前面的多层次配置系统图)的序号。
要重新配置MySQL用户,可执行下面的其中一个命令:
[1] LOAD MYSQL USERS FROM MEMORY / LOAD MYSQL USERS TO RUNTIME
将内存数据库中的配置加载到runtime数据结构,反之亦然。
[2] SAVE MYSQL USERS TO MEMORY / SAVE MYSQL USERS FROM RUNTIME
将MySQL用户从runtime持久化到内存数据库。
[3] LOAD MYSQL USERS TO MEMORY / LOAD MYSQL USERS FROM DISK
从磁盘数据库中加载MySQL用户到内存数据库中。
[4] SAVE MYSQL USERS FROM MEMORY / SAVE MYSQL USERS TO DISK
将内存数据库中的MySQL用户持久化到磁盘数据库中。
[5] LOAD MYSQL USERS FROM CONFIG
从配置文件中加载MySQL用户到内存数据库中。
要处理MySQL server:
[1] LOAD MYSQL SERVERS FROM MEMORY / LOAD MYSQL SERVERS TO RUNTIME
从内存数据库中将MySQL server加载到runtime。
[2] SAVE MYSQL SERVERS TO MEMORY / SAVE MYSQL SERVERS FROM RUNTIME
将MySQL server从runtime持久化到内存数据库中。
[3] LOAD MYSQL SERVERS TO MEMORY / LOAD MYSQL SERVERS FROM DISK
从磁盘数据库中加载MySQL server到内存数据库。
[4] SAVE MYSQL SERVERS FROM MEMORY / SAVE MYSQL SERVERS TO DISK
从内存数据库中将MySQL server持久化到磁盘数据库中。
[5] LOAD MYSQL SERVERS FROM CONFIG
从配置文件中加载MySQL server到内存数据库中。
要处理MySQL的查询规则(mysql query rules):
[1] LOAD MYSQL QUERY RULES FROM MEMORY / LOAD MYSQL QUERY RULES TO RUNTIME
将MySQL query rules从内存数据库加载到runtime数据结构。
[2] SAVE MYSQL QUERY RULES TO MEMORY / SAVE MYSQL QUERY RULES FROM RUNTIME
将MySQL query rules从runtime数据结构中持久化到内存数据库。
[3] LOAD MYSQL QUERY RULES TO MEMORY / LOAD MYSQL QUERY RULES FROM DISK
从磁盘数据库中加载MySQL query rules到内存数据库中。
[4] SAVE MYSQL QUERY RULES FROM MEMORY / SAVE MYSQL QUERY RULES TO DISK
将MySQL query rules从内存数据库中持久化到磁盘数据库中。
[5] LOAD MYSQL QUERY RULES FROM CONFIG
从配置文件中加载MySQL query rules到内存数据库中。
要处理MySQL变量(MySQL variables):
[1] LOAD MYSQL VARIABLES FROM MEMORY / LOAD MYSQL VARIABLES TO RUNTIME
将MySQL variables从内存数据库加载到runtime数据结构。
[2] SAVE MYSQL VARIABLES TO MEMORY / SAVE MYSQL VARIABLES FROM RUNTIME
将MySQL variables从runtime数据结构中持久化到内存数据中。
[3] LOAD MYSQL VARIABLES TO MEMORY / LOAD MYSQL VARIABLES FROM DISK
从磁盘数据库中加载MySQL variables到内存数据库中。
[4] SAVE MYSQL VARIABLES FROM MEMORY / SAVE MYSQL VARIABLES TO DISK
将MySQL variables从内存数据库中持久化到磁盘数据库中。
[5] LOAD MYSQL VARIABLES FROM CONFIG
从配置文件中加载MySQL variables到内存数据库中。
要处理管理变量(admin variables):
[1] LOAD ADMIN VARIABLES FROM MEMORY / LOAD ADMIN VARIABLES TO RUNTIME
将admin variables从内存数据库加载到runtime数据结构。
[2] SAVE ADMIN VARIABLES TO MEMORY / SAVE ADMIN VARIABLES FROM RUNTIME
将admin variables从runtime持久化到内存数据库中。
[3] LOAD ADMIN VARIABLES TO MEMORY / LOAD ADMIN VARIABLES FROM DISK
从磁盘数据库中加载admin variables到内存数据库中。
[4] SAVE ADMIN VARIABLES FROM MEMORY / SAVE ADMIN VARIABLES TO DISK
将admin variables从内存数据库中持久化到磁盘数据库。
[5] LOAD ADMIN VARIABLES FROM CONFIG
从配置文件中加载admin variables到内存数据库中。
注意:上面的命令支持如下简写格式:
MEM 是 MEMORY 的缩写
RUN 是 RUNTIME 的缩写
例如,下面两个命令是等价的:
SAVE ADMIN VARIABLES TO MEMORY
SAVE ADMIN VARIABLES TO MEM
总结
在理解了上面的3层系统是如何工作之后,这里有几个最常用的命令:如何让修改的配置生效(runtime),以及如何持久化到磁盘上(disk)。记住,只要不是加载到runtime,修改的配置就不会生效。
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;
Troubleshooting
注意,只有在加载到runtime时才会去做最后的有效性验证。在保存到内存数据库或持久化到磁盘上时,都不会发生任何警告或错误。当加载到runtime时,如果出现错误,将恢复为之前保存的状态。这时可去检查错误日志。
例如: [WARNING] Impossible to set variable monitor_read_only_interval with value "0". Resetting to current "1500".