不少时候咱们都不用特别的关心服务器时间的问题,好比后台管理系统,若是服务器时间出错顶多会在页面获取错误的时间而已,影响不大。但有些程序对时间很是敏感,不能出一丁点错误,今天要讲的是去年发生在本身身边的事:因为时间同步问题引起了部门级故障,形成很是严重的后果。由于事件发生还不到一年,而且就在本身身边,因此记忆犹新。老规矩,在讲故事以前先了解一下背景,故事中 X 系统后台的简化架构以下: 程序员
上图中 Client 模块机器数量 > 万台,Connector 模块机器数量 > 百台,而 Heartbeat 模块机器却只有一台,这是引起惨案的根本缘由。事情通过:服务器
int g_lastReportTime = sometime;
void report() {
int currentTime = getCurrentTime();
if (somevalue / (currentTime - g_lastReportTime ) > threshold) {
reportSomething();
g_lastReportTime = currentTime;
}
}
复制代码
从上面代码能够看出 currentTime - g_lastReportTime 在理论上是不会等于零的,可是因为新启的机器时间并未与 X 系统内部保持一致。致使 Client 时间回退,也就出现了 currentTime - g_lastReportTime = 0 的状况。架构
以上过程花了将近 40多分钟,形成了很是大的影响。后来部门对事故相关责任人进行了问责和所有门通报。此次事故看似偶然,其实必然,从心跳机器单点那一刻。器宕机形成的事故远不及 Client core 形成的严重,能够看出本次事故的主要缘由是因为时间不一样步形成的,但它也不是孤立的,是众多因素的统一做用结果。本标题服务器时间同步引起的“惨案”并不夸张,但愿能引发读者这块的注意和思考。并发
在事故发生的时候我也没有想太多,毕竟当时做为萌新也想不出来个因此然来。可是随着工做经验积累,慢慢的从此次事故中有了一些总结。此次事故主要引出如下四个问题:运维
心跳机器宕机,心跳数据上不来竟然在次日上班的时候才被发现,整整超过 8 小时了。幸好该系统只是一个内部系统,若是是相似淘宝、天猫这种的,那形成的经济损失和口碑影响可想而知了。据说在半夜监控已经报出异常,可是一个新来的同事定位并未发现问题,才致使了最后的蝴蝶效应。不过好像即便当场发现,若是在切换新机器时没作好时间同步也会出现 core 事故。对于系统监控我有如下几点建议:分布式
这是一个老生常谈的话题,网上有一堆的解决方案,这里不讲普适性的只介绍下针对 X 系统的。因为该系统的特殊性,Heartbeat 模块并不能进行多机器部署。因此只能单点,那咱们只能祈祷单点机器不会发生故障了吗?根据墨菲定律:若是你担忧某种状况发生,那么它就更有可能发生。因此不要有侥幸心理,对于 X 系统 Heartbeat 的单点,虽然不能在短期内重构,但咱们仍是能够作一些事情而不至于须要运维手动切换机器的。一种方案以下:学习
在服务注册中心对 Heartbeat 模块机器进行监控,若是发现服务注册中心没有了心跳模块超过必定时间。则启动备用机器上的 Heartbeat 并发出告警。这样就能及时的切换到备用 Heartbeat 不至于太匆忙忘这忘那。简单结构图以下:测试
事故中的错误代码是我简化后的,通常不会出现出现这种低级错误,应该是一段逻辑处理后产生了相似的代码,只是不够直接没被发现。这种状况咱们怎么保证代码质量问题?我以为能够从三个方面考虑:spa
分布式或者集群的时间同步也是分布式系统下须要解决的问题之一,抛开 X 系统事故中的场景不说。有不少场景是须要保持分布式系统中各个节点(机器)上的时间一致的的,好比银行交易系统,不能让后一笔交易的时间比前一笔交易的时间早,不然会给用户形成困扰。不一样的分布式系统有不一样的解决方案,有的简单有的复杂。简单的像 X 系统同样直接用 ntpdate 就能够实现,复杂的参考博客园这篇文章《分布式系统----时钟同步》实现本身的同步系统。code
固然,以上只是泛泛而谈,权当抛砖引玉。不知道你所维护的系统中是否也存在相似的问题呢?早一点把已知的问题暴露出来,比藏着掖着要好的多。在出事故以前发现问题能赢得老板对你好感,说不定还能升职加薪,而若是在出事以后再来解决问题那就只能背锅咯。记得关注公众号哦,记录着一个 C++ 程序员转 Java 的学习之路。