在 haproxy 中的写入故障转移期间,正在进行的 mysql 事务会发生啥?
Posted
技术标签:
【中文标题】在 haproxy 中的写入故障转移期间,正在进行的 mysql 事务会发生啥?【英文标题】:What happens to in-flight mysql transactions during a write failover in haproxy?在 haproxy 中的写入故障转移期间,正在进行的 mysql 事务会发生什么? 【发布时间】:2016-03-04 21:38:15 【问题描述】:我目前已将 haproxy 配置为负载平衡和故障转移一组 mysql 服务器。我有一个为写事务配置的后端,如下所示:
backend pool_mysql_write
timeout connect 10s
timeout server 1m
mode tcp
option mysql-check user haproxy_check
server primary <primary_node>:3306 check fastinter 1000
server secondary <secondary_node>:3306 check fastinter 1000 backup
存在“备份”指令,以便所有写入仅转到主数据库节点,并且只有在主数据库节点出现故障时才会故障转移到辅助数据库节点。
编辑:数据库节点处于主-主复制模式。
我的问题是,在 haproxy 故障转移到辅助数据库节点的过程中,运行中的 mysql 写入查询会发生什么?例如,如果 haproxy 需要 5 秒来提升辅助 DB 节点进行写入,那么在 5 秒的故障转移时间内可能一直尝试写入 DB 的所有写入查询会发生什么情况?
它们会消失吗?他们是否在某个地方排队,以便在辅助数据库节点升级后可以提交?
【问题讨论】:
除了 haproxy,您如何将写入从主副本复制到辅助副本? 啊,我忘了提——两个数据库节点都在主-主复制上 【参考方案1】:当(由客户端)启动与 haproxy 的新 TCP 连接时,它会反过来打开与上游服务器的新 TCP 连接。一旦上游 TCP 连接建立,haproxy 就会将这些 TCP 连接连接在一起,来回中继通信。
如果这些 TCP 连接中的任何一个(即它与客户端的连接,或与上游服务器的连接)断开,haproxy 会简单地断开另一个 - 换句话说,haproxy 不会切换现有的 TCP 连接到备用服务器(它只是重定向新连接)。交易对手负责决定下一步做什么。 (对于更智能的方法,您需要像 MariaDB MaxScale 这样的第 7 层代理,它可以重新路由现有连接)。
通常,如果其连接意外断开,客户端将尝试重新连接(因此 haproxy 可能最终将其连接到不同的上游服务器,例如,因为原来的服务器不再可用)。
问题是,如果客户端向原始服务器发送了会改变其状态的命令怎么办?
如果客户端在连接断开之前收到了提交确认,则客户端将理解其写入已提交。因此,您必须确定 primary
在写入被复制到 secondary
之前不会确认提交——因此我在上面问您如何执行复制:至少,您想要 Semisynchronous Replication:
默认情况下,MySQL 复制是异步的。主服务器将事件写入其二进制日志,但不知道从服务器是否或何时检索并处理了它们。使用异步复制,如果主服务器崩溃,它已提交的事务可能不会传输到任何从服务器。因此,在这种情况下,从主服务器故障转移到从服务器可能会导致故障转移到缺少与主服务器相关的事务的服务器。
半同步复制可以用来替代异步复制:
[ deletia ]当主节点阻塞时(等待从节点的确认),它不会返回执行事务的会话。当块结束时,主控返回到会话,然后可以继续执行其他语句。此时,事务已在 master 端提交,并且至少有一个 slave 已确认收到其事件。
如果客户端在连接断开之前没有收到提交确认,那么客户端应该假设写入没有提交并相应地处理——例如建立新连接后重新尝试事务。
但是,可能primary
实际上已经提交了写入(并且确实将它们复制到了secondary
),但是在它发送提交确认之前失败了,或者它发送了提交确认,但连接在客户端收到之前失败。我认为对此无能为力(请使用 cmets?),但风险非常小(因为在提交完成和发送确认之间没有进行任何处理)。
【讨论】:
感谢您的详细回复。我正在运行嵌入式 mariadb,并将查看 MaxScale。以上是关于在 haproxy 中的写入故障转移期间,正在进行的 mysql 事务会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章