bebeOracle CSSD(Cluster ServicesSynchronization Daemon)进程通过两个互相独立的心跳信号来监控集群节点的健康状况:network heart beatdisk heart beat

 

网络心跳:集群里每一个节点的CSSD进程的一个线程每秒会通过inteconnect发送一个TCP协议心跳信号给RAC里面的所有节点(包括自己)。如果心跳信号传输出现问题,TCP协议的自我矫正机制会重新传送数据包。这种情况下,oracle不会关注传输细节。

 

磁盘心跳:集群里每一个节点的CSSD进程会在voting磁盘的特定位置的数据块通过读写数据维持心跳信号。此外,每个节点还会监控其它节点CSSD进程维护的心跳信号数据块。如果发现某个节点在指定的时间内没有写入磁盘心跳,这个节点就被判决为死亡。如果一个节点处于未知状态,其它节点也会被通过更新它的voting disk上的kill block状态的方式把它驱逐出集群。

 

总的来说,网络心跳每秒都会发起,如果一个节点超出了参数css_miscount time设定的时间没有响应,就会被踢出集群。类似的,集群里的每个节点每秒读写voting disk特定区域,出现超时响应的节点也会被踢出集群。下面是节点面临的心跳可能出现的状况及后果:

wKioL1c2ys-ApCQwAAFBGyT5C8M355.jpg

脑裂: RAC环境里,所有的oracle实例都是通过高速私有网络互相通讯的。这个私有网络的链路都应该配置成冗余的,并且仅用于实例之间的oracle数据块传输。以含有运行在两台机器上的2个实例组成的RAC集群为例,当RAC集群里服务器运行正常,两个实例本身也运行正常的情况下,两个oracle实例不能够通过私有网络互相通讯时,如果不做预防,两个实例会各自独立的运行并对外提供服务。由于两个实例失去了互相之间的通讯,都会认为对方已死,从而不再使用原有的保护共享数据的机制,这会导致共享数据混乱。这就是脑裂。

 

IOfencing:如果操作系统正常但是oracle实例出现故障导致时,recovery进程可能会把之前故障实例残留的写操作执行。由于在这种情况下写操作无法保持正确的写入顺序,他们可能会导致数据混乱,所以必须阻止。所以,在集群环境里,如果一个节点故障,必须阻止它对共享存储的写操作。这种方法称之为IO fencing

 

简单多数原则:为了维持RAC集群正常运行,配置的仲裁盘必须有一半以上数量正常运行。


下面两个实例用来理解当心跳出现问题时,仲裁盘的作用机制。

例子1,如下图,三个节点的集群,配有3个仲裁盘. Node3与其它两个节点的网络通讯(network heartbeat)中断。但是,CSSD进程通过读仲裁盘状态发现所有的节点都可以写仲裁盘,这说明出现了脑裂。于是节点1和节点2就会更新仲裁盘上的节点3 kill block状态。然后节点3CSSD进程通过读仲裁盘上对应的kill block,知道自己应该退出集群。于是执行IO fencing,然后关闭自己。


wKiom1c2yeuiZJrYAAB8a25--UM662.jpg

例子2,配有3个仲裁盘的双节点集群,disk heartbeat出现问题,导致节点1可以访问2个仲裁盘,节点2可以访问1个仲裁盘。这时基于简单多数原则,节点1(两个仲裁盘)会发出自杀指令给节点2。这样节点2就会退出集群。

 

例子2中更进一步的问题,如果出现一个仲裁盘故障导致两个节点都不能访问它,但是另外两个仲裁盘对两个节点都可访问。这种情况下,如何判定该退出哪个节点?此时,由于两个节点可以访问的仲裁盘满足简单多数原则,如果此时Network heartbeat正常,RAC会正常运行,不会踢出任何一个节点。如果不幸,又有一个仲裁盘故障导致它不能被两个node访问,又会发生什么?

此时,网络正常,但是仲裁盘低于简单多数,所以RAC必然重构,但是两个节点条件一致。RAC会选择保留最低节点号的节点,在这个案例中,就是node1被保留,node2被踢出。


本文大部分内容来自需要科学上网的英文网站https://nitishanandsrivastava.wordpress.com/,我对其做了裁剪和引申。