根本问题
在 Galera 集群中,所有节点必须以相同的顺序应用相同的写入集(writeset)以保持一致性。但并非所有节点都是相同的:有些节点更快(较新的硬件、较轻的负载),有些则更慢(较旧的硬件、繁重的查询)。
当一个较慢的节点跟不上写入速度时会发生什么?写入集在其接收队列(recv queue)中累积。如果不采取措施,这个队列会无限增长,消耗所有内存,节点最终崩溃或从集群中偏离。
Flow Control 就是防止这种情况的机制。它是集群的手刹:当一个节点不堪重负时,它要求其他节点放慢速度。
Flow Control 的工作原理
Flow Control 依赖一个简单的阈值:gcs.fc_limit。
每个 Galera 节点维护一个接收队列(recv queue),存储等待应用的写入集。当该队列大小超过 gcs.fc_limit 时,节点向集群中的所有其他节点发送 FC_PAUSE 消息。
收到 FC_PAUSE 后,其他节点停止向慢速节点发送新的写入集。整个集群的写入都被阻塞——这是同步一致性的代价。
当慢速节点的 recv 队列降至 gcs.fc_limit * gcs.fc_factor 以下时,该节点发送 FC_CONTINUE 消息,集群恢复正常操作。
5 个关键的 wsrep 变量
要监控 Flow Control,五个状态变量至关重要:
SHOW GLOBAL STATUS WHERE Variable_name IN (
'wsrep_local_recv_queue',
'wsrep_local_recv_queue_avg',
'wsrep_flow_control_paused',
'wsrep_flow_control_paused_ns',
'wsrep_flow_control_sent'
);
wsrep_local_recv_queue
当前 recv 队列大小。正常运行时应接近 0。如果经常超过 gcs.fc_limit,说明该节点正在挣扎。
wsrep_local_recv_queue_avg
recv 队列的移动平均值。检测趋势最可靠的指标。平均值超过 0.5 时值得调查。
wsrep_flow_control_paused
在 Flow Control 状态下花费的时间比例(0 到 1 之间)。如果超过 0.1(即 10% 的时间),集群存在严重的性能问题。
wsrep_flow_control_paused_ns
Flow Control 状态下的总时间(纳秒)。用于计算一段时间内的绝对暂停时间。
wsrep_flow_control_sent
此节点发送的 FC_PAUSE 消息数量。如果单个节点发送了大部分 FC_PAUSE 消息,它就是需要解决的瓶颈。
6 个调优参数
gcs.fc_limit
Flow Control 触发阈值。默认值:16。增加此值可以在触发制动前容忍更多延迟,但会增加内存消耗。
gcs.fc_factor
恢复系数。默认值:0.5。当 recv 队列降至 fc_limit * fc_factor 时,Flow Control 被解除。当 fc_limit=100 且 fc_factor=0.8 时,FC 在 80 个写入集时解除。
wsrep_slave_threads
写入集应用线程数。更多线程 = 更快的写入集应用 = recv 队列更快排空。建议:2 x CPU 核心数。
wsrep_cert_deps_distance
事务之间的平均认证距离。表示潜在的并行度。如果值较高,增加 wsrep_slave_threads 将产生积极影响。
gcs.recv_q_hard_limit
recv 队列的绝对字节限制。如果超出,节点将被终止。这是避免 OOM 的最后手段。建议:内存的一半加上 swap。
gcs.max_throttle
在 Flow Control 期间保证的最小吞吐量(0 到 1 之间)。默认值 0.25 意味着即使在 FC 期间,也保持正常吞吐量的 25%。设为 0 表示在 FC 期间完全停止。
专家建议
经过多年在生产环境中管理 Galera 集群的经验,以下是汇总的建议:
Slave 线程数配置
wsrep_slave_threads = 2 * CPU_CORES
如果您的服务器有 8 个核心,从 wsrep_slave_threads = 16 开始。监控 wsrep_cert_deps_distance——如果它低于 slave 线程数,就减少线程数。
基于 Slave 线程数的 fc_limit
gcs.fc_limit = 5 * wsrep_slave_threads
使用 16 个 slave 线程时,gcs.fc_limit = 80。这为线程提供了足够的空间来并行工作,而不会过早触发 FC。
渐进恢复的 fc_factor
gcs.fc_factor = 0.8
0.8 的 fc_factor(而不是默认的 0.5)允许更渐进的流量恢复,避免 FC_PAUSE / FC_CONTINUE 的振荡。
安全硬限制
gcs.recv_q_hard_limit = HALF_RAM_PLUS_SWAP
在拥有 32 GB 内存和 16 GB swap 的服务器上,设置 gcs.recv_q_hard_limit = 24G。这是防止 OOM 的安全网。
识别问题节点
当 Flow Control 频繁触发时,您需要找出慢速节点:
-- 在每个节点上
SELECT @@hostname,
VARIABLE_VALUE AS fc_sent
FROM information_schema.GLOBAL_STATUS
WHERE VARIABLE_NAME = 'wsrep_flow_control_sent';
发送最多 FC_PAUSE 的节点就是瓶颈。常见原因:
- 较差的硬件:更慢的磁盘、更少的内存
- 繁重的查询:ALTER TABLE 或大型 SELECT 垄断了资源
- 正在进行备份:mariabackup/xtrabackup 消耗了大量 I/O
- 不均衡的应用负载:一个节点承受了过多的读取请求,同时还必须应用写入集
总结
Flow Control 是 Galera 一致性的守护者。理解其工作原理和参数对于维护高性能集群至关重要。
黄金法则:slave_threads = 2 * CPU、fc_limit = 5 * threads、fc_factor = 0.8、硬限制 = 内存的一半加 swap。监控 wsrep_flow_control_paused,一旦超过 10% 就立即响应。
本文最初发表于 Medium。
评论 (0)
暂无评论。
发表评论