数据库故障容错之系统时钟故障

本文通过对CnosDB数据库系统时钟故障的讨论,提出了在单机环境和集群环境中解决系统时钟故障的方案,具有非常重要的指导意义。


可能并不存在的情况引发的讨论

有一天,CnosDB实习生小邵在做时间乱序数据处理逻辑的设计,时序数据的产生一般有以下几个规律可以遵循:

1. 一般情况下,时序数据由一条条时间线组成,每一条时间线背后都是一个独立的数据源。

2. 时序数据的产生往往是实时的,时间线上的数据也是按照时间顺序排列的,大多数时序数据库的底层数据存储设计也基于此。

3. 在一些特殊的情况下,一条时间线上的时间顺序可能会被破坏,一段时间之前的数据可能现在才到达数据库;由于处理起来太过麻烦,一些数据库会拒绝这种数据写入。

问题出在“一些特殊的情况上”,小邵异想天开地提出了一个我没有想到过的可能情况:

1. 如果客户端发来的数据是没有时间戳的,那么数据的时间戳由数据库服务端的系统时间戳决定。

2. 如果数据库服务端的系统时钟发生了修改,比如本来是5点,调成了3点,就会出现时间乱序数据。

不得不说,这是比“一些特殊的情况”还要特殊的情况,而比较典型的时间乱序数据场景是这样的;一个远程设备不断向数据库端发送自带时间戳的数据,可能有两种情况出现:

1. 网络方面的故障,导致从设备发来的数据,并没有按照数据发出的时间到达。

2. 设备发出的数据在到达数据库前丢失或损坏了,设备在之后的时间里将这些数据重新发给数据库。

经过了一段时间的思考,我发现小邵说的那种情况,不应该放在时间乱序数据的问题里讨论,而是一个需要单独处理的问题。

系统时钟故障

相比于掉电宕机、网络故障等常见又严重的故障,系统时钟发生变化的情况其实很少被考虑到,一般主要影响的也都是日志时间戳之类,不会直接影响到用户的部分。

近年来,由于NewSQL的概念普及,许多分布式数据库选择依赖系统时钟与NTP实现混合逻辑时钟,这时系统时钟故障可能才真正被广泛讨论。不过,CnosDB是个典型的原生时序数据库,不是那种拼接改造的数据库项目,并不支持事务,所以在这里并不是讨论混合逻辑时钟的问题。

定义

在具体讨论之前,先给系统时钟故障一个明确的定义:指由于恶意攻击、用户误操作等原因,导致数据库部署环境的系统时钟突然发生跨度较大的变化,比如前一秒系统时钟为17:00,下一秒变成了3:19。

由于从数据库的角度无法确认这种变化是否正确、是否符合用户的预期,所以将这种变化视为故障。

集群中的情况

单机下的情况比较简单,就是上文中的定义情况,而集群中的情况可以大致分为三种:

1. 只有少数节点的系统时钟发生变化。

2. 超过半数节点的系统时钟发生变化。

3. 所有节点同步切换到新的、相同的系统时钟。

对时序数据库的影响

就像上文中小邵所说的“特殊情况”,系统时钟故障会影响没有自带时间戳的数据,其背后是时序数据库对这类数据处理的策略:

1. 要求用户写入的所有数据都必须自带时间戳。

2. 对于没有时间戳的数据,自动添加客户端的系统时间戳。

3. 对于没有时间戳的数据,自动添加数据库服务端的系统时间戳。

据我观察,目前策略三应该是比较主流的方案,所以一个时序数据库最好还是要考虑如何处理系统时钟故障。否则,一旦出现问题,就会有大量“时间戳异常”的数据写入到数据库中,影响到数据库的性能还是小事,出现了用户角度的“脏”数据就是大麻烦了。

故障的处理

根据既往的经验和知识,一个足够健壮的系统,在处理故障时需要依循以下四个原则:

1. Fail-Fast:能够第一时间发现故障的产生。

2. Fail-Safe:尽将故障的影响范围控制在最小。

3. Fail-Over:在发生故障时能够进行主备切换,由没有发生故障的备份/备用节点继续提供服务。

4. Fail-Back:在主副本/主节点从故障状态恢复到正常状态之后,可以切回到主副本/主节点提供服务。

基于这样的原则,针对单机和集群两种情况,做出了以下设计。

单机:发现故障然后服务降级

在单机的环境中,系统发现故障之后,需要做以下的操作:

1. 周期性获取当前系统时间戳,并与上一次获取到的值对比,如果两者的偏差超过了容忍阈值,判定为出现了时钟故障。

2. 用户可以通过查看系统表中的某项,查看当前CnosDB节点是否处于时钟故障状态,此状态不会因CnosDB进程的重启而变化。

3. 出现故障后,只允许用户自行指定时间戳的数据写入,拒绝未指定时间戳的数据写入。

4. 用户可以通过使用管理员权限执行一条命令,解除当前CnosDB节点的时钟故障状态。

我们在处理单机故障时,可以用以下的用户接口设计去定义:

统一的命名规则

clock_fault_XX

系统变量/参数

1. clock_fault_check_interval

a. 获取系统时间戳并进行检查的时间间隔。

b. 默认值5min,可在线变更。

2. clock_fault_last_timestamp

a. 最后一次获取到的系统时间戳。

b. 只读。

3. clock_fault_check_threshold

a. 时钟故障的触发阈值。

b. 当前系统实际时间戳与clock_fault_last_timestamp + clock_fault_check_interval的差值超过此阈值时,当前CnosDB节点切换为时钟故障状态。

c. 默认值为1h,可在线变更。

4. clock_fault_state

a. 当前CnosDB节点是否处于时钟故障状态

b. 处于时钟故障状态,此值为error;反之,为normal。

c. CnosDB将此值设置为error时,需要同时在日志中进行记录。

d. 可在线变更,但只能由CnosDB管理员手动设置为normal,代表CnosDB管理员对目前的情况已经完全掌握并进行了相应的处理。

系统时间线

clock_fault_timestamp:记录每次进行检查时获取的系统时间戳,用户可以通过查看此时间线来判断时钟故障发生的具体时间点。

集群:复杂的故障发现与主备切换机制

在集群环境中,因为多节点的原因,处理的过程相对于单机的机制会更加的复杂,那么也有以下的相应操作:

1. 以每个CnosDB节点的单节点故障处理为基础。

2. 当一个节点处于时钟故障状态时,未指定时间戳的数据写入将自动路由到其他节点进行执行。

3. 定期检查集群所有节点的系统时钟:

a. N为当前集群内的主机(物理机、虚拟机或容器)总数量, μ为集群内全部主机某个子集,μ包含的主机数量超过N/2。

b. 如果存在一个μ在两个节点间的系统时间戳差值不超过一个预先设定的阈值,这个μ就可以称为时钟基准主机组。

c. 时钟基准主机组应尽可能包含更多主机。

d. 如果部署在时钟基准主机组中的所有节点都没有处于时钟故障状态,这些节点的集合就可以成为时钟基准节点组。

e. 当集群中无法找出一个时钟基准节点组时,整个集群将被判定为处于时钟异常状态。

f. 只有当集群中可以找到时钟基准节点组时,CnosDB集群管理员才可以将集群解除时钟异常状态。

g. 当某一节点的系统时钟与时钟基准主机组中一个节点的系统时钟的差值超过了一个预先设定的阈值,集群会将该节点的clock_fault_state设置为error(通过集群内部的一个账号,一般用户无法进行这样的操作)。

我们在处理集群故障时,可以用以下的用户接口设计去定义:

统一的命名规则

cluster_clock_fault_XX

系统变量/参数

1. cluster_clock_fault_check_interval

a. 集群范围内进行clock_fault_check的时间间隔。

b. 默认值5min,可在线变更。

2. cluster_clock_fault_check_threshold

a. 用于判定时钟基准节点是否存在的阈值。

b. 默认值为10s,可在线变更。

3. cluster_clock_fault_state

a. 当前CnosDB集群处于时钟故障状态时,此值为error;反之,为normal。

b. CnosDB将此值设置为error时,需要同时在日志中进行记录。

c. 可在线变更,但只能由CnosDB管理员手动设置为normal,代表CnosDB管理员对目前的情况已经完全掌握并进行了相应的处理。

系统时间线

1. cluster_clock_fault_base_clock_node_list:记录当前基准时钟节点组包含的节点列表。

2. cluster_clock_fault_base_clock_host_list:记录当前基准时钟主机组包含的节点列表。

结语

尽管系统时钟故障并不是一个时序数据库首要去考虑如何处理的故障,对于集群层面的时钟故障检测与处理,可能也不需要直接放在时序数据库这一层来实现,但这个思考和做大体设计的过程还是很有趣的,于是决定分享给大家。

如果大家有真实遇到这种问题的案例,可以告诉我们,这样本文中的设计会考虑得更加严谨,也会更快地在CnosDB中落地。


CnosDB简介

CnosDB是一款高性能、高易用性的开源分布式时序数据库,现已正式发布及全部开源。

欢迎关注我们的代码仓库,一键三连🙇🙇🙇:https://github.com/cnosdb/cnosdb

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容