Apache Ignite事务架构:故障和恢复

原创
2018/04/09 16:08
阅读数 5.8K

在本系列的上一篇文章中,探讨了并发模型和隔离级别,下面是本系列剩下的文章将要讨论的主题:

  • 故障和恢复
  • Ignite持久化层的事务处理(WAL、检查点及其他)
  • 第三方持久化层的事务处理

在本文中,会聚焦于事务执行过程中的故障和恢复。

一个分布式的集群由事务协调器、主节点和备份节点组成,部分或者全部节点故障是很有可能的,按照严重程度递增的顺序,如下所示:

  • 备份节点故障;
  • 主节点故障;
  • 事务协调器故障;

下面会挨个分析这些场景,讲解Ignite如何管理这些故障,先从备份节点故障开始。

备份节点故障

回顾一下本系列第一篇文章的内容,知道了在二阶段提交协议中,有准备和提交阶段。不管是那个阶段如果备份节点故障,对Ignite都不会产生影响,因为事务会继续在集群中剩余的主备节点上执行,如图1所示: 图1:备份节点故障

在所有的活动事务(包括这一个)结束之后,Ignite会因为节点故障而更新网络拓扑版本,然后选择一个或者多个节点来持有之前故障节点持有的数据,Ignite会在后台启动再平衡过程来满足所需的数据复制级别。

接下来,再看一下Ignite如何管理主节点故障。

主节点故障

主节点故障需要不同的处理,这取决于故障发生在准备阶段还是提交阶段。

如果故障发生在准备阶段,事务协调器会抛出一个异常,如图2所示(3 exception),之后应该由应用来决定如何处理这个异常以及下一步怎么做,比如,是重启事务呢?还是什么其他的异常处理。 图2:准备阶段主节点故障

如果故障发生在提交阶段,如图3所示,事务协调器会等待来自某个备份节点的特定消息(4 ACK)。 图3:提交阶段主节点故障

当备份节点检测到故障时,它会通知事务协调器事务已经成功提交。这时,因为有备份所以数据没有丢失,并且也不影响应用对数据的访问和使用。

事务协调器完成事务之后,因为主节点故障所以Ignite会进行集群的再平衡,它会选举一个新的主节点替代故障的主节点。 接下来,看一下Ignite如何管理事务协调器故障。

事务协调器故障

最糟糕的情况是事务协调器故障,这是因为主节点和备份节点只能感知到本地的事务状态,无法知道全局的事务状态。只有部分节点会收到提交消息而其他的收不到,如图4所示。 图4:事务协调器故障

这个故障场景的解决方案是,节点间互相交换它们的本地事务状态,如图4所示,这样他们就知道了全局事务状态。

这时,Ignite会发起一个恢复协议。工作流程是这样的,参与事务的所有节点都将消息发送给参与该事务的所有其它节点,询问它们是否收到准备消息。如果任何节点回复它没有收到准备消息,则事务将回滚,否则将提交事务。然而,一些节点可能在收到恢复协议消息之前已经提交了事务。对于这种情况,所有节点在一段时间内保留完成的事务ID信息。如果给定的ID没有找到正在进行的事务,则检查后台日志,如果后台日志也不包含该事务,则该事务就从没启动过。因此,如果故障发生在准备阶段完成之前,那么事务会被回滚。如果主节点或备份节点也与事务协调器一起故障,恢复协议也可以工作。

总结

在不同的阶段,各种类型的节点都有可能发生故障,通过上面的示例,会知道Ignite如何优雅地管理这些故障并且提供恢复机制。

展开阅读全文
打赏
1
2 收藏
分享
加载中
李玉珏博主

引用来自“我还在等你回家”的评论

作者我想转发一下你这篇文章,留你的原文地址,可以嘛

可以
2018/12/13 14:12
回复
举报
作者我想转发一下你这篇文章,留你的原文地址,可以嘛
2018/12/13 13:19
回复
举报

引用来自“lee_osg”的评论

你好,我看你的文章试着搭建了一个集群。昨天导入了上亿数据,结果一个SQL查询整个集群挂掉了。
现在每个节点都起来了,但无法激活集群。
在baseline都能看到节点,在visor激活就报错:
Suppressed: SchemaOperationException [code=3, msg=Table already exists: USER]
    at org.apache.ignite.internal.processors.query.QueryUtils.checkQueryEntityConflicts(QueryUtils.java:1126)
请问这种情况数据还能找回来吗?

引用来自“李玉珏”的评论

不了解你的实际情况,你是不是开启了持久化?
如果导入数据时间不长,你可以把持久化数据删除,然后重新加载一次再看
建议你如果了解的不够深入,可以逐步增加加载的数据量,慢慢加压,然后测试,不要一次加载大量数据,然后出问题了找不到原因。
😄现在把持久化、wal、wal_achive全删了,集群可以激活了。
😛期待更多文章分享啊,ignite挺好的
2018/04/12 14:47
回复
举报

引用来自“lee_osg”的评论

你好,我看你的文章试着搭建了一个集群。昨天导入了上亿数据,结果一个SQL查询整个集群挂掉了。
现在每个节点都起来了,但无法激活集群。
在baseline都能看到节点,在visor激活就报错:
Suppressed: SchemaOperationException [code=3, msg=Table already exists: USER]
    at org.apache.ignite.internal.processors.query.QueryUtils.checkQueryEntityConflicts(QueryUtils.java:1126)
请问这种情况数据还能找回来吗?

引用来自“李玉珏”的评论

不了解你的实际情况,你是不是开启了持久化?
如果导入数据时间不长,你可以把持久化数据删除,然后重新加载一次再看
建议你如果了解的不够深入,可以逐步增加加载的数据量,慢慢加压,然后测试,不要一次加载大量数据,然后出问题了找不到原因。
恩,是的,开启了持久化。然后用odbc连接的插入数据。这次也算压力测试,导入了1亿数据,做sql的limit查询,limit 1000000,1。是从100,1000,10000逐步增加看响应时间,没想到卡死了。
现在删除了persistence下的cache数据。😄网上资料比较少,国内搜到都你发布的,英文的谷歌也没多少结果。
2018/04/12 14:40
回复
举报
李玉珏博主

引用来自“lee_osg”的评论

你好,我看你的文章试着搭建了一个集群。昨天导入了上亿数据,结果一个SQL查询整个集群挂掉了。
现在每个节点都起来了,但无法激活集群。
在baseline都能看到节点,在visor激活就报错:
Suppressed: SchemaOperationException [code=3, msg=Table already exists: USER]
    at org.apache.ignite.internal.processors.query.QueryUtils.checkQueryEntityConflicts(QueryUtils.java:1126)
请问这种情况数据还能找回来吗?
不了解你的实际情况,你是不是开启了持久化?
如果导入数据时间不长,你可以把持久化数据删除,然后重新加载一次再看
建议你如果了解的不够深入,可以逐步增加加载的数据量,慢慢加压,然后测试,不要一次加载大量数据,然后出问题了找不到原因。
2018/04/12 10:40
回复
举报
你好,我看你的文章试着搭建了一个集群。昨天导入了上亿数据,结果一个SQL查询整个集群挂掉了。
现在每个节点都起来了,但无法激活集群。
在baseline都能看到节点,在visor激活就报错:
Suppressed: SchemaOperationException [code=3, msg=Table already exists: USER]
    at org.apache.ignite.internal.processors.query.QueryUtils.checkQueryEntityConflicts(QueryUtils.java:1126)
请问这种情况数据还能找回来吗?
2018/04/12 10:15
回复
举报
更多评论
打赏
6 评论
2 收藏
1
分享
返回顶部
顶部