MySQL Connector/J failover协议
MySQL Connector/J支持 failover 协议:即Client链接失效时,将会尝试与其他host建立连接,这个过程对应用是透明的。Failover协议是“Multi-Host”模式中最基础的协议,“load balancing”、“replication”、“farbic”协议都基于Failover协议。其URL格式如下:
jdbc:mysql://[primary-host]:[port],[secondary-host]:[port],.../[database]?[property=<value>]&[property=<value>]
Host列表中有两种hosts:primary(master)和secondaries(slaves),priamry需要位于hosts列表的第一个;当创建一个新的连接时,会首先尝试与primary连接,如果primary连接异常,将会依次与secondaries建立连接直到成功为止。即使与primary的链接失效,但是并不会丢失primary的特殊状态:比如它的访问模式、优先级等。
连接属性
Failover协议支持以下属性:
- failOverReadOnly
- secondsBeforeRetryMaster
- queriesBeforeRetryMaster
- retriesAllDown
- autoReconnect
- autoReconnectForPools
failOverReadOnly用于控制连接中“read_only”参数,即当primary连接失效时,连接到secondary时的默认访问模式,此值默认为“true”,即与secondary的连接访问模式为“只读”。
primary的连接访问模式总是“read/write”,即read_only为false。当与primary的连接失败,如果failOverReadOnly为false,表示与secondary的连接上允许发生“write”操作,与secondary的连接访问模式也是“read/write”。
在failover发生后,会定期检测primary的链接状况,如果发现primary的连接恢复正常,那么连接会“Fallback”(回落)到primary上,即此后的read/write将在primary连接上发生(与secondary的连接将会保持空闲,或者断开)。“secondsBeforeRetryMaster”表示驱动每隔多少秒将重试master的连接,“queriesBeforeRetryMaster”表示执行多少次queries后重试master的连接,如果重试成功,则将连接“Fallback”到primary上。可以将上述两个属性设置为“0”来关闭自动Fallback。
当primary的连接失效后,触发failover,此时驱动将依次与hosts列表中的secondary建立连接,直到与某个Secondary连接成功,否则将所有的secondaries都尝试完毕,然后继续从头开始,直到与其中一个secondary连接成功。如果所有的hosts都无法连接,驱动最多重试“retriesAllDown”次(默认为120)。
测试
- MySQL部署结构
2.JDBC设置:
db.url = jdbc:mysql://172.16.21.193:3306,172.16.21.191:3306/testdb?failOverReadOnly=false&secondsBeforeRetryMaster=0&queriesBeforeRetryMaster=0&retriesAllDown=120&autoReconnect=false
每秒访问MySQL进行一次查询,在日志中打印时间。
- 当触发一次MySQL主从切换,旧主解绑 172.16.21.193,新主绑定 172.16.21.191,看日志每隔3s才会访问一次 172.16.21.191,这显然是有问题的:
- 抓包分析得知,每次访问 172.16.21.191 后,会发3次 ARP 广播询问 172.16.21.193 的 mac 地址,每隔1s 发一次,刚好 3s:
- 对比测试,将 VIP 换成真实 IP:
db.url = jdbc:mysql://172.16.21.5:3306,172.16.21.4:3306
关闭 172.16.21.5:3306 这个 MySQL,观察到每次连接 MySQL 时,都先尝试连接 172.16.21.5:3306 ,再连接 172.16.21.4:3306。不同的是很快就会收到 RST 重连信号,不会阻塞与 172.16.21.4:3306 的连接。此处不会有 arp,因为 arp -a 查看到的 arp 缓存一直都有真实IP的mac地址。
测试结论
从前面分析可以推得结论:
MySQL-JDBC 驱动每次访问 host 列表都需要检测 primary host 的连通性,如果 primary host IP 地址不在 arp 缓存中,则会发3次 arp 广播,导致连接 secondary host 时有3s 延迟,这对应用来说延迟太大。secondsBeforeRetryMaster=0&queriesBeforeRetryMaster=0 看起来失效了(本来作用是定义 primary host 连接检测失败后,不再检测 primary host)
但是:
尝试修改 JDBC 其他参数(autoReconnect=true),发现并不是每次访问 secondary host 即 172.16.21.191 前都需要 arp 广播寻找 primary host 即 172.16.21.193,而是隔多少秒才会进行 arp 广播。与前面的结论又相矛盾。
因此本次探索MySQL Connector J 高级特性 failover 协议以一头雾水告终,留此记录希望以后能解开这个谜团。
MySQL Connector/J loadbalance协议
Load Balancing可以将read/write负载,分布在多个MySQL实例上,这些MySQL实例通常为 Cluster 架构或者 Replication 架构,本文主要讲解“Replication”架构相关的知识。LB协议基于“Failover协议”,即具备Failover特性,其URL格式:jdbc:mysql:loadbalance://[host]:[port],[host]:[port],...[/database]?[property=<value>]&[property=<value>]
网友评论