MySQL高可用运维设计三合一实战
|
线上报警那一刻,我正把咖啡杯底最后半口晃荡着往嘴里送,凉得跟隔夜茶似的——手抖了一下,滴在键盘右下角那块油乎乎的“Ctrl”上。工单系统又弹了条消息,标题是「【P0】主库读延迟突增」,我点开没点进详情页,先划掉通知栏。去年11月份的事儿,现在想起来还像嚼了颗没剥壳的生花生,硌牙,但你又不敢吐。 运维老张电话进来的时候我刚切到监控看板,他第一句是:“查吧,主从同步断了。”第二句就拐了:“产品说‘昨天灰度发完用户反馈变快了’,结果今早登录接口超时率涨了四成。”我没接话,他顿了三秒,补了句:“……前端昨儿晚上还夸咱们缓存命中率稳。”——这话我听着耳熟,因为上周五我也在群里回过一句“缓存层稳得很”,结果转头MySQL连着重启了三回,连哨兵都没拉住,光听告警铃响,跟催命似的。 说白了,“MySQL高可用运维设计三合一实战”这名字起得挺唬人,其实就三件事:故障发现得快、切换动作要准、恢复后别漏账。我们去年搞的那一版,真站得住的地方?就俩字:优胜劣汰。不是说方案多高级,是它让跑得慢的节点、配错的中间件、没加timeout的老代码,全他妈暴露在监控底下,逼着人要么改,要么滚。我原以为只要哨兵配置够细、VIP漂移脚本够稳就能糊弄过去,结果呢?一个从库relay-log里少写了一行GTID,硬是撑了六小时没报错,直到主库OOM前37分钟才被慢查询日志里一条“SELECT FROM user_profile WHERE id IN (…)”带出来——这SQL压根不该走主库,它该走缓存,但那个getById()方法里,cache.get()之后居然没判null,直接fallback到db.query(),还加了个try-catch吞了异常……我删它的时候手都在抖。 窗外天黑了。我盯着屏幕右下角时间,19:43,还没到下班点,但空调出风口那块冷凝水滴滴答答开始往下掉,节奏跟数据库连接池耗尽时的报错日志频率差不多。产品小李抱着笔记本冲进来问“能不能把灰度比例从30%调回10%”,我点头说“可以”,其实心里想的是——调回10%只是拖时间,不是解法。她转身时头发扫过我桌上那张贴了半年的便签,上面写着“binlog_format=ROW,别碰”,字迹都洇开了。我伸手按了下,纸边翘起来,露出底下一行更早的字:“记得check slave_sql_running”。没人check,从来没人check。 前端小陈昨天联调时甩给我个curl命令,说“这个接口你们DBA看下为啥比上周慢两倍”,我接过来扫了眼explain,索引用得没问题,然后一翻慢日志,发现执行计划里有临时表和filesort,再往上追,发现他传过来的分页参数是page=1&size=500,而我们默认的“合理分页阈值”配置写死在my.cnf里,注释还写着“此值供DBA参考”,可谁他妈看过?我改了,顺手commit进config repo,第二天上线发现配置中心没拉新版本——这事儿不归我管,但最后背锅名单上我的工号排第三。不是我说,去年校招面的三个实习生,有一个当场问我:“MySQL主从延迟能不能靠加大relay_log_space_limit扛过去?”我愣了三秒,说:“能,但扛不过产品经理下周要的报表。”他点点头,笔记里写了四个字:“物理上扛”。
文章配图,仅供参考 其实最荒诞的不是技术问题。是我们做高可用方案评审那天,会议室投影仪蓝屏,运维老张蹲在后面扒机箱,产品小李一边拍着键盘一边说“我觉得用Redis做兜底比切从库更稳”,我说“那你得保证Redis不崩”,她回“那我再加一层本地缓存呗”。我当时没吭声,只觉得咖啡凉透了,舌头麻了半边。后来我查源码才发现,那个所谓的“本地缓存”,是个ConcurrentHashMap套了层Guava Cache包装器,最大size设成了200,key是user_id+timestamp,timestamp每毫秒变一次……所以,它根本没缓存过任何东西。这事儿我到现在没敢告诉任何人,包括我自己——怕一说出口,整套高可用就塌了最后一根承重柱。 谁的键盘声很响,就在隔板左边,敲F12的声音特别脆,一下一下,跟打点计时器似的。我盯着error log里反复出现的一行:“Waiting for semi-sync ACK from slave”,等了整整十八分钟。其实我该去查半同步超时参数的,但我想起了旧同事老周——他离职前最后一周干的事,是把所有从库的wait_timeout从28800改成300,理由是“防长连接淤积”。后来他走了,这配置还在,没人动,也没人记得为什么这么设。我现在不敢动,怕一动,某个凌晨三点跑的ETL脚本就全挂掉,而我又得爬起来改crontab——这活儿比修数据库累,因为它没有错误码,只有静默失败。 手机亮了一下,是招聘群,HR转发了条JD:“急招DBA,要求熟悉MySQL高可用架构,有‘三合一’实战经验者优先。”我划掉,打开Navicat,连上那个最怂的从库,show processlist;里面二十多个Sleep状态,最长那个idle了117分钟。我手指悬在kill command上停了半分钟,最后删掉了整个窗口。下次查,我打算看看gtid_executed和gtid_purged差多少,再顺手grep下backup脚本里有没有--set-gtid-purged=OFF——反正今天也来不及改了。其实,也不确定是不是它的问题。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

