如何在日志轮换期间避免Galera集群的WSREP停机问题?
嘿,我之前维护MariaDB Galera集群时也碰到过一模一样的糟心事——日志轮换突然触发WSREP超时,半夜被监控告警叫醒的滋味真的太难受了!咱们一步步来搞定它。
首先得搞清楚问题根源:你用的默认logrotate配置里,postrotate阶段执行了一堆flush-*log命令。在Galera集群环境下,这些flush操作会让MariaDB短暂关闭并重新打开日志文件,这个过程中节点的WSREP同步线程可能会暂停,导致其他节点误以为这个节点挂了,进而触发超时和WSREP错误。
下面是几个实测有效的解决方案,你可以根据自己的场景选择:
方案一:用copytruncate替代flush操作(推荐)
这是对集群影响最小的方式,原理是先复制当前日志到归档文件,再截断原日志文件,全程不需要让MariaDB做任何flush或重启操作,也就不会干扰集群同步。
修改你的logrotate配置如下:
/var/lib/mysql/mysqld.log { su mysql mysql notifempty daily rotate 3 missingok compress copytruncate # 核心替换项,替代原来的postrotate脚本 create 600 mysql mysql # 打开这个注释,确保新生成的日志文件权限正确 }
⚠️ 小提醒:copytruncate可能会丢失极少量日志(复制和截断之间几秒内产生的日志),但对于绝大多数业务场景来说,这个损失远小于集群停机的影响。如果你的业务对日志完整性要求极高,可以看下面的方案二。
方案二:精简flush操作,只刷新必要的日志
如果你不想用copytruncate,那可以把postrotate里的flush命令精简到只处理当前轮换的日志(也就是mysqld.log对应的错误日志),减少对数据库的冲击:
修改后的postrotate部分:
postrotate # 只在mysqld运行时执行操作 if test -x /usr/bin/mysqladmin && \ /usr/bin/mysqladmin ping &>/dev/null then # 只刷新错误日志,去掉其他不必要的flush命令 /usr/bin/mysqladmin --local flush-error-log fi endscript
原来的脚本一次性刷新4种日志,会给数据库带来额外负载,精简后只处理需要轮换的日志,能大幅降低集群超时的概率。
方案三:调整Galera超时参数(治标不治本)
如果上面的方案还没完全解决,你可以适当调大Galera的超时阈值,让集群对短暂的节点波动更宽容:
- 增大
wsrep_sst_receive_timeout(比如从默认的60调为120) - 修改
wsrep_provider_options里的evs.suspect_timeout(比如从默认的5调为10)、evs.inactive_check_period(从默认的1调为2)
不过这个只是让告警晚一点触发,不能从根本上解决日志轮换带来的扰动,所以还是优先用前两个方案。
最后别忘了测试!修改配置后,手动执行一次logrotate验证:
logrotate -f /etc/logrotate.d/mariadb
然后查看集群节点状态SHOW STATUS LIKE 'wsrep_cluster_status';,确认没有出现新的WSREP错误,这样就能安心睡个整觉啦!
备注:内容来源于stack exchange,提问作者Tim

