编者按:
本文作者系肖遥(花名),现任甲骨文技术支持工程师 ,目前专注于Oracle RAC领域。个人主页:
https://blog.csdn.net/weixin_50510978,经其本人授权发布
【免责声明】本号文章仅代表个人观点,与任何公司无关。
积极的眼睛,还是败给了懒惰的双手。停更了一段时间,今天继续浅谈RAC的博文。
我们在前面的博客说集群是一组相互独立的、通过高速网络互联的节点(计算机),它们构成了一个组回,并以单一系统的模式加以管理。所以集群管理软件注定了要有网络互联的管理机制和共享磁盘的守护机制。在GI软件中,这个机制则是由组件CSSD来实现的。
集群中的每个节点都有CSSD守护进程,这些进程间会通过私网进行通信,并且定期向其它节点发送网络心跳,以此来确认不同节点间的通信状态。同时各个节点的CSSD还会定期向共享磁盘发送磁盘心跳,以保证所有成员节点都可以IO读写共同的磁盘。
1.Interconnect
我们在配置GI时需要在host文件中配置私网通信用(Interconnect)的IP地址。
代码语言:javascript复制[root@node1 ~]# cat /etc/hosts | grep private
192.168.3.11 node1-i private1
192.168.3.12 node2-i private2
这个私网通信地址就是CSSD进行网络心跳时所要用到的IP地址。这些IP地址的信息在安装GI时被root脚本写到了OCR中。所以我们通过oifcfg命令可以获得OCR中保存的网络配置信息。
代码语言:javascript复制[root@node1 ~]# oifcfg getif
enp0s8 10.10.3.0 global public
enp0s9 192.168.3.0 global cluster_interconnect,asm
2.集群心跳机制
ocssd.bin是个多线程的进程。其中clssnmSendingThread线程会每秒钟向集群中的所有节点通过TCP协议发送网络心跳信息(Network HeartBeat,简称NHB)。clssnmPollingThread线程则会接收这些网络心跳,并确认节点之间的连接状态。如果集群中的某一个或者一些节点持续的丢失网络心跳一段时间,则会发生Reconfiguration,其结果则往往是发生节点排除。
这里面需要强调的一个点是,发生节点排除时的条件必须是连续的丢失NHB。有些网络状态是时断时续的不稳定状态时,节点并不一定会被排除。那么这里面所谓的持续的丢失网络心跳一段时间则是由misscount参数决定的。
misscount是保存在OCR中的参数值。我们可以通过下面的命令获得该参数值。
代码语言:javascript复制[root@node1 ~]# crsctl get css misscount
CRS-4678: Successful get misscount 30 for Cluster Synchronization Services.
这个参数值也是可以手动设定的,其命令如下。
代码语言:javascript复制crsctl set css misscount <秒>
变更方法是:
- 只保留一个节点启动,停止其它所有节点。
- 在启动的节点上更改misscount。
- 将步骤2中原本启动的节点重新启动。
- 启动在步骤1 中停掉的其它节点。
但是这里面需要非常注意的地方是,一般情况下misscount这个值不要轻易的去更改。甲骨文官方也不会给出更改这个值的建议,misscount的初期值已经是甲骨文官方的最佳实践的值。如果客户不得不去更改这个值的时候,也必须在满足客户的SLA的情况下,在客户实机中进行充分的测试。
3. 本地心跳
与NHB相同,ocssd.bin每秒钟会向cssdagent和cssdmonitor发送本地心跳。如果本地心跳持续丢失时间超过了misscount值,cssdagent和cssdmonitor则认为ocssd.bin出了问题,会将本地的节点排除。
4.磁盘心跳
磁盘心跳(Disk HearBeat,简称DHB)的主要目的是当集群发生脑裂时帮助决定踢出哪个或者哪些节点。一个集群中可以设定复数个投票盘。我们可以通过下面的命令查看投票盘。
代码语言:javascript复制[root@node1 ~]# crsctl query css votedisk
##STATE File Universal Id File Name Disk group
-- ----- ----------------- --------- ---------
1. ONLINE 8cece9d66ad54fbdbf82a93486017586 (/u02/storage/asm1) [DATA]
Located 1 voting disk(s).
cssd.bin的clssnmvDiskPingThread线程每秒钟都会向集群中的所有投票盘注册本地节点的信息,同时也会将自己能够联系到的其它节点信息写入投票盘中。同时clssnmvDiskPingMonitorThread线程则会确定磁盘心跳信息。
与网络心跳一样,磁盘心跳也会丢失。磁盘心跳丢失的结果也是会发生节点排除。磁盘心跳丢失发生节点排除的机制则是当过半数的投票盘的IO处理都超过了设定的timeout值时,则该节点会被排除。
关于磁盘心跳的timeout值,甲骨文导入了两个timeout的概念:diskShortTimeout和diskLongTimeout 。
这两个timeout值是针对两个不同场景引入的。diskShortTimeout则适用于Reconfiguration时,diskLongTimeout 则适用于GI正常运行时。
代码语言:javascript复制 (正常稼动时) diskLongTimeout = disktimeout
(Reconfiguration时) diskShortTimeout = misscount - reboottime
disktimeout和reboottime也是保存在OCR中,可以通过以下命令获得。
代码语言:javascript复制[root@node1 ~]# crsctl get css disktimeout
CRS-4678: Successful get disktimeout 200 for Cluster Synchronization Services.
[root@node1 ~]# crsctl get css reboottime
CRS-4678: Successful get reboottime 3 for Cluster Synchronization Services.
这些参数值同样也是可以通过crsctl set css命令进行更改,但是与misscount 一样,通常情况下甲骨文官方不会给出更改这些值的具体建议。
投票盘IO丢失时,在集群的告警日志中会有CRS-1615,CRS-1614,CRS-1613的告警信息输出。他们分别代表投票盘IO丢失时间超过了timeout值的50%, 75%, 90%。
代码语言:javascript复制CRS-1615:No I/O has completed after 50% of the maximum interval. Voting file "string" will be considered not functional in "number" milliseconds
CRS-1614:No I/O has completed after 75% of the maximum interval. Voting file "string" will be considered not functional in "number" milliseconds
CRS-1613:No I/O has completed after 90% of the maximum interval. Voting file "string" will be considered not functional in "number" milliseconds
当超过半数的投票盘的IO丢失都达到了设定的timeout值时,CSS会被abort。
代码语言:javascript复制ERROR: ###################################
ERROR: clssscExit: CSSD aborting from thread clssnmvDiskPingMonitorThread
ERROR: ###################################
从上面的DHB丢失时节点排除机制我们可以看出,配置奇数个投票盘时更好一些,不会造成浪费。
投票盘是可以追加和删除的,以后会写专题介绍管理投票盘的方法和步骤。
5.脑裂
我们在解Oracle集群的问题时经常会听到脑裂这个概念。所谓的脑裂是指某些节点间丢失网络心跳,但是节点间DHB正常进行的情况。
发生脑裂的时候,往往需要进行节点排除来进行解决。发生脑裂时,集群会根据投票盘上的信息来确认节点间的连接状况,从而决定集群被分裂成哪几个子集群(Corhort)。基本原则是节点数多的Corhort存活。如果Corhort的节点数相同时,节点会根据内部的算法来估算weights来决定排除哪个Corhort。
这个估算weights的信息会被打印到OCSSD的日志文件中。
代码语言:javascript复制clssnmrCheckSplit: Waiting for node weights, stamp
需要注意的一点是,在11.2的版本中,如果Corhort的节点数相同,包含最小编号的节点的Corhort会被排除。根据weights来排除Corhort则是从12c开始的。
6.rebootless
在11.2.0.2以前的节点排除中,都是通过重启OS达到节点排除的目的。而在11.2.0.2中则导入了rebootless机制。导入的目的是尽可能减少OS重启。
很多朋友会认为rebootless机制的导入是替代了传统的OS重启的机制,这种认识其实是错误的。rebootless机制只能解决一时的或者集群软件上的问题,对于节点上真实存在的持续丢失网络心跳或者磁盘心跳的问题,单纯重启GI往往无法解决问题,这时候重启OS则往往是必要的。
关于rebootless的机制并没有公开的信息详细介绍算法,但是根据经验我们可以总结出以下的工作机制。
当出现私网通信问题时节点排除机制被启用。集群首先会去尝试停止所有的IO capable 进程。一旦所有的IO进程被清除,其它的进程也会被停止。当所有的进程被停止之后,GI会设定一个"restart flag"的标签,然后通过重启OHASD来重启集群,这就是Rebootless机制。
所以我们可以总结一下节点排除时发生OS重启的场景。
- 1 Rebootless在进行时CSSD本身发生预想不到的例外而被kill时,OS会被重启。
- 2 当IO capable 进程无法清除时,传统的节点重启方法将被启用,OS会被重启。
- 3 cssdmonitor 夯住时,OS会被重启。
- 4 GI停止超时时,OS会被重启。
其实关于节点排除时OS是否被重启,我们也没有更多必要去研究rebootless的机制。毕竟rebootless的导入本身只是为了减少OS重启的可能。如果一旦发生OS重启或者rebootless,我们应该还是更多关注于实际问题本身,纠结于rebootless发生的机制通常是没有更多意义的。
7.补充材料
上面我们提到了ocssd.bin的一些线程。这些线程我们是可以通过pstack命令获得的。
代码语言:javascript复制[root@node1 ~]# pstack 13808 | grep clssnm
#3 0x00005620c56617a2 in clssnmWaitThread ()
#4 0x00005620c5670b2b in clssnmvDDiscThread ()
#3 0x00005620c56616d8 in clssnmWaitThread ()
#4 0x00005620c5667d99 in clssnmvDiskPingThread ()
#3 0x00005620c56616d8 in clssnmWaitThread ()
#4 0x00005620c56706e8 in clssnmvKillBlockThread ()
#3 0x00005620c56616d8 in clssnmWaitThread ()
#4 0x00005620c566bb3e in clssnmvWorkerThread ()
#3 0x00005620c56616d8 in clssnmWaitThread ()
#4 0x00005620c5668fc7 in clssnmvDiskPingMonitorThread ()
#3 0x00005620c56616d8 in clssnmWaitThread ()
#4 0x00005620c566242f in clssnmPollingThread ()
#3 0x00005620c56616d8 in clssnmWaitThread ()
#4 0x00005620c5661421 in clssnmSendingThread ()
#3 0x00005620c56617a2 in clssnmWaitThread ()
#4 0x00005620c563a406 in clssnmRcfgMgrThread ()
#7 0x00005620c56409ae in clssnmClusterListener ()
#3 0x00005620c5636e50 in clssnmNMGetStatus ()
一谈到CSS,大部分问题都是关于NHB和DHB的问题。对于集群来讲,理解NHB和DHB是非常重要的。因为实际应用中,节点重启现象是常见问题,如果无法理解CSS的机制,往往遇到这类问题则无的放矢。所以今天的内容对于GI来讲非常重要,感兴趣的同学一定要花点时间去理解和巩固。