Oracle RAC 值得上吗?处理过 3 次节点驱逐后,聊聊 RAC 和 ADG 的真实取舍

🔑 关键词:Oracle RAC, Active Data Guard, 数据库高可用, 节点驱逐, 单实例ADG

📖 摘要:从三次真实的 RAC 节点驱逐事故出发,拆解 Cache Fusion 的隐藏成本、私网 MTU 这个经典坑、连接池重连风暴,以及 RAC 和单实例+ADG 在 License、RTO、故障域上的具体差异。附可执行的排查命令和参数清单。

先把结论放前面

图片

RAC 不是“加强版的高可用”,它是一个为了解决特定问题而设计、代价很高的架构。如果你上 RAC 的唯一理由是“高可用”这三个字,那大概率是选错了。我经手过的集群里,真正需要 RAC 的不到三分之一,剩下的其实一套单实例 + Active Data Guard 就能覆盖,还能省掉至少一半的 License 和一大半的运维心智负担。

这篇文章不讲概念,讲我踩过的坑。

凌晨 2 点 40 的那次驱逐

去年 11 月,一个 4 节点 RAC,x86 + 万兆私网 + ASM,19c。凌晨 2 点 40,node3 被驱逐。$GRID_HOME/log/<host>/cssd/ocssd.log 里的日志很干脆,先是 missed 3 heartbeats,接着就是 node eviction initiated。从心跳丢失到节点重启,整个过程 78 秒。

真正要命的不是这 78 秒,是这 78 秒之后发生的事。node3 上大概 1200 个会话全部断开,这些会话背后的连接池同时开始重连。HikariCP 默认 maximumPoolSize 是 10,但生产上没人用默认值,我见过配 200 的,再乘以 4 个节点上跑的应用实例数量,重连请求轻松上到几千。这些请求全部涌向剩下 3 个节点,CPU 打到 100%,gc buffer busy acquire 开始堆,node1 也跟着不健康了。

图片

这就是级联故障。故障本身只干掉了 1/4 的容量,重连风暴差点干掉全部。我们后来做了两件事:私网交换机开 jumbo frame(MTU 9000),以及给连接池加指数退避的重连策略。之后半年没再炸。

私网 MTU:藏得最深的那个坑

那次故障查了两天才定位到根因,是 MTU 不一致。服务器端私网网卡配了 9000,交换机没配 jumbo frame,结果就是大包被静默丢弃,小包(也就是心跳)正常通行。你在服务器上 ping 是通的,cluvfy comp nodereach 也是通的,但心跳就是在特定负载下丢。

验证方法很简单,Linux 上跑:

图片

ping -M do -s 8972 <私网对端IP>

8972 + 28 字节包头 = 9000。如果不通就说明链路某一段的 MTU 不够。另外用 ip -s link show <iface> 看 dropped 计数,用 netstat -s | grep -i retrans 看重传,这两个数字比任何监控图表都诚实。

顺带说个参数:Linux 上 CSS 的 misscount 默认是 30 秒,disktimeout 默认 200 秒,用 crsctl get css misscountcrsctl get css disktimeout 可以查。我不建议把 misscount 调大,那只会拉长故障检测时间,真正该修的是网络。

Cache Fusion 到底贵在哪

RAC 的核心是 Cache Fusion,数据块在节点之间通过私网传递。GCS 负责块级别的协调,GES 负责锁。听起来很美,但这里有个数量级的问题:本地内存读一个块是百纳秒级别,走私网 RTT 是几十到几百微秒。差三个数量级。

图片

所以判断一个业务适不适合 RAC,看一个指标就够了:写热点是否集中在少数几张表上。如果所有节点都在写同一张订单表、同一张流水表,私网流量会爆炸,gc current block 2-waygc buffer busy release 会直接反映出来。正常健康的 RAC,gc cr block 2-way 的平均等待应该在 1ms 以内,超过了就要去看 AWR 里的 Global Cache 部分。

Oracle 早就知道这个问题,所以做了 DRM(动态资源重配),把热块的所有权在节点之间搬家。但 DRM 在 11g 时代有不少 bug,remaster 期间会有短暂的性能抖动,12c 之后 _gc_policy_time 的默认值直接变成了 0,也就是默认关闭。你可以查一下自己库里的这个隐藏参数,如果是非 0 的值,想想是谁、什么时候、为什么改的。

还有一个容易被忽略的点:节点驱逐之后,剩下的节点要为失败节点做实例恢复,SMON 要回放失败节点的 redo。失败节点事务越重,这个恢复时间越长,我见过超过 3 分钟的。这期间整个集群的性能都是打折的。

RAC 和单实例 + ADG 的硬账

先把一个事实摆出来:Data Guard 的基础功能在 EE 里是免费的,但 Active Data Guard(实时只读查询 + Fast-Start Failover)是付费选件。RAC 同样也是 EE 的付费选件。

图片

再说 License 计费。x86 平台(Intel/AMD)的核心系数是 0.5,也就是 2 个物理核心折算 1 个 processor license。一个 32 核的服务器,折算下来是 16 个 processor license。这意味着:

维度 2 节点 RAC 单实例 + ADG
EE License 份数 2 份 1 份
额外选件 2 份 RAC 1 份 Active Data Guard
节点故障 RTO 节点驱逐 60-90 秒 + 实例恢复 + 会话重连 FSFO 默认 30 秒(可设 10-180 秒)
存储故障 不解决(共享存储挂了全挂) 解决
DROP TABLE / 误删 不解决 可以延迟应用,直接规避
计划内维护 滚动,接近零停机 switchover,通常 10-30 秒
跨站点容灾 需要 Extended RAC,对私网 RTT 要求苛刻 天然支持,就是主备关系
运维复杂度

FSFO 需要配 observer,一般放第三个站点,避免和主备任何一个一起挂。保护模式我建议 MaxAvailability,不要上 MaxProtection,后者在主库和备库都挂的时候整个库会停住,这在真实故障里是非常危险的赌注。

同步模式下每个 commit 都要等备库的 RFS 把 redo 落盘并回 ack,所以 commit 延迟 = 网络 RTT + 备库写盘时间。同城双活 RTT 通常在 0.5-2ms,对高频交易是致命的,对一般业务无所谓。这个账要提前算,不要等上线了才发现 TPS 掉了 30%。

图片

什么情况下 RAC 是真的必要的

说了这么多 RAC 的坏话,但也得说清楚什么时候它真的没得选:

  • 计划外维护窗口要求极高,比如年停机时间要求 5 分钟以内,ADG 的 switchover 那 10-30 秒都接受不了;
  • 已经在用 Exadata,RAC 是 Exadata 的默认也是最佳部署形态,这个不用纠结;
  • 单机 CPU 已经顶到物理上限,要的是真正的横向读写扩展能力(注意前提:写热点必须能打散);
  • 团队里有人真的看得懂 ocssd.log 和 AWR 的 Global Cache 段,这不是开玩笑,RAC 出故障时的排查门槛比单实例高一个档次。

反过来说,如果你的场景是“读写分离 + 同城容灾 + 能接受半分钟切换”,单实例 + ADG 是更理性也更省钱的选择。而且它解决了一个 RAC 根本解决不了的问题:存储故障和人为误操作。

最后说句实在话。我见过不少 RAC 集群,上它的理由写的是“高可用”,真实原因是采购流程里 RAC 是老传统,或者架构评审时有人问了句“为什么不用 RAC”。技术选型被流程惯性绑架,最后买单的是半夜被叫起来的 DBA。

🏷️ 标签: