scr系统常见故障及解决办法(故障分析从一则)
scr系统常见故障及解决办法(故障分析从一则)
2024-11-08 08:27:18  作者:踏梦女顽童  网址:https://m.xinb2b.cn/sport/cnq274553.html

作者:李锡超

一个爱笑的江苏苏宁银行 数据库工程师,主要负责数据库日常运维、自动化建设、DMP平台运维。擅长mysql、Python、Oracle,爱好骑行、研究技术。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

1. 问题现象:

9月15日,收到告警提示测试环境某系统的 MySQL MGR 集群存在异常。

日志内容如下:

// 10.x.y.97 节点MySQL 错误日志提示节点 10.x.y.95 不可达:2022-09-15T19:26:14.320181 08:00 0 "Warning" "MY-011493" "Repl" Plugin group_replication reported: "Member with address 10.x.y.95:3306 has become unreachable." // 随后mgraliver(MGR 探针)日志提示进行了切换:"2022-09-15 19:26:16" : Exception: Invalid primary_member_ip: or secondary_node_list:""10.x.y.96", "10.x.y.97"" ."2022-09-15 19:26:16" : Exception: MGR is likely to be switching, Sleep 1 sec and continue ."2022-09-15 19:27:01" : Exception: MGR running with WARN. ONLINE nodes Pri:10.x.y.96 Sec:10.x.y.97 diff from conf_node:10.x.y.95,10.x.y.96,10.x.y.97 .

即告警提示应用系统 MySQL MGR 发生了切换,由故障前的三节点 MGR 集群,切换为包括 Pri:10.x.y.96 Sec:10.x.y.97 两个节点集群。

2. 初步分析

收到告警后,通过分析MySQL错误日志、操作系统系统、监控日志等信息,发现操作系统的时间存在异常:

具体异常截图,如下图:


即:存在【Time has been changed 】异常。

结合mysql官方文档说明:其明确说明其故障检测基于时间:

如果一个成员在 5 秒内没有收到另一个成员的消息,则怀疑该成员发生故障,并在自己的 Performance Schema 表 replication_group_members 中将该成员的状态列为 UNREACHABLE。如果怀疑持续超过 10 秒,则怀疑成员会尝试将其认为可疑成员有错误的观点传播给该组的其他成员。 具体参考:https://dev.mysql.com/doc/refman/8.0/en/group-replication-responses-failure.html

由此初步怀疑是操作系统的时间发生了跳变,触发MySQL MGR发生故障切换。

并将相关异常,反馈系统系统管理部相关老师进行进一步确认。

3. 根本原因

经过系统专家深入分析,确认其根本原因是由于问题时段服务器底层存在异常。

导致 19:27:13左右 虚拟机发生挂起(此时虚拟机的任何操作都不能进行,包括监控脚本、时间、MGR的心跳等)。

虚拟机挂起后,由于除故障节点外的其它两个节点无法与故障节点进行通信,因此认为该节点存在异常并将其驱逐。并最终产生如上告警信息。

至此,该问题得到最终确认。

4. 关于时间对MGR的影响

既然该问题最终确认是由于虚拟机挂起导致主节点被驱逐。那么如果不是挂起,只是虚拟机的时间发生跳变,那还会触发故障切换么??

为此,通过测试环境进行了测试,其测试结论为:

当MGR集群中一个节点时间发生变化后(比如突然快了1小时、慢了1小时),MGR集群的同步状态并不会因此受到影响。error_log 里面也未看到明显的报错!

即:MGR 节点的时间异常,并不会触发MGR发生故障切换。

那具体是什么机制呢??为此结合源码进行确认!!

5. 我们知道,源码中涉及节点间探测,主要包括如下函数(alive_task/detector_task):

函数总体调用关系:

alive_task task_now may_be_dead task_nowdetector_task check_global_node_set DETECT task_now check_local_node_set DETECT task_now// alive_task :int alive_task(task_arg arg MY_ATTRIBUTE((unused))) { while (!xcom_shutdown) { .. // 超过0.5秒,广播我是 alive f (server_active(site, get_nodeno(site)) < task_now() - 0.5) { replace_pax_msg(&ep->i_p, pax_msg_new(alive_synode, site)); ep->i_p->op = i_am_alive_op; send_to_all_site(site, ep->i_p, "alive_task"); } ... { double sec = task_now(); // 超过4秒没有心跳,询问你是否活着 if (i != get_nodeno(site) && may_be_dead(site->detected, i, sec)) { replace_pax_msg(&ep->you_p, pax_msg_new(alive_synode, site)); ep->you_p->op = are_you_alive_op; ep->you_p->a = new_app_data(); ep->you_p->a->app_key.group_id = ep->you_p->a->group_id = get_group_id(site); ep->you_p->a->body.c_t = xcom_boot_type; init_node_list(1, &site->nodes.node_list_val[i], &ep->you_p->a->body.app_u_u.nodes); send_server_msg(site, i, ep->you_p); } } TASK_DELAY(1.0); }}// DETECT #define DETECTOR_LIVE_TIMEOUT 5.0 // 判断心跳是否超时 #define DETECT(site, i) \ (i == get_nodeno(site)) || \ (site->detected[i] DETECTOR_LIVE_TIMEOUT > task_now())static void check_global_node_set(site_def *site, int *notify) { u_int i; u_int nodes = get_maxnodes(site); site->global_node_count = 0; for (i = 0; i < nodes && i < site->global_node_set.node_set_len; i ) { int detect = DETECT(site, i); if (site->global_node_set.node_set_val[i]) site->global_node_count ; // 本次捕获的心跳状态,则表示有节点心跳突变: 无心跳->有心跳 有心跳->无心跳 if (site->global_node_set.node_set_val[i] != detect) { // 需要通知全局状态发生变化 *notify = 1; } DBGOHK(FN; NDBG(i, u); NDBG(*notify, d)); }}static void check_local_node_set(site_def *site, int *notify) { u_int i; u_int nodes = get_maxnodes(site); for (i = 0; i < nodes && i < site->global_node_set.node_set_len; i ) { int detect = DETECT(site, i); // 本次捕获的心跳状态,则表示有节点心跳突变: 无心跳->有心跳 有心跳->无心跳 if (site->local_node_set.node_set_val[i] != detect) { site->local_node_set.node_set_val[i] = detect; // 需要通知本地识别到可疑节点 *notify = 1; } DBGOHK(FN; NDBG(i, u); NDBG(*notify, d)); }}// detector_taskint detector_task(task_arg arg [[maybe_unused]]) { while (!xcom_shutdown) { { site_def *x_site = get_executor_site_rw(); if (x_site && get_nodeno(x_site) != VOID_NODE_NO) { if (x_site != last_x_site) { reset_disjunct_servers(last_x_site, x_site); } update_detected(x_site); if (x_site != last_x_site) { last_x_site = x_site; ep->notify = 1; ep->local_notify = 1; } check_global_node_set(x_site, &ep->notify); //判断是否有节点心跳超时,需要发起全局view变更通知 update_global_count(x_site); //更新全局节点个数 if (ep->notify && iamtheleader(x_site) && enough_live_nodes(x_site)) { ep->notify = 0; send_my_view(x_site);//如果有节点心跳异常,且当前节点是0号主节点,且多数派的节点存活, 则发送视图变更通知,即驱逐心跳异常节点,并处理新节点加入或老节点退出 } } if (x_site && get_nodeno(x_site) != VOID_NODE_NO) { update_global_count(x_site); //更新全局节点个数 check_local_node_set(x_site, &ep->local_notify);//判断是否有节点心跳超时,需要发起suspicion操作 if (ep->local_notify) { ep->local_notify = 0; deliver_view_msg(x_site); //驱逐心跳异常节点 } } } TIMED_TASK_WAIT(&detector_wait, 1.0); } }}

重点

通过阅读以上代码,可知函数 alive_task/detector_task 都通过 task_now() 获取当前时间,并进行判断是否超过对应的阈值。 那么进一步分析 task_now() 逻辑如下:

task_now xcom_init_clock xcom_monotonic_secondssecondsstatic void xcom_init_clock(xcom_clock *clock) { // 调用Linux 的 clock_gettime 函数,获取从系统启动时开始计时,以秒为单位(小于1秒以小数表示)。该时间不受系统影响,也不会被用户改变。 clock->monotonic_start = get_monotonic_time(); // 调用Linux 的 clock_gettime 函数,获取系统时间(如date),以秒为单位(小于1秒以小数表示)。该时间随着系统时间的改变而改变。 clock->real_start = get_real_time(); // 计算系统时间与启动计时的差值(offset) clock->offset = clock->real_start - clock->monotonic_start; // 通过差值 启动计时,得到时间。 xcom_monotonic_seconds(clock); // 修改计算标记为1。此后,只要MGR正常运行,MGR节点所获取时间等于=此处获取的差值(offset) 启动计时。 // 因此,无论系统时间如何变化,MGR都将获取“正确”的时间。 // 具体逻辑见如下代码: clock->done = 1;}static double xcom_monotonic_seconds(xcom_clock *clock) { // 初始化时获取的差值(offset) 启动计时。 clock->now = get_monotonic_time() clock->offset; return clock->now;}// 后续其它操作获取时间的函数:double seconds() { // 当第一步初始化后,!task_timer.done 始终未false if (!task_timer.done) { , xcom_init_clock(&task_timer); } // 因此初始化之后调用seconds()返回 :xcom_monotonic_seconds(&task_timer) return xcom_monotonic_seconds(&task_timer);}double task_now() { // 当第一步初始化后,!task_timer.done 始终未false。 if (!task_timer.done) { xcom_init_clock(&task_timer); } // 直接返回计算的 task_timer.now return task_timer.now;}对于 task_timer.now,通过跟踪发现多个逻辑都在调用,部分位置参考,如下代码栈:

6. debug 验证记录

基于如上代码分析,总结如下:

1). MGR 集群中获取时间=初始化时获取的固定差值(offset) 启动计时。由于offset是不变的值,启动计时在OS正常运行时,是一个恒定增加的数字。 即MGR集群心跳的时间不受系统时间的控制。因此在步骤3,进行测试时,未发现MGR集群存在异常。也确认本次故障确实不是由于时间发生变化而引起。

  • 好莱坞硬汉全程惨不忍睹(这些老头儿为什么越老越能打)
  • 2024-11-08这些老头儿为什么越老越能打1988年,《虎胆龙威》惊艳亮相,让观众牢牢记住了布鲁斯·威利斯的硬汉形象布鲁斯·威利斯是《虎胆龙威》系列的铁打男主,以至于今年已经63岁的他,还将主演明年上映的《虎胆龙威6》老兵不死,只是凋零但看着。
  • 宋志辉简历 原董事长宋志勇离任
  • 2024-11-08宋志辉简历 原董事长宋志勇离任民航资源网2020年4月29日消息:深圳航空近日发布公告,原董事、董事长宋志勇不再担任公司董事及董事长;原董事王明远、朱松岩不再担任公司董事经全体股东审议,同意陈志勇担任深航董事长,同意詹中、王杰、章。
  • 什么时候才能走出饥荒(如果发生了饥荒)
  • 2024-11-08如果发生了饥荒听说饥荒那时候死了很多人,草根树皮土豆吃如果未来又会饥荒,我现在该怎么做来应对?首先,中国基本不会出现缺粮问题,原因如下:一、粮食储备充足不知道国家到底储备了多少粮食,但全国吃上两三年应该没问题,有这。
  • 汉字趣谈百家姓全集:中行-百家姓的汉字的演变
  • 2024-11-08汉字趣谈百家姓全集:中行-百家姓的汉字的演变一、文字演变中字:行字:二、姓氏读音拼音:zhōngháng注音:ㄓㄨㄥˉㄏㄤˊ三、姓氏起源中行(háng)姓,为中国复姓中行姓源出于荀姓,最早可以追溯到春秋时期晋国一卿家——中行氏,距今已有二千多年。
  • 子弹姐舍甫琴科最新比赛(舍甫琴科打赢与卡尔穆什的二番战)
  • 2024-11-08舍甫琴科打赢与卡尔穆什的二番战UFC格斗之夜乌拉圭蒙得维的亚站,“子弹”瓦伦缇娜·舍甫琴科和利兹·卡尔穆什进行的二番战,是本站比赛的主赛之一这场比赛的一大看点是,在UFC已成王者的弹姐能否得报九年前的“一箭之仇”舍甫琴科曾输给过卡。
  • 东北炒虾皮的做法
  • 2024-11-08东北炒虾皮的做法做法一:干炒虾皮材料:虾皮250g、油80g做法:1、虾皮用清水淘洗两遍去掉杂质,尽量控干水份;2、锅烧热后倒油,转小火加入虾皮;3、不停翻炒,让虾皮里面的水分全部蒸发掉;4、最后炒成金黄色就可以了做。
  • 香港紫荆花寓意好吗(香港市花就是它吗)
  • 2024-11-08香港市花就是它吗紫荆花(Cercischinensis),属于豆科、紫荆属,它是一种落叶乔木,株高可达15米,但是栽培种常见为幼龄的小型树木它有哪些特点呢?1、花期3~4月花先于叶开放,花冠螳螂形(也叫假蝶形)、紫红。
  • 隆武帝朱聿键壮烈牺牲(生不逢时的君王隆武帝)
  • 2024-11-08生不逢时的君王隆武帝公元1625年五月,明熹宗朱由校在魏忠贤与乳母客氏的簇拥下,来到西苑的湖上泛舟游乐明熹宗与两名贴身小太监所乘的一艘小船,船至湖心深处,忽来一阵狂风,小船倾覆明熹宗等三人尽数落水,由于距离太远救援不及,。
  • 猴痘病毒后续(国内首例猴痘感染过程公布)
  • 2024-11-08国内首例猴痘感染过程公布国内首例猴痘感染者感染过程公布据中国疾病预防控制中心9月19日通报,9月16日中国大陆首例输入性猴痘病例是通过男男性行为传播感染该病例是一名29岁的中国籍销售人员,于2022年9月2日至8日访问德国,。
  • 健脾的食物(健脾的食物推荐)
  • 2024-11-08健脾的食物推荐健脾的食物,从中医五行理论中可以得知,脾主黄色,甘味,也就是甜味入脾,所以健脾的食物主要就是有着两个特征的饮食物,也就是说,颜色发黄的、还有味道发甜的食物,可以健脾养脾具体举例来说,健脾的食物有南瓜、。
  • 劳资笑死系列(嘻咦嗷笑就完了)
  • 2024-11-08嘻咦嗷笑就完了我现在的身体状况可以用四个字来形容:『稍纵即逝』意思是,稍微放纵一下,我感觉我就要即将逝去(去世)了所以理发师们是不是还是比较容易入门,毕竟大家都互相留面子了这个游戏其实我也玩过……怎么煮粥才不会溢出。
  • 郑州十佳班主任案例(严爱相济润己泽人)
  • 2024-11-08严爱相济润己泽人在本学期学校的统一组织下,开封七中历史组教师张佳慧积极参加见习班主任学习活动,在优秀指导教师李歌的带领下,她认真学习各项班级管理能力,有了很大进步,一学期以来,在工作中收获颇多,感悟深刻培养优秀的学风。