2020年之后,我接手过不少核心业务系统的数据库改造,无论客户底子是新上的私有云,还是老机房里跑了很多年的集中式架构,只要你把“确保数据库高可用”这五个字摆到台面上,Oracle RAC一定是那张绕不开的主牌。尤其在Oracle Linux 8.4这套操作系统已经非常成熟的今天,RAC从部署到运维的整个链路都比前几年顺滑太多。这篇文章我就结合自己在生产环境里真实搭过的环境,把Oracle Linux 8.4上配置Oracle RAC集群这件事从头到尾捋一遍,重点讲高可用性和负载均衡这两个目标是怎么落到具体配置上的,也算给准备入坑的朋友一份现成的参照。
我会尽量说人话,把每一步为什么这么做、踩过什么坑、哪些配置一疏忽就出事故都讲清楚。内容按项目落地顺序来走,你可以直接当作一份操作前自查清单,也可以对照你正在搭的环境逐步核实。
1. 为什么企业级数据库要选RAC而不是其他方案
1.1 RAC的核心价值:不止是故障切换
很多刚接触高可用的人会把RAC和Data Guard或者双机热备混在一起,其实这是两码事。RAC是Oracle自家的多实例共享存储架构,同一份数据文件被多个节点的数据库实例同时打开,任何一个实例挂了,应用连接会自动切到幸存的节点上,数据库服务不停、数据不丢。而Data Guard本质是一套日志复制的备库机制,角色切换的过程通常需要几十秒到几分钟,应用层往往要改连接串甚至重启中间件。
RAC最打动人的地方在于它把高可用和性能横向扩展一起解决了。比如你有两个节点,每个节点4路CPU 256GB内存,平时两个节点都在干活,各自承担一半连接,而不是像主备架构那样主节点干活、备节点在旁边干等。对于企业级OLTP业务来说,这种“不浪费一台机器”的设计本身就是最大的价值。
还有一点容易被忽略:RAC天然提供了应用层透明的连接管理。配上SCAN监听器和Service之后,客户端只要知道一个固定域名,连接请求会在这个域名的所有监听之间自动分发,哪台机器参与服务、哪些节点被踢出了集群,应用什么都不用感知。
1.2 高可用系统选型时要权衡什么
很多客户一开始就问“RAC、LVS、中间件集群我到底该上哪一个”。这里我想多讲两句。LVS是网络层的负载均衡方案,它解决的是流量分发问题,从不关心Oracle实例是不是活着。中间件集群比如WebLogic、Tomcat的集群,负责处理应用请求的可用性,但数据库一旦瘫痪,应用层再高可用也是空中楼阁。
真正合理的组合拳是:网络层有LVS或者F5这类入口设备做流量入口高可用,应用层中间件做业务无状态水平扩展,数据库层用RAC保证最终数据服务的连续可用和并发吞吐。三层各干各的,职责边界清晰。所以如果你问我企业级数据库的高可用,我的答案永远是先把数据库这一层的RAC建立在正确的轨道上,再谈上层的东西。
2. 准备阶段决定成败:环境规划与硬件清单
2.1 Oracle Linux 8.4上的安装前置条件
Oracle Linux 8.4是RHEL8系的操作系统,默认自带UEK R7内核,兼容性非常好。装Oracle Grid Infrastructure和数据库软件之前,有几个硬性条件必须提前满足,少一个后面都会卡住。
硬件层面最低要求是节点数量不少于两个、每个节点物理内存不少于8GB、共享存储可用空间不低于100GB。这里的“共享存储”指所有节点能同时看到同样的裸盘或LUN,通常靠SAN存储或iSCSI模拟出来。
操作系统层面需要注意的点包括:
- 所有节点的内核参数、系统包、用户配置完全一致
- 主机名与/etc/hosts里的大小写、IP对应关系不能有差异
- 时间同步必须用NTP或者Oracle自带的CHRONYD服务,节点间时间差超过几百毫秒就可能被CSS判定为脑裂
- 所有节点防火墙必须放行特定端口,或者直接关闭内网防火墙
这里我强烈建议你用rsync或者Ansible把所有节点的/etc/hosts、/etc/sysconfig/network-scripts/的文件、以及用户和组定义一次性铺平。手工逐台敲配置是大忌,漏一台就等着后面装GI时通信验证失败。
2.2 网络IP规划:Public、Private、Virtual、SCAN一个都不能少
RAC集群的网络设计常常是初次部署者最容易搞混的地方。每个节点需要四类IP地址:
- 公网IP(Public IP):节点对外提供服务的日常IP,承载客户端的连接
- 私网IP(Private IP):节点与节点之间的专用通信地址,承载相关心跳与数据块传输
- 虚拟IP(VIP):节点故障时自动漂移到存活节点的地址,客户端如果直连VIP,就能实现秒级感知故障
- SCAN IP:整个集群的统一入口域名地址,通常配置三个IP,解析到同一个SCAN域名
以我经常用的两个节点规划为例:
节点1公网是192.168.10.21,私网是10.0.1.21,VIP是192.168.10.22;节点2公网是192.168.10.31,私网是10.0.1.31,VIP是192.168.10.32;SCAN域名rac-scan.localdomain解析到192.168.10.51、192.168.10.52、192.168.10.53三个地址。这样从客户端看,只需要知道一个SCAN域名,连接层的高可用和负载均衡基本就有了一半。
有很多人在/etc/hosts里简单地把SCAN域名指向一个IP,这是不允许的。SCAN IP要么交给DNS解析,要么用Oracle的GNS功能让集群自己管理IP。生产环境里我倾向于GNS加DHCP的方式,省去了让网络管理员反复跑流程的时间,但前提是网络设备支持DHCP保留地址。
2.3 共享存储的规划与UDEV规则绑定
RAC的架构模型可以简单理解成“多个脑袋共用一副身躯”,这份身躯就是所有节点共享的数据库文件。Oracle RAC的高可用性依赖两个底层组件:OCR和Voting Disk。前者保存集群配置信息,后者负责任务调度节点成员决策。这两个组件以及全部数据文件都必须存放在共享存储上。
通过虚拟机模拟或真实SAN环境,最直接的做法是给所有节点挂载同一批共享SCSI磁盘。操作系统启动后,不同节点看到同一块盘对应的设备路径可能不一样,这就需要通过UDEV规则把磁盘的WWID绑定为统一的设备名和权限。
给出一个典型的UDEV规则片段:
# /etc/udev/rules.d/99-oracle-asm.rules KERNEL=="sd*", SUBSYSTEM=="block", ENV{ID_SERIAL}=="36000c2938e6example1", OWNER="grid", GROUP="asmadmin", MODE="0660"规则里的ID_SERIAL重新写成你真实磁盘的序列号。绑定后重启系统,或者手动执行udevadm trigger,然后检查ls -l /dev/sd*是否正常。这里最常踩的坑是忘记把grid用户加入asmadmin组,导致ASM无法读写磁盘。
你还需要规划好ASM磁盘组的冗余策略。生产环境里我一般用正常冗余(Normal Redundancy),也就是三块盘或更多组成一个磁盘组,每个区保留两份副本,这样单块盘丢失不影响数据可用性。如果预算有限,外部冗余也不是不行,但就放弃了ASM层对数据的安全保护。
3. RAC集群安装过程的实操分解
3.1 Grid Infrastructure安装与常见坑位
环境准备好了,下面就是整个项目最耗时的部分:安装Oracle Grid Infrastructure。这套软件就是RAC的架子,提供了集群件、ASM、监听器、SCAN监听等服务。安装步骤如下:
先在第一个节点运行runInstaller,选择“设置Oracle Grid Infrastructure”,再选“配置Oracle Standalone Cluster”选项。GNS建议启用,如果前面规划没有使用独立DNS,此时就用固定域名和本机解析模式。安装界面里的网络接口eth0对应公网,eth1对应私网,一定要准确对应,错了后面排障非常痛苦。
root脚本执行顺序是先全部节点执行root.sh脚本,再回头执行rootupgrade.sh(如果安装完毕有提示)。这是Oracle官方推荐的套路,我自己第一次部署因为贪图省事在某个节点提前跑了root.sh,结果导致集群注册不全,后来花了一晚上重新配置oifcfg才救回来。
核心心法:跑root脚本时速度再慢也要按顺序来,并且一个节点一个节点确认执行成功后再继续下一个。
3.2 数据库软件与ASM磁盘组创建
GI装完,ASM实例会自动运行,此时用grid用户登录环境执行asmca,可以图形化创建磁盘组。生产库我习惯建三组磁盘:DATA组存数据文件、OCR组专门放OCR和Voting Disk、FRA组放归档日志和RMAN备份。数据量不大的话,DATA组也可以是外部冗余以节省空间,OCR和FRA建议Normal。
数据库软件安装比较简单,用oracle用户运行runInstaller选择“仅安装数据库软件”,语言选英文,选择“Oracle Real Application Clusters”安装类型。等待它把软件同步到其他节点,时间取决于节点数和后端存储性能,一般在十几分钟到半小时。
装好软件后,用dbca创建数据库并勾选“配置Oracle RAC”。这里有一步非常关键:全局数据库名和SID前缀要一致,实例名会自动加数字后缀。比如全局库名是oradb,那节点1实例就是oradb1,节点2就是oradb2。dbca过程中会让你选磁盘组,以及是否启用“归档日志模式”,生产库一定勾上,不然高可用只能算半吊子。
3.3 监听器配置与服务注册:负载均衡的地基
RAC环境的监听器有别于单机环境,SCAN监听器由GI自动配置并托管在所有节点上。安装完成后,可以通过这个命令检查:
crsctl status resource -t正常情况下,ora.scan1.vip、ora.scan2.vip、ora.scan3.vip这三个资源都会显示ONLINE,监听器ora.LISTENER_SCAN1.lsnr等也都处于运行状态。
RAC的负载均衡能力首先体现为连接到SCAN域名时,Oracle Net会轮流解析SCAN IP的地址,自动将新连接请求分散到不同节点的SCAN监听器。但如果你只配置了SCAN,却没有配置服务端负载均衡参数,那它还只是最基础的DNS轮询层面。
服务端要做两件事:一是确保每个实例都把本地监听地址注册到SCAN上,这个由REMOTE_LISTENER和LOCAL_LISTENER两个初始参数控制;二是为每个服务设置连接负载均衡目标。从Oracle 19c开始,最常用的做法是在dbca创建完库之后,直接用srvctl命令修改服务属性。
一个典型的负载均衡服务配置命令:
srvctl modify service -db oradb -service ORASVC -clbgoal SHORT -lbgoal LOW -preferred oradb1 -available oradb2这里CLBGOAL表示客户端连接池在服务层运行时负载均衡的时间粒度,SHORT适合短连接大量出入的场景;LBGOAL表示由RAC内部调度器为每个节点连接分配权重,LOW表示尽量平衡节点负载同时兼顾性能。
4. 高可用和负载均衡的机制是怎么真正落地的
4.1 CSS与OCR:保障高可用的神经系统
所谓的高可用性,在RAC内部说到底是一套“心跳检测 + 仲裁投票”机制。每个节点的CSS进程会定期通过私网网卡向其他节点发送心跳消息,同时每个节点对Voting Disk投票。一旦某个节点的私网心跳中断,其他节点会发起重新配置流程,决定是把失联节点驱逐出集群还是等待它恢复。
OCR相当于整个集群的元数据库,记录着每个资源的状态、每张配置参数、每个服务的偏好。RAC高可用能这么稳定,OCR的高可用起着定海神针的作用。生产环境里OCR放在ASM磁盘组,配合ASM的故障组,至少有两份副本,即使单块盘出了故障也不会丢失配置。
实战中让我印象最深的教训是:企业级高可用方案一定不能只靠系统层面自愈,还要定期备份OCR和Voting Disk。别问我为什么强调这个,2021年有客户升级GI版本时把OCR所在磁盘组误格式化了,那一刻我比谁都怀念会自动备份的备存储柜。
4.2 服务级别的负载均衡与故障切换的配合
负载均衡如果只是把连接平均分发到各节点,那还是最浅层的玩法。Oracle RAC真正让人舒服的是在“负载均衡”与“高可用”之间形成的联动。
我们来拆一个典型场景:应用连接池配置了SCAN地址,此时一个中型电商系统白天有2000个活跃连接。在没有故障时,这2000个连接会分散在节点1和节点2上,各承担1000个。节点1上的服务器CPU突然飙升到95%,数据库实例运行变得极其缓慢。此时负载均衡策略会将新的连接请求优先分配给节点2,并延迟将节点1的服务标记为“不希望接受新任务”。这是数据库层面的自适应负载均衡,不由网络设备决定,而是由实例的实际性能驱动。
另一个场景是节点2计划维护,你执行srvctl stop instance -d oradb -i oradb2,Oracle会先进行服务优雅关闭,待节点2上已有的连接处理完毕后,再将后续连接全部指向节点1,整个过程应用侧连接不会中断。这种滚动维护能力在关键业务变更时需要频繁使用。
4.3 连接池配置中的负载均衡参数
如果你在Java应用中使用UCP或WebLogic的连接池,有专门面向RAC的负载均衡优化。JDBC侧,Oracle 19c及以上的驱动在连接池创建时建议设置oracle.jdbc.fanEnabled属性。FAN(Fast Application Notification)是Oracle高可用与负载均衡很关键的桥梁——在数据库实例晋升、宕机、服务切换时,RAC会立即向订阅的客户端发送FAN事件,连接池收到事件后主动淘汰坏连接、提前预建新连接,避免客户端苦等网络超时。
配置文件里我习惯这样配:
<data-source-name>racDS</data-source-name> <connection-factory-class>oracle.jdbc.pool.OracleDataSource</connection-factory-class> <url>jdbc:oracle:thin:@(DESCRIPTION=(LOAD_BALANCE=ON)(FAILOVER=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=rac-scan.localdomain)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORASVC)))</url> <property name="connectionPoolCachingEnabled">true</property> <property name="connectionPoolPingInterval">1</property> <property name="fanEnabled">true</property>URL里的LOAD_BALANCE=ON表示连接池在每次创建新连接时,会从SCAN域名解析出的三个IP中通过等开销算法选择开销最小的一台服务器;FAILOVER=ON则允许在建立新连接时尝试备选监听地址。这两项分别对应了我们常说的负载均衡和故障转移。
需要注意的是,等开销负载均衡这个概念其实是Oracle Net Services和连接池共同协作的结果,它并非意味每秒连接数严格对半分,而是算法倾向于把每个新建连接的服务器负载维持在不同节点相近的水平。在连接池、FAN、服务调度三层配合下,整个系统的连接分布会越来越接近理论最优。
5. 常见故障排查与我的实操经验
5.1 节点被驱逐或集群脑裂的处理
RAC部署完成后,碰到的第一类故障往往是节点宕机、私网拥塞、时间偏差导致的节点驱逐。节点驱逐的直接表现是一个或多个实例突然被关闭,随后Oracle自动重启实例。排障的第一条命令永远是这个:
crsctl status resource -t如果某个节点处于OFFLINE状态,再查集群成员表:
crsctl status css -f这里可以看出CSS表决是否在进行。如果是两个节点之间私网心跳延迟很高,多半是私网交换机端口故障或网卡负载。一个实用的小技巧:用ethtool和netstat -i持续监控私网接口的错误包和丢弃包,RAC大多故障都能在网卡层面提前发现。
时间偏差引发的ORA-29701这类资源争夺,往往是因为NTP服务未正常启动导致节点时间漂移超过1000毫秒。Oracle Linux 8.4上我一般用chrony而不是老旧的ntpd,配置方式如下:
chronyc sources -v systemctl status chronyd如果时间差持续增大,说明上游时间源不可达,需要立即修正服务配置。
5.2 磁盘设备在重启后丢失的问题
共享存储配置一个很隐蔽的坑:服务器重启后UDEV规则可能重新执行,但ASM磁盘的设备路径会变。有一次我在客户现场把一台新的数据库节点接入了已有的RAC集群,由于UDEV规则写错了ID_SERIAL,导致新节点启动后一直没有发现OCR所在的ASM磁盘,集群直接把新节点踢出去了。
处理办法是先确认所有节点都能看到相同序列号的磁盘,然后统一应用UDEV规则,并刷新设备管理器。一条命令立即查看:
udevadm info --query=all --name=/dev/sdb | grep ID_SERIAL将返回的序列号复制进规则文件后,重启udev服务:
udevadm control --reload-rules udevadm trigger5.3 关于安装和日常维护的几条经验
这么多年搭过的RAC环境多了,有几个原则我一再给团队强调,现在也写在这里供参考。
第一,节点间所有配置必须一致性,包括时间、内核参数、环境变量、目录权限。任何一条不一致,排查时长都以小时起步。我最常用的自查手段是写一个循环脚本,对集群所有节点执行相同命令然后对比输出,比如sar、df、free、uname以及crsctl stat res的输出。
第二,高可用方案中要留出足够的“恢复窗口”。RAC虽然有自动重派功能,但它不会帮你解决冗余存储损坏和备份失效的问题。ASM磁盘组、OCR自动备份、归档日志备份这三件事必须纳入日常巡检。
第三,使用SCAN域名时,如果企业内部DNS支持,配置好轮询A记录后务必检查SCAN解析时间,不能让SCAN解析指向一个已经失效的IP。FAN事件和连接池之间如果没有配合好,应用报错可能要比手动切换多十几分钟。
第四,负载均衡不是一劳永逸的功能,需要你定期观察每个节点的AWR报告。如果两个节点实例负载差异较大,先别急着调整LBGOAL,可能是某条业务SQL存在热块冲突,那属于SQL调优的范畴了。
还有一点,也是我个人很感慨的一点:RAC环境的高可用性,说到底是靠运维纪律支撑的。软件本身的自愈能力再强,也抵不过你几个月不做一次恢复演练。每次新上一套RAC,我都会在项目交付前安排一次拔卡测试,把其中一个节点的私网线直接拔掉,观察整个集群在无人干预的情况下能否自动恢复。这才是检验高可用最真实的方式。