在维护IRIS的镜像前,管理员需要清楚的了解以下一些概念:
Mirror的切换模式(failover mode)
切换模式在镜像监视器里被翻译成”故障转移模式“。 有两种模式:
- Agent Controlled模式:
- Arbiter Controlled模式:(页面上翻译为“仲裁程序受控制”)
通常情况,生产环境的镜像是安装了arbiter(仲裁者)的。Mirror启动时,在还没有连接上arbiter的时候,自动进入Agent-Controlled模式。而后当两台机器,主机,备机都连通了Arbiter,会保持在这个模式。
- 主备之间有连接;
- 又都连到arbiter;
- backup is active,
满足上面的条件,就进入arbiter controlled mode。而如果主备的任一方,失去了和arbiter的连接,或者备用侧丢了active, 开始尝试连接另一方,退回到agent-controlled模式。
Mirror同步成员的状态
Mirror Member Journal Transfer and Dejournaling Status. 请注意,这里面有两个概念:一个是Mirror成员的状态,一个是Journal传输和Dejournaling的状态。下面的图中是3个字段: STATUS, Journal传输,Dejournaling.
STATUS
镜像成员的状态。 正常工作状态
- 对于同步成员,是Primary(主), Backup(备机)。
-
对于异步成员,正常状态是Connected(已连接)
-
In Trouble : 如果主机In Trouble, 是失去了到backup的连接。备机收到主机的同步数据是要返回证实(Ack)消息的。一旦出现问题,主机无法收到备机的Ack, 主机就会把备机标为"In trouble", 从此再也不会向备机发同步数据。
- Transition: 暂时状态,进程正在查看一个成员的状态,很快会转换到一个稳定状态。 如果在mirror配置的member中发现了primary,本机会进入Synchronizing状态,否则自己会尝试进入primary状态。
- Sychronizing: 从Primary接收journal,同步数据库。
Journal Transfer and Dejournaling Status
Journal Transfer是主机向其他成员发送Journal文件。而Dejournal是把Journal文件读入数据库。 对于backup或者asycn成员,Journal Transfer状态表示镜像成员是否有来自主数据库的最新日志数据,如果没有,则表示日志传输的落后程度,Dejournaling表示从主数据库收到的所有日志数据是否已经被dejournaled(应用到成员的镜像数据库),如果没有,则表示dejournaling的落后程度。
上图中显示的是正常的状态,其中主机 Journal Transfer 和 Dejournaling 都是N/A, 表示不适用。
对于其他成员,我们分开看:
Journal Transfer状态
-
Active: backup的正常状态。说明backup从primary收到了最新的journal。注意哪怕是Dejournal状态只是“x秒落后“,而不是"被捕获",Journal Transfer状态也可以是Active,只要是从主机收到了最新的Journal更新。
-
Caught up(被捕获) : 备机被捕获状态,说明备机从主机收到了最新的journal数据,但主机没有在等待备机的证实消息。 这通常是一个暂时的过程,当备机在连接主机的时候会出现。 异步成员,因为不需要向主机发证实,所以正常的状态就是“被捕获”
If the Primary Failover Member does not receive an acknowledgment from the Backup every Heartbeat Interval period, it demotes the Backup system from Active status to Catch-Up mode.
-
time behind (多少秒落后)
-
Disconnected on time(断开): 在一个时间点上这个成员和primary断开了。
Dejournaling状态
- Caught up
- time behind
- Disconnected on time
- Warning! Some Databases need attention
- Wanring! Dejournaling is stopped
正常状态下的图;
备机Backup MirrorB, Journal Transfer是Active, Dejournaling是Caught up, 异步机器MirrorDR的Journal Transfer状态和Dejournaling状态都是Caught up. 表示它们收到了最新的journal数据,并且也都把最新的global修改写入了自己的数据库。
Mirror的自动切换
Mirror的核心是自动切换。Backup接替主机的工作有两个前提:1. 备机在同步(Active) 状态, 2. 主机不能正常工作。在这两个前提下,我们来看看自动切换的触发条件,涉及主机,备机,仲裁机之间的通信,
自动切换触发条件
- Primary要求Backup接替。这种情况,主机会发生一个请求消息给备机, 要求备机接替。
- 主机IRIS正常退出
- 主机发现自己hung
-
备机收到arbiter的请求,报告失去了到主机的连接。
仲裁机要求是和外部系统以及应用服务器部署在一个网段的。如果仲裁机无法联络主机,可以认为其他的应用系统和服务器也无法连接主机。有可能主机宕机, 也有可能主机还在正常工作,但外界已经无法联络它了, 这时候也是需要备机接手的。
这时备机也要再去核实一下,是不是能联络到主机。如果能联络到, 备机会发请求让主机Down。如果不能, 说明主机要么死了, 要么失联了, 备机先接手,等联络上再让对方force down.
-
从主机的ISCAgent收到消息,报告Primary已经down or hung.
在agent-controlled的情况。 primary的服务器还活着。备机主动去问主机的agent, 一旦agent报告主机死了, 那备机就可以上位了。
Mirror的进程
管理员应该了解mirror涉及的那些进程。当出现故障时,这些进程名字,或者称为User, 经常会出现在message log记录的故障描述中。
On Primary Failover Member(主机)
我们来一个个的看看这些进程:
- Mirror Master: 系统启动时自动启动,负载mirror control 和管理。
- Mirror Primary: 出向数据传输通道。 上图中有两个Mirror Primary进程,状态时RUNW, 一个连接MirrorB, 一个连接MirrorDR.
- Mirror Svr: Rd*: 入向证实通道(inbound acknowledgement), 也是单向的。 上图中同样有两个此进程,状态都是READ, IP地址分别是MirrorB和MirrorDR.
- Mirror Arbiter: 到aibiter的通信进程,注意它的状态是"EVTW", 也是个单向写的频道。
On Backup Member/Async member(备机)
Mirror Masht, Mirror Arbiter不再重复解释,我们看看其他进程是干什么的。
-
Mirror JrnRead: Mirror Journal从Primary发送到backup是先写到硬盘的。 JrnRead进程把收到的journal同步读到内存里,然后才进行下一步,Dejournal的工作。
-
Mirror Dejour: backup机器的dejournal job进程。它把从Primary收到的journal中记录的global改变(set and kill)保存到本机的镜像数据库。
-
Mirror Prefetch: 这个稍微有点难懂。当收到的journal修改中包括了使用当前backup的journal中已有的内容时,比如收到了一个修改:set ^A=^B+1, 而^B当前存在backup里, Prefetch进程会把^B从硬盘拿到内存,以加快dejournal的速度。
-
Mirror Backup: two-way channel, 把收到的primary的journal写到backup的mirror journal,并且返回证实(ACK)
这里我省略了在DR上的进程,如果有兴趣,请自己查看文档。
MIRROR状态的监控
根据不同的场景,查看Mirror的状态有以下几种途径
使用镜像监视器
使用^MIRROR
如果您只是要简单的获得Mirror成员的状态,最直接的方法是使用^Mirror程序。 我们先看看在IRIS Terminal下^MIRROR的执行。
%SYS>do ^MIRROR
1) Mirror Status
2) Mirror Management
3) Mirror Configuration
Option? 1
1) List mirrored databases
2) Display mirror status of this node
3) Display journal file info
4) Status Monitor
Option? 4
Status of Mirror MIRRORTEST at 08:09:24 on 05/19/2023
Arbiter Connection Status:
Arbiter Address: arbiter|2188
Failover Mode: Agent Controlled
Connection Status: This member is not connected to the arbiter
Journal Transfer
Member Name+Type Status Latency Dejournal Latency
-------------------------- --------- --------------- --------------
MIRRORA
Failover Primary N/A N/A
Press RETURN to refresh, D to toggle database display, Q to quit,
or specify new refresh interval <60> D
Database display is now on
Status of Mirror MIRRORTEST at 08:09:29 on 05/19/2023
Arbiter Connection Status:
Arbiter Address: arbiter|2188
Failover Mode: Agent Controlled
Connection Status: This member is not connected to the arbiter
Journal Transfer
Member Name+Type Status Latency Dejournal Latency
-------------------------- --------- --------------- --------------
MIRRORA
Failover Primary N/A N/A
Mirror Databases:
Record To
Name Directory path Status Dejournal
------------- ----------------------------------- ----------- -----------
TEST /isc/mirrorA/TESTDB/ Normal N/A
Press RETURN to refresh, D to toggle database display, Q to quit,
or specify new refresh interval <60>
在操作系统中执行^MIRROR
您可以把以下的代码写入您的脚本语言,查看mirror的状态
irisowner@mirrorA:~$ iris session iris -U "%sys" "Monitor^MIRROR"
Status of Mirror MIRRORTEST at 02:57:08 on 06/13/2023
Arbiter Connection Status:
Arbiter Address: arbiter|2188
Failover Mode: Arbiter Controlled
Connection Status: Both failover members are connected to the arbiter
Journal Transfer
Member Name+Type Status Latency Dejournal Latency
-------------------------- --------- --------------- --------------
MIRRORA
Failover Primary N/A N/A
MIRRORB
Failover Backup Active Caught up
MIRRORDR
Disaster Recovery Connected Caught up Caught up
Press RETURN to refresh, D to toggle database display, Q to quit,
or specify new refresh interval <60>q
Doneirisowner@mirrorA:~$
或者更简单的,只查看本机的mirror成员状态:
irisowner@mirrorA:~$ iris session iris -U "%sys" "LocalMirrorStatus^MIRROR"
This instance is a Failover member
Status for mirror MIRRORTEST is "Primary"
Current mirror file #2 ends at 681224
Min trans file #2 min trans index: 680744
irisowner@mirrorA:~$
如果您熟悉ObjectScript, 也可以使用$SYSTEM.Mirror
类的各个method来查看:
irisowner@mirrorB:~$ echo "write \$SYSTEM.Mirror.GetMemberStatus(),! halt" |iris session iris -U "%sys"
Node: mirrorB, Instance: IRIS
%SYS>
Backup
irisowner@mirrorB:~$
如果您要查看更多的内容,您可以更多的使用%SYSTEM.Mirror类的其他方法,比如%SYSTEM.Mirror.GetFailoverMemberStatus(.pri,.alt), $SYSTEM.Mirror.ArbiterState()等等。
使用Mirror_MemberStatusList存储过程
如果您从第3方的工具查询mirror成员的状态,还有一个简单的方案,就是调用%SYS命名空间的存储过程。下图是从iris管理门户调用的截图,你可以使用任何SQL客户端调用。
如果是从iris里执行,
%SYS>do ##class(%ResultSet).RunQuery("SYS.Mirror","MemberStatusList")
Member Name:Current Role:Current Status:Journal Transfer Latency:Dejournal Latency:Journal Transfer Latency:Dejournal Latency:Display Type:Display Status:
MDCHCNDBSL1.HICGRP.COM/STAGE:Primary:Active:N/A:N/A:N/A:N/A:Failover:Primary:
MDCHCNDBSL2.HICGRP.COM/STAGE:Backup:Active:Active:Caught up:Active:Caught up:Failover:Backup:
CDCHCNDRSL.HICGRP.COM/STAGE:Async:Async:Caught up:Caught up:Caught up:Caught up:Disaster Recovery:Connected:
通过SNMP获得
如果使用监控工具,您可以通过SNMP获得Mirror的状态,下面是最新的ISC-IRIS.mib中有关Mirror得指标部分。
.4.1.12 = irisMirrorTab | Table of current Mirror Members status and information
-- .4.1.12.1 = irisMirrorRow | Conceptual row for Mirror status and metrics | INDEX = irisSysIndex, irisMirrorIndex
-- .4.1.12.1.1 = irisMirrorIndex | unique index for each Mirror Member | INTEGER
-- .4.1.12.1.2 = irisMirrorName | Name of the mirror this system is a member of | STRING
-- .4.1.12.1.3 = irisMirrorMember | Mirror member name | STRING
-- .4.1.12.1.4 = irisMirrorRole | "Primary", "Backup", or "Async". | STRING
-- .4.1.12.1.5 = irisMirrorStatus | "Active" or "Activate". | STRING
-- .4.1.12.1.6 = irisMirrorJrnLatency | Mirror journal latency "Caught up", "Catchup", or "N/A". | STRING
-- .4.1.12.1.7 = irisMirrorDBLatency | Mirror database latency "Caught up", "Catchup", or "N/A". | STRING
MIRROR的日志和告警
通常情况下, 维护人员是通过mirror的日志和警告来获得Mirror状态,Mirror成员之间的连接情况,而不必须定时的用命令或者调用存储过程来查看。
Cache'和IRIS的日志和警告保存在两个文件: console.log/messages.log和alert.log, 其中alert.log中记录了console.log/messages.log中级别为2,3的记录, 并必须实时发送给管理员。有关这部分内容,请参考在线文档,或者我的帖子:
我们来看看在日志中有哪些mirror的记录:
Becoming primary mirror server
系统固有的通知消息, level =2。当一个iris实例从备机变成了主机,此信息会写到此实例的alert.log, 同时发送给管理员。 可以查看这个链接。
在Mirror切换时,管理员除了从刚刚接手的机器中收到Becoming primary mirror server的通知。如果原来的主机没有宕机或者从宕机中恢复,它也会将引起切换的故障从alert.log发送给管理员,是一个level2, 或者level3的记录。
Arbiter connection lost
level =2 , 自动发送给管理员。 当主机和arbiter失去连接后,在主机上会出现此警告。此时在备机上会出现“Switched from Arbiter Controlled to Agent Controlled failover on request from primary”的提示,是个level0的信息。
MirrorServer: Connection to xxxx(backup) terminated
MirrorServer: Connection to MIRRORDR (async member) terminated
当主机和备机(backup)失去连接,在主机上会出现level2的警告。 而和异步成员丢失连接,主机会出现level1的消息。尽管level1的消息不能自动通知管理员,但这时如果同时监控该异步成员的alert.log, 通常会有level2的警告消息发出,能提醒管理员检查MIRRORDR这个镜像成员的状态。
举例说明:如果在MirrorDR中操作系统重启,IRIS启动后会出现这样的level2的警告:“Previous system shutdown was abnormal, ^SHUTDOWN forced down”
Async member for MirrorSetName started but failed to connect to primary
level =2 , 自动发送给管理员
其他更多的关于Mirror出错的level2, 也就是警告记录, 比如:
- Could not open mirror journal log to read checksum, errno = 2
- Preserving all mirror journal files for offline failover member
- Server^MIRRORCOMM(d): Failed to notify MIRRORB for mirror configuration change
- Failed to become either Primary or Backup at startup
这不是个完整的列表,实际环境中会出现各种各样的告警通知。读懂这些通知,需要管理员了解镜像的原理,架构,以及上面介绍的镜像状态和进程的功能。
除此之外,绝大多数的level2日志的同时,会有更多的level0,level1的有关mirror变化的记录。这些内容不需要通知管理员,只是用于分析问题。 如图,下面是在一个messages.log里一个iris从备机变成主机的过程。
06/13/23-07:16:25:472 (2189) 0 [Generic.Event] MirrorClient: Switched from Arbiter Controlled to Agent Controlled failover on request from primary
06/13/23-07:16:26:274 (2189) 1 [Generic.Event] MirrorClient: Mirror_Client: Primary closed down, last # read = 504
06/13/23-07:16:26:301 (2189) 0 [Generic.Event] MirrorClient: Backup waiting for old Dejournal Reader (pid: 2190, job #31) to exit
06/13/23-07:16:27:394 (2189) 0 [Generic.Event] MirrorClient: Set status for MIRRORTEST to Transition
06/13/23-07:16:28:477 (1996) 0 [Utility.Event] [SYSTEM MONITOR] Mirror status changed. Member type = Failover, Status = Transition
06/13/23-07:16:30:261 (2177) 0 [Utility.Event] Returning to restart, old primary reported: "DOWN
06/13/23-07:16:31:524 (11721) 0 [Utility.Event] Applying journal data for mirror "MIRRORTEST" starting at 1538184 in file #2(/isc/mirrorB/mgr/journal/MIRROR-MIRRORTEST-20230613.001)
06/13/23-07:16:31:804 (2177) 0 [Utility.Event] Manager initialized for MIRRORTEST
06/13/23-07:16:31:986 (2177) 0 [Utility.Event] MIRRORA reports it is DOWN, becoming primary mirror server
06/13/23-07:16:32:381 (2177) 0 [Generic.Event] INTERSYSTEMS IRIS JOURNALING SYSTEM MESSAGE
Journaling switched to: /isc/mirrorB/mgr/journal/MIRROR-MIRRORTEST-20230613.002
06/13/23-07:16:32:426 (2177) 0 [Utility.Event] Scanning /isc/mirrorB/mgr/journal/MIRROR-MIRRORTEST-20230613.001
06/13/23-07:16:32:479 (2177) 0 [Utility.Event] No open transactions to roll back
06/13/23-07:16:32:485 (2177) 0 [Generic.Event] MirrorServer: New primary activating databases which are current as of 1538184 (0x00177888) in mirror journal file #2
06/13/23-07:16:32:488 (2177) 0 [Generic.Event] Changed database /isc/mirrorB/TESTDB/ (SFN 5) to read-write due to becoming primary.
06/13/23-07:16:32:924 (2177) 0 [Utility.Event] Initializing Interoperability during mirror initialization
06/13/23-07:16:32:930 (2177) 2 [Utility.Event] Becoming primary mirror server
更多的有关mirror监控和排除的问题, 请各位留言。 谢谢