
作者:Miguel Araújo,Oracle MySQL 团队首席软件工程师
原文:https://dev.mysql.com/blog-archive/smarter-query-routing-with-mysql-routing-guidelines/,爱可生开源社区翻译。
本文约 3400 字,预计阅读需要 15 分钟。

作者:Miguel Araújo
随着 MySQL Shell[1] 和 MySQL Router[2] 9.2.0 创新版的发布,我们引入了 Routing Guidelines[3](本文译为:路由指南)这一新功能,使 MySQL 数据库架构中的查询路由更加动态、灵活且声明式。
MySQL 社区版和企业版 均提供此功能,它能够根据特定的应用需求定制查询路由,并确保在 MySQL InnoDB Cluster、ClusterSet 和 ReplicaSet 拓扑结构中无缝分配查询。借助 路由指南,管理员能够获得对查询流的更大控制权,以可扩展且弹性的方式优化性能和可用性。
在现代数据库架构中,高效的查询路由对于实现性能、可扩展性、弹性和适应性至关重要。
MySQL Router 在 MySQL 架构中扮演着核心角色,作为中间件动态地将客户端连接引导至适当的 MySQL 服务器实例。它能够无缝集成到 MySQL 部署中,支持故障转移、负载均衡和查询分发。

MySQL Router
然而,随着 MySQL 拓扑结构的复杂性增加,对连接路由的控制需求也变得更加明显。
虽然对于 简单部署 来说,默认的路由行为是有效的,但 MySQL Router 的默认路由行为可能不再足以应对处理多样化场景所需的特定需求。
考虑一个跨越多个区域的 ClusterSet,例如一个主区域的主集群和另一个区域的副本集群。

多集群拓扑
通过传统路由,MySQL Router 仅应用基本的读写规则,导致次优的查询路由,从而产生:
现在,考虑一个由 InnoDB Cluster 和多个读副本组成的拓扑结构,用于 读扩展 和 测试较新的 MySQL 版本。不同的应用程序有不同的需求:

InnoDB Cluster 拓扑结构
传统路由无法根据 特定用户、应用程序、平台 或 查询类型 区分流量。
它对所有连接应用相同的 读写分离,使得无法确保 前端流量被引导至副节点,资源密集型查询被引导至适当的读副本,以及测试查询在特定 MySQL 版本上隔离,而不干扰生产工作负载。
另一个例子是多租户应用程序,其中不同客户的查询应被路由到特定的数据库或模式。
没有会话感知,MySQL Router 缺乏在没有复杂应用程序端逻辑的情况下强制执行基于租户的查询路由的能力。
许多 现实工作负载 有 专门的路由需求,而传统路由无法处理,例如:
这些限制表明,为什么需要一个更 适应性强 和 上下文感知 的路由解决方案。

Routing Guidelines
为了解决这些挑战,MySQL 数据库架构引入了路由指南 - 一种旨在使用声明式规则动态调整查询路由的功能,这些规则考虑了各种因素。
与传统的自动路由不同,路由指南允许管理员定义声明式规则,智能地根据以下因素在 MySQL 实例之间分配查询:
这提供了一种 可定制的、规则驱动的方法,可用于各种目的,例如:
通过提供 细粒度的控制,路由指南允许 MySQL Router 做出更智能的决策,根据应用程序的具体需求量身定制。
路由指南使用 MySQL Shell 中的 AdminAPI 定义,允许管理员声明式地创建和管理路由规则。
路由指南由 两个关键组件 组成:
示例路由指南:
{
"destinations": [
{
"match": "$.server.memberRole = PRIMARY AND $.server.clusterRole = PRIMARY",
"name": "Primary"
},
{
"match": "$.server.memberRole = SECONDARY AND $.server.clusterRole = REPLICA",
"name": "ReplicaClusterSecondary"
},
{
"match": "$.server.memberRole = READ_REPLICA AND $.server.clusterRole = REPLICA",
"name": "ReplicaClusterReadReplica"
}
],
"name": "default",
"routes": [
{
"connectionSharingAllowed": true,
"destinations": [
{
"classes": ["Primary"],
"priority": 0,
"strategy": "round-robin"
}
],
"enabled": true,
"match": "$.session.targetPort = $.router.port.rw",
"name": "rw"
},
{
"connectionSharingAllowed": true,
"destinations": [
{
"classes": ["ReplicaClusterSecondary", "ReplicaClusterReadReplica"],
"priority": 0,
"strategy": "round-robin"
},
{
"classes": ["Primary"],
"priority": 1,
"strategy": "round-robin"
}
],
"enabled": true,
"match": "$.session.targetPort = $.router.port.ro",
"name": "ro"
}
],
"version": "1.0"
}
在这个路由指南中:
这个示例展示了路由指南如何提供对查询路由的细粒度控制,实现跨拓扑结构的高效负载均衡和故障转移管理。
路由指南依赖于 匹配表达式,这些表达式作为管理查询路由的规则。这些表达式允许管理员:
AND、OR 和 NOT 组合 条件,以获得更高级的灵活性。通过利用匹配表达式,路由指南提供了精确且动态的查询路由,确保每个查询由最合适的 MySQL 实例处理。
在上面的示例中,我们使用了具有以下预定义变量的匹配表达式:
变量 | 目的 | 示例 |
|---|---|---|
$.server.memberRole | 识别 MySQL 实例的角色。 | PRIMARY, SECONDARY, READ_REPLICA |
$.server.clusterRole | 定义服务器是主集群还是副本集群的一部分。 | REPLICA, PRIMARY |
$.session.targetPort | 指向客户端请求的端口,允许基于会话类型的路由决策。 | 3306 |
$.router.port.rw | MySQL Router 中读写流量的端口。 | 6446 |
$.router.port.ro | MySQL Router 中只读流量的端口。 | 6447 |
... | ... | ... |
然而,还有许多其他预定义变量[4] 和函数可用。
除了 预定义变量,路由指南支持 各种内置函数,这些函数允许更高级的路由逻辑。
这些函数允许执行诸如 匹配网络子网、字符串操作 和 评估正则表达式 等操作。
这里有一些示例:
函数 | 目的 | 示例 |
|---|---|---|
NETWORK('str', 'int') | 计算给定地址和位掩码的网络地址。以字符串形式返回网络地址。 | NETWORK('10.1.1.120', 24)返回范围 10.1.1.0 到 10.1.1.255。 |
CONTAINS('str1', 'str2') | 检查 str2 是否是 str1 的子字符串,不区分大小写。 | CONTAINS('foobar', 'foo')返回 true。 |
REGEXP_LIKE('str1', 'str2') | 检查 str1 是否匹配 str2 中定义的正则表达式。不区分大小写,并使用修改后的 ECMAScript 正则表达式语法。 | REGEXP_LIKE('foobarbaz', 'foo.*baz')返回 true。 |
... | ... | ... |
这些只是路由指南中可用函数的几个示例。完整列表[5] 包含更多。
以下是一些匹配表达式及其解释的示例:
"match": "$.session.schema = 'analytics' AND $.session.user = 'reporting_user'"
此规则确保来自用户 "reporting_user" 的所有针对 "analytics" 模式的查询都根据相应的路由指南进行路由。
"match": "NETWORK($.session.sourceIP, 24) = NETWORK('192.168.1.0', 24) OR
NETWORK($.session.sourceIP, 8) = NETWORK('10.0.0.0', 8)"
此规则根据客户端 IP 地址的网络子网进行匹配:
如果任一条件为真,则查询将被路由到一组特定的服务器。
"match": "$.session.connectAttrs.program_name = 'mysqldump'"
此规则检测 MySQL Dump(mysqldump)是否作为客户端使用。来自 mysqldump 的查询将被路由到特定服务器(例如,备份服务器),以避免影响主数据库节点的性能。
"match": "$.server.tags.environment = 'staging' AND $.server.version = 90200"
此规则创建一个目的地,仅包含在暂存环境中运行(标记)且 specifically 在 MySQL 版本 9.2.0(90200)上运行的 MySQL 服务器。
路由指南通过一个结构化的工作流程操作,确保查询根据实时条件动态路由到最合适的 MySQL 实例。该过程包括以下通用步骤:
路由指南提供了一种强大且灵活的查询路由方法,使管理员能够精确控制查询在 MySQL 架构中的路由方式。以下是一些关键优势:
MySQL Router 被设计为用于 无状态连接扩展,因为所有配置都直接存储在 MySQL 中。
这也确保了路由指南保持灵活且集中化,避免了不必要的 Router 配置文件复杂性。
此外,路由指南需要 MySQL Shell 和 MySQL Router 9.2.0 或更高版本,但它们不依赖于特定的 MySQL Server 版本,使其在不同部署中兼容。
在 MySQL 社区版和企业版中,路由指南解锁了 MySQL 查询路由的新灵活性,使优化不同 MySQL 部署的性能、可扩展性和弹性比以往任何时候都更加容易。
这篇介绍为理解路由指南奠定了基础。在下一篇博文中,我们将探讨如何使用 MySQL Shell 的 AdminAPI 配置和管理路由指南,并提供实际示例和用例。敬请关注!
有关更多详细信息,请查看 MySQL 官方文档 或立即使用 MySQL Shell 和 MySQL Router 尝试路由指南。
参考资料
[1]
MySQL Shell: https://dev.mysql.com/doc/mysql-shell/9.2/en/
[2]
MySQL Router: https://dev.mysql.com/doc/mysql-router/9.2/en/
[3]
Routing Guidelines: https://dev.mysql.com/doc/mysql-shell/9.2/en/admin-api-routing-guidelines.html
[4]
routing guidelines syntax: https://dev.mysql.com/doc/mysql-shell/9.2/en/admin-api-routing-guidelines-syntax.html
[5]
routing guidelines full list: https://dev.mysql.com/doc/mysql-shell/9.2/en/admin-api-routing-guidelines-syntax.html
本文关键字:#MySQL# #Router# #Shell# #Routing Guidelines#