很多老系统其实还肩负着银行、保险、政务这些行业最核心的业务,COBOL就是其中最常见的一套“老古董”。别嫌它老,它跑了几十年,稳定得让人忘了它还活着。可正因为太重要,一旦这台“老古董”所在的机房出点事,比如停电、火灾、网络故障,整个业务可能就瘫了,客户取不了钱、交不了费,损失大到没法算。所以,咱们今天就从一个比较接地气的角度,聊聊在大型机这种特殊环境里,怎么给COBOL系统搭一套靠谱的灾备架构。
一、为啥要聊这个事
COBOL系统一般跑在大型机上,大型机那真是又贵又皮实,可再皮实也挡不住“天灾人祸”。比如某地发生地震,机房直接塌了;或者某个施工队一铲子把光缆挖断了;再或者运维大哥手滑敲错了一条命令,把生产环境的数据清掉了。这些情况一旦发生,业务必须能快速恢复,不然按分钟算都是钱。传统上,很多COBOL系统就是单机运行,连个备份资源都没有。后来大家开始做磁带备份、磁盘备份,但恢复可能要花好几个小时甚至一整天,这显然不行。所以灾备架构设计,就是为了让这些老系统遇到突发状况时,还能“断点续传”,用最短时间把业务拉起来。
二、灾备是个啥概念
别想得太玄乎,灾备就是给系统置办一份“保险”。平时生产机房正常工作,灾备机房在一边待命,等生产出事了,灾备顶上。这里面有两个关键数字:RTO和RPO。RTO就是“多久能恢复业务”,比如老板说最长只能停半小时,那你的RTO就是30分钟。RPO是“最多能丢多少数据”,比如业务说允许丢10分钟的数据,那RPO就是10分钟。举个例子,你手机里的照片,如果没开云备份,手机坏了就会丢最近几个月的照片,RPO就是几个月;如果开了自动备份到当天,那RPO就是一天。放在COBOL系统里,数据就是账本,丢了账那是要出大事的,所以RPO通常要求特别低,最好一分钱都不能丢。
既然要设计灾备,就得先明确应用场景。哪些系统需要灾备?不是所有系统都值得。比如一个内部管理系统,停半天也没啥;但涉及资金交易、社保发放、电信计费这类系统,一分钟都停不起。再比如一些监管要求严格的行业,比如银行、证券,监管部门直接要求必须做灾备。所以第一步,就是分清核心和非核心业务,把有限的资金花在刀刃上。
三、大型机环境下的难点
大型机跟普通服务器不一样,它有自己的生态。难点主要体现在几个地方:
第一,硬件设备贵。一台大型机动辄几百万上千万,灾备机房再配一台同样配置的,那预算简直吓人。所以很多时候,大家会采用“一主一备”但备用机配置略低一点的做法,不过能不能扛住生产负载,得做好验证。
第二,数据一致性要求极高。COBOL系统处理的是交易数据,比如账务、流水,容不得半点错乱。两台机器之间同步数据,稍微慢一点或者丢一笔,账就不平了。所以数据复制技术怎么选,非常关键。
第三,距离限制。大型机的同步复制对距离特别敏感,光信号在光纤里跑也有延迟,两机房之间超过几十公里,同步性能就会明显下降,所以同城双活通常限定在几十公里半径内。异地容灾距离远了,就只能做异步复制,数据会有些许延迟,这又跟RPO打架。
第四,运维和迁移难。COBOL程序员现在越来越少,懂得大型机灾备的更少。很多老系统跑了几十年,配置文件、作业调度、权限体系全都盘根错节,想挪到灾备机房,不是简单拷贝一个文件就行。这些历史包袱,让很多团队干脆“不敢动”。
四、常见灾备方案
先说说几种典型的方案,按启动速度排个队。
冷备,就是平时啥都不跑,只放着一台机器和一份备份数据。真出了事,先把机器打开,再把数据恢复回来。这种方式最省钱,但RTO往往要按小时算,适合能接受长时间中断的系统。
温备,比冷备好一点。备机上装了系统和应用,数据定期同步过去,比如每天同步一次。出事时启动备机,恢复个把小时能搞定,但数据可能会丢一天。
热备,备机随时在运行,数据实时或者准实时同步。生产一倒下,备机立刻就能接管。RTO可以压缩到分钟级甚至秒级,但成本也最高。
从地理维度看,又分同城双活和异地容灾。同城双活,就是两个机房在同一个城市,距离近,网络延迟低,可以做成双活模式,两边都在干活,互相备份。异地容灾,则在几百甚至上千公里外搞一个灾备中心,防止“整个城市都没了”这种极端情况,但距离远,数据同步只能异步,所以RPO会稍微长一些。
五、咱们的优化方案设计
结合COBOL系统的特点,我建议采用“同城主备+异地异步”的混合架构,既兼顾RTO和RPO,又不至于预算爆表。
5.1 整体架构
生产中心放一套完整的COBOL运行环境,包括大型机、磁盘阵列、磁带库。同城灾备中心放另一套几乎相同的环境,但平时不处理生产请求,只保持数据同步。异地灾备中心再放一台相对低配的大型机或者用大型机的LPAR逻辑分区,做异步数据复制。这样即使同城整个挂掉,异地方案也能把数据差补回来,保证核心账目基本不丢。
5.2 数据同步设计
数据同步是灾备的核心。对COBOL系统来说,最靠谱的方式是利用磁盘阵列的远程复制功能,比如在存储层面做同步镜像。生产数据每写一笔,存储立刻把这一笔复制到同城灾备的存储,生产确认写完后才返回成功。这种模式RPO基本为零,但需要足够的带宽和低延迟,所以同城距离不能太远。对于异地,用异步复制,生产写完后不管,后台慢慢把数据传过去,这样RPO可能会差几秒或者几分钟,但可以接受。
另一种方式是用数据库或中间件的复制工具,比如CICS日志复制、VSAM文件同步等。不过COBOL系统常常大量使用VSAM文件,直接同步文件比较麻烦,建议还是依赖存储复制为主,应用层做一些辅助校验。
5.3 自动切换流程
有了架构还得有流程。平时生产跑着,灾备中心盯着同步状态。一旦生产真的出问题,不能全靠人工去查,得有一套自动判断的逻辑。比如监控程序每30秒检查一次生产心跳,连续失败3次就拉响警报,然后让运维确认。确认后启动切换脚本,把VIP和域名解析切到灾备机器,然后启动灾备的COBOL应用。这一切看起来简单,真正落地细节非常多。下面就拿COBOL写几个小例子,让大家直观感受一下。
六、具体示例演示
技术栈:COBOL
这里我们用GnuCOBOL的语法写几个贴近灾备场景的小程序。它们不追求工业级完整,但能说明核心逻辑。第一个程序用来检查同步状态,第二个决定要不要切换,第三个记录切换日志。
示例1:检查同步状态
IDENTIFICATION DIVISION.
PROGRAM-ID. CHKSYNC.
* 模拟灾备同步状态检查程序
* 生产环境会生成一个状态文件,里面存着心跳数字
* 这个程序读取它,如果数字太旧,说明同步可能卡住了
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT STATUS-FILE ASSIGN TO 'SYNCSTAT.DAT'
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD STATUS-FILE.
01 STATUS-RECORD.
05 HEARTBEAT-NUM PIC 9(8).
05 LAST-TIME PIC X(20).
WORKING-STORAGE SECTION.
01 CURRENT-TIME.
05 CUR-DATE PIC X(10).
05 CUR-HOUR PIC X(8).
01 SYNC-ERROR PIC X(1).
88 SYNC-OK VALUE 'N'.
88 SYNC-BAD VALUE 'Y'.
PROCEDURE DIVISION.
MAIN-PARA.
OPEN INPUT STATUS-FILE
IF SYNC-STATUS-FILE NOT AVAILABLE
DISPLAY '状态文件不存在,灾备可能没同步'
MOVE 'Y' TO SYNC-ERROR
END-IF
READ STATUS-FILE
AT END
DISPLAY '文件是空的,同步异常'
MOVE 'Y' TO SYNC-ERROR
NOT AT END
IF HEARTBEAT-NUM < 100
DISPLAY '心跳数字低于100,同步可能滞后'
MOVE 'Y' TO SYNC-ERROR
ELSE
MOVE 'N' TO SYNC-ERROR
END-IF
END-READ
CLOSE STATUS-FILE
IF SYNC-OK
DISPLAY '同步状态正常'
ELSE
DISPLAY '同步状态异常,需要关注'
END-IF
STOP RUN.
这个程序就干了件小事:读状态文件,判断心跳数字是不是小于100。如果小于100,就认为同步出问题了。真实环境里,通常是由存储设备提供API,或者用系统命令去查同步进度,这里用文件模拟,更容易理解。
示例2:切换决策程序
IDENTIFICATION DIVISION.
PROGRAM-ID. SWITCHDEC.
* 这个程序负责决定是否要切换到灾备中心
* 输入参数是生产心跳次数和同步状态
* 输出结果是:1 表示立即切换,2 表示等待人工确认,3 表示暂不切换
DATA DIVISION.
WORKING-STORAGE SECTION.
01 PROD-HEARTBEAT-CNT PIC 9(5).
01 SYNC-OK PIC X.
88 SYNC-GOOD VALUE 'Y'.
01 DECISION PIC X(10).
PROCEDURE DIVISION.
DECISION-PARA.
DISPLAY '请输入生产心跳次数:'
ACCEPT PROD-HEARTBEAT-CNT.
DISPLAY '同步状态是否正常?(输入Y/N):'
ACCEPT SYNC-OK.
IF PROD-HEARTBEAT-CNT = 0
MOVE 'PROD_DOWN' TO DECISION
ELSE
MOVE 'PROD_UP' TO DECISION
END-IF
IF SYNC-GOOD AND DECISION = 'PROD_DOWN'
DISPLAY '决策:立即切换'
END-IF
IF NOT SYNC-GOOD AND DECISION = 'PROD_DOWN'
DISPLAY '决策:先等待人工确认,避免数据不一致'
END-IF
IF DECISION = 'PROD_UP'
DISPLAY '决策:不切换,生产还活着'
END-IF
STOP RUN.
这里没有用复杂的编排,就是让运维人员输入两个信息,程序给个建议。真实自动驾驶切换会复杂得多,但核心逻辑就是:生产死了,同步还正常,就切;同步不正常,切过去也是脏数据,还是先问问人比较好。
示例3:记录切换日志
IDENTIFICATION DIVISION.
PROGRAM-ID. SWLOGGER.
* 每次发生切换或演练,都要把过程记录到日志文件
* 日志里包含时间、动作、状态和备注
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT LOG-FILE ASSIGN TO 'SWITCH.LOG'
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD LOG-FILE.
01 LOG-RECORD.
05 LOG-DATE PIC X(10).
05 LOG-ACTION PIC X(10).
05 LOG-STATUS PIC X(10).
05 LOG-COMMENT PIC X(50).
WORKING-STORAGE SECTION.
01 WS-CURRENT-DATE.
05 WS-DATE PIC X(10).
PROCEDURE DIVISION.
OPEN EXTEND LOG-FILE.
MOVE FUNCTION CURRENT-DATE(1:10) TO WS-DATE.
MOVE WS-DATE TO LOG-DATE.
MOVE 'SWITCH' TO LOG-ACTION.
MOVE 'SUCCESS' TO LOG-STATUS.
MOVE '演练切换成功' TO LOG-COMMENT.
WRITE LOG-RECORD.
CLOSE LOG-FILE.
DISPLAY '日志已记录:' LOG-DATE ' ' LOG-ACTION.
STOP RUN.
这个小程序可以在切换脚本里调用,每次切换都留下痕迹,方便事后审计。有人说COBOL写这些太老土?其实大型机环境里的自动化编排,挺多就是用COBOL或者REXX写的,因为咱们的系统里到处是COBOL,用COBOL写运维工具反而省事,不用再搭一套技术栈。
七、技术优缺点分析
这套“同城主备+异地异步”的方案,优点很明显。RTO能控制在几分钟内,因为灾备机一直在待命,存储层做了同步,应用启动很快。RPO也基本为零,主备数据一字不差。而且用存储复制,对COBOL应用透明,不用改业务代码,这非常关键。老系统最怕动代码,万一改出问题,比灾备还头疼。
缺点也逃不掉。第一,成本高,同城灾备需要一台几乎等配置的大型机,磁盘阵列也要成对买。第二,存储同步依赖专用硬件和光纤链路,链路一断,整个存储可能会自动停止对外服务,这在很多存储上是一种保护机制,但可能会导致生产也挂,这就有点“同生共死”了。第三,同城距离有限,如果整个城市发生灾难,比如大地震,同城灾备也跟着完蛋,所以必须要有异地异步做兜底。第四,异地异步总会有数据延迟,如果生产突然死掉,最近一小段交易可能丢了,只能靠事后补账或者冲正来解决。
八、注意事项和踩坑经验
这里分享几个我亲眼见过的坑。
第一个坑是演练不认真。很多公司灾备方案做了一大堆,但一年也舍不得演练一次。真出事的时候,切换上去发现数据库文件权限不对、应用连不上、IP地址冲突,这都太常见了。所以至少每季度要做一次切换演练,而且不能提前通知到所有人,要模拟“突袭”状态。
第二个坑是链路质量不过关。同城同步复制对链路的时延和抖动极其敏感。有的公司为了省钱,用电信的公共线路而不是裸光纤,结果高峰期网络拥塞,存储同步的响应时间暴涨,生产写入直接被拖慢。这种情况宁可用专用的DWDW波分线路,也不要在同步复制上凑合。
第三个坑是忘了“人”的因素。COBOL系统老,会的人少,灾备切换需要几个关键角色配合:主机运维、网络运维、应用操作、业务确认。如果没提前写好切换预案,也没指定“谁来按下最后那个切换键”,大家到了现场手忙脚乱。建议把切换步骤做成一张纸质检查单,每一步谁确认签字,都写得明明白白。
第四个坑是忽略数据除了“文件”还有“日志”。COBOL系统里像VSAM、DB2、CICS的日志,都分散在不同的位置。做灾备复制时,存储层面复制了数据文件,但应用的一致性必须靠日志完整。如果日志复制顺序乱了,恢复出来的数据可能逻辑不一致。所以一定要保证复制操作是按时间序列逐起来的,最好让存储的复制组把同一个应用的磁盘绑成一个一致性组,这样所有磁盘的快照是同一时刻的。
第五个坑是恢复之后没有“倒回去”的方案。灾备切换过去,生产那边修好了,还得切回来。切回来同样要精心设计,不是简单反着来一遍。如果灾备系统运行了一段时间,产生了新的交易数据,这些数据也得回灌到生产中心。现实中就有企业切过去了,结果灾备中心改成新生产,老中心做成了灾备,再也不切回去,这也算一种“将错就错”的无奈选择。
九、总结
COBOL系统再老,也是许多行业的中流砥柱。给这种系统做灾备,不能生搬硬套云原生的那套思路,得尊重大型机自己的生态。我的核心观点是:先用RTO和RPO把目标定死,再根据预算选冷、温、热,最后用“同城同步复制+异地异步复制”的组合来兜底。重点从来不是技术多花哨,而是能不能把数据完整地保住,能不能在最短时间内让业务回归。文中那三个COBOL小示例,其实就是灾备系统里最常见的三个动作:看货、拍板、记账。它们本身不复杂,但组合起来就是一套可操作的落地流程。最后再啰嗦一句,灾备这东西,最怕的是“纸上谈兵”。你把它搭好了,只是万里长征第一步,定期去演练,把它当成一次真实的灾难去推演,才是真正对业务负责。希望这篇大白话的博客,能让你对COBOL灾备这事心里更有底。
评论
围绕“COBOL系统的灾备架构设计:大型机环境下的高可用方案优化”参与讨论