Connector/J 为 MySQL 集群或多源部署提供了一个有用的负载均衡实现,如 第 9.3 节,“使用 Connector/J 配置负载均衡” 和 支持多源复制拓扑 中所述。相同的实现用于在复制感知连接的只读副本之间平衡负载。
在尝试在多台服务器之间平衡工作负载时,驱动程序必须确定何时可以安全地交换服务器,例如,在事务中间这样做可能会导致问题。重要的是不要丢失状态信息。为此,Connector/J 仅在以下情况之一发生时尝试选择新服务器
在事务边界(事务显式提交或回滚)。
遇到通信异常(SQL 状态以“08”开头)。
当
SQLException
匹配用户定义的条件时,使用由loadBalanceSQLStateFailover
、loadBalanceSQLExceptionSubclassFailover
或loadBalanceExceptionChecker
属性定义的扩展点。
第三种情况涉及三个属性,这些属性允许您控制哪些 SQLException
触发故障转移
-
loadBalanceExceptionChecker
-loadBalanceExceptionChecker
属性实际上是关键。它采用一个完全限定的类名,该类名实现了新的com.mysql.cj.jdbc.ha.LoadBalanceExceptionChecker
接口。此接口非常简单,您只需实现以下方法public boolean shouldExceptionTriggerFailover(SQLException ex)
传递一个
SQLException
,并返回一个布尔值。值true
触发故障转移,false
不触发。您可以使用它来实现自己的自定义逻辑。一个可能很有用 的示例是在使用 MySQL 集群处理瞬态错误时,某些缓冲区可能变得过载。以下代码片段说明了这一点
public class NdbLoadBalanceExceptionChecker extends StandardLoadBalanceExceptionChecker { public boolean shouldExceptionTriggerFailover(SQLException ex) { return super.shouldExceptionTriggerFailover(ex) || checkNdbException(ex); } private boolean checkNdbException(SQLException ex){ // Have to parse the message since most NDB errors // are mapped to the same DEMC. return (ex.getMessage().startsWith("Lock wait timeout exceeded") || (ex.getMessage().startsWith("Got temporary error") && ex.getMessage().endsWith("from NDB"))); } }
上面的代码扩展了
com.mysql.cj.jdbc.ha.StandardLoadBalanceExceptionChecker
,它是默认实现。对于那些想要使用属性进行一定程度的控制而不编写 Java 代码的人来说,此默认实现中内置了一些方便的快捷方式。此默认实现使用另外两个属性:loadBalanceSQLStateFailover
和loadBalanceSQLExceptionSubclassFailover
。 -
loadBalanceSQLStateFailover
- 允许您定义一个以逗号分隔的SQLState
代码前缀列表,与之比较SQLException
。如果前缀匹配,则触发故障转移。因此,例如,以下内容将触发故障转移,如果给定的SQLException
以“00”开头或为“12345”loadBalanceSQLStateFailover=00,12345
-
loadBalanceSQLExceptionSubclassFailover
- 可以与loadBalanceSQLStateFailover
结合使用,也可以单独使用。如果您希望某些SQLException
子类触发故障转移,只需提供一个以逗号分隔的完全限定的类或接口名称列表以进行检查。例如,如果您希望所有SQLTransientConnectionExceptions
触发故障转移,您将指定loadBalanceSQLExceptionSubclassFailover=java.sql.SQLTransientConnectionException
虽然前面列出的三个故障转移条件适合大多数情况,但如果启用了 autocommit
,Connector/J 永远不会重新平衡,并且继续使用相同的物理连接。这可能会有问题,尤其是在使用负载均衡在多个副本之间分配只读负载时。但是,可以配置 Connector/J 在启用了 autocommit
时,在执行一定数量的语句后重新平衡。此功能取决于以下属性
loadBalanceAutoCommitStatementThreshold
– 定义将触发驱动程序可能交换物理服务器连接的匹配语句数量。默认值 0 保留启用autocommit
的连接永远不会平衡的行为。-
loadBalanceAutoCommitStatementRegex
– 与之匹配语句的正则表达式。默认值为空白,与所有语句匹配。因此,例如,使用以下属性将导致 Connector/J 在每第三个包含字符串““test””的语句后重新平衡loadBalanceAutoCommitStatementThreshold=3 loadBalanceAutoCommitStatementRegex=.*test.*
loadBalanceAutoCommitStatementRegex
在许多情况下都可能非常有用。您的应用程序可能使用临时表、服务器端会话状态变量或连接状态,在处理完成之前让驱动程序随意交换物理连接可能会导致数据丢失或其他问题。这使您可以标识仅在交换物理连接安全时才执行的触发语句。
使用 DNS SRV 配置负载均衡和故障转移
有关详细信息,请参阅 第 6.14 节,“支持 DNS SRV 记录”。