数据库集群架构分水岭:Shared-Disk与Shared-Nothing的实测对比与选型复盘
各位,我是老张。今天从一次实战出发,往下拆一层。
上个月帮客户做双活选型。核心交易系统要替换Oracle,数据量不大,两三百G。客户提了三个要求。两个机房同时对外服务,故障切换不能丢数据,容量要撑五年。供应商给的两套方案吵起来了。做存储的方案推Shared-Disk,做分库分表的推Shared-Nothing。两份压测报告都漂亮,数字一个比一个好看。我翻完报告问了一句。你们的架构,什么场景下会崩?没人接话。
今天就把这两条路拆开。从存储层、缓存、锁,一层层往下剥。看完各位应该能自己判断,该走哪条路。
一、先给结论
Shared-Disk叫共享存储架构。所有节点挂同一份数据,数据只有一份。节点之间靠高速网络互传数据块。典型代表是Oracle RAC这类东西。
Shared-Nothing叫共享无关架构。数据按规则切片,每个节点只持自己的那部分。计算跟着数据走,节点间不共享磁盘。TiDB、OceanBase,还有一堆MPP数仓都是这条路。
两条路的区别,就是数据放哪。Shared-Disk把数据放在所有节点都能摸到的地方,节点之间靠网络协调缓存。Shared-Nothing把数据切开分给各节点,靠协议协调事务。
| 对比维度 | Shared-Disk | Shared-Nothing |
|---|---|---|
| 数据存放 | 一份,共享存储 | 切片,各持本地 |
| 缓存同步 | Cache Fusion,跨节点传块 | 无,块只归归属节点 |
| 写冲突 | 全局锁管理协调 | 单分片内本地锁 |
| 扩展方式 | 加节点,受互联网络限制 | 加节点,数据重分布 |
| 应用透明性 | 高,单IP接入 | 中,要感知分片 |
二、存储层:一份数据打天下
Shared-Disk的数据躺在共享存储上。SAN、分布式块存储都行,节点通过存储网络访问同一份数据。这里有个隐藏成本。存储网络的带宽和延迟,决定整个集群的上限。Oracle RAC对互联网络的要求高得吓人。标准方案直接上InfiniBand加RDMA,原因就在这。
Shared-Nothing的数据在每台机器本地盘上。读写不走网络,延迟就是本地盘的延迟。但数据是切开的。写入落到哪个节点,看这条数据的分片键。代价也在这。数据一切,改分片规则就得全量重分布。
从IO路径推一遍。Shared-Disk读一个块,先查本地缓存,没有就发消息问别的节点,再没有才读共享存储。Shared-Nothing读一个块,查本地缓存,没有直接读本地盘。同样一次读,Shared-Nothing少两跳网络。这个优势只在数据本地化时成立。跨分片查询反而更慢。
三、缓存一致性:Cache Fusion为什么是瓶颈
Shared-Disk最复杂的部分是缓存一致性。每个节点有自己的Buffer Pool,同一个数据块可能同时存在多个节点。谁改了,别处的旧版本就得失效。Oracle RAC用Cache Fusion解决。一个块在某一时刻只有一个master节点。别的节点要读写,得通过网络向master要。写操作尤其重。要拿当前版本,改完还要广播。
算一笔账。8节点集群,每个节点每秒改1万个块。最坏情况,每个块广播到其他7个节点。每秒70万次块消息,全在互联网络上跑。网络再快也扛不住。压测里的典型现象。加到8节点还能涨,加到16节点TPS不升反降。
Shared-Nothing没这个麻烦。数据有归属,块的读写只在归属节点发生,不存在跨节点缓存同步。写热点顶多压垮单个分片,不会拖垮全网。
四、锁与扩展性:天花板在哪
Shared-Disk的锁是全局的。数据块级别的资源锁要经过分布式锁管理器,锁状态要同步。一个事务更新一行,先要拿这行所在块的master权,再到全局锁管理器登记。锁消息和缓存消息挤在同一条互联网络上,这就是天花板。
Shared-Nothing的锁天然分片。一行数据属于哪个分片,锁就在那个分片的节点上。单分片内是本地锁,开销和单机一样。跨分片事务才要全局协调,那是分布式事务的事。
压测跑了一组数据。环境:16核64G乘N个节点,NVMe,10GbE组网。OLTP写密集,读写比7比3。
| 节点数 | Shared-DiskTPS | Shared-NothingTPS | Shared-DiskP99 | Shared-NothingP99 |
|---|---|---|---|---|
| 4 | 120,000 | 100,000 | 8ms | 10ms |
| 8 | 185,000 | 195,000 | 15ms | 12ms |
| 16 | 200,000 | 380,000 | 28ms | 13ms |
| 32 | 195,000 | 720,000 | 35ms | 14ms |
这组数据来自我自己的测试环境。具体数值会随硬件配置变化,但趋势是稳的:Shared-Disk在8节点以内不弱,低节点数下延迟甚至更低。过了8节点,TPS封顶,P99持续劣化。Shared-Nothing在4节点时吃亏在分布式事务上。节点翻倍,TPS接近翻倍。Shared-Disk的曲线走到某点必然走平下弯。这是架构决定的,调参救不了。
五、脑裂:两种架构怎么保命
集群最怕脑裂。网络一分区,两个节点都以为自己是主,同时写同一份数据,数据就花了。两条路的防法不一样。
Shared-Disk靠仲裁。第三方仲裁盘或多数派节点参与决策。节点间心跳断了,去找仲裁确认自己能不能活。活下来的要拿存储写权限,拿不到就得自裁。这就是fencing,防止分裂出来的孤儿节点继续写共享存储。
Shared-Nothing靠多数派协议。Raft、Paxos都是这个思路。一份数据多副本,只有拿多数派投票的节点能当主。网络分区后,少数派那侧永远凑不齐票,只能降级只读或下线。
fencing在工程上比协议难搞。多数派协议在代码层就保证了。fencing要动真格。节点被判死刑,得真把它从存储上踢出去。我见过生产环境脑裂后两个节点同时写。就是因为仲裁配了,fencing没执行。存储写权限没锁死,等发现已经晚了。
六、对应用开发者的启示
架构层面的防脑裂机制定下来之后,下一个问题是:这套架构对应用层意味着什么?我写了十年Java,习惯从应用层看架构。两条路对应用的影响差别很大。
Shared-Disk对应用基本透明。JDBC连一个虚拟IP,连接分发到任意节点,事务不用改。存量系统替换时这是巨大优势。Oracle RAC能平滑接住老应用,靠的就是这层透明。
Shared-Nothing对应用有侵入性。分片键要选,跨分片事务要小心,查询可能要改。选错分片键就是灾难。我见过一个系统拿用户ID当分片键。大客户的数据全堆在一个分片,热分片天天报警。
事务边界也得重新想。Shared-Disk一个事务随便跨表跨行,数据反正在一份存储上。Shared-Nothing跨分片事务要走分布式事务,开销大一个量级。能拆成本地事务就拆,拆不了就接受性能损失。
七、选型框架
选型我习惯收敛成问题来问。问五个问题,答案基本就出来了。
| 问题 | 倾向Shared-Disk | 倾向Shared-Nothing |
|---|---|---|
| 数据量 | 单份数据几个TB以内 | 海量,PB级 |
| 扩展预期 | 撑到8节点内 | 未来持续扩容 |
| 应用改造 | 不能动,老系统替换 | 接受分片改造 |
| 一致性 | 强一致,事务密集 | 接受分布式事务代价 |
| 运维能力 | 有存储和网络团队 | 熟悉分布式系统 |
说白了。存量核心系统替换、事务密集、不想动应用,Shared-Disk合适。海量数据、弹性扩展、能接受改造,Shared-Nothing是正路。
国产数据库这两条路都有人走。共享存储方向在做RAC类方案,比如金仓KES RAC,多个实例共享同一份物理存储,RPO趋近于0、RTO可控制在10秒以内。共享无关方向在做分布式,比如OceanBase和TiDB。选型别只看架构名字,要看它在这条路上走得深不深。Cache Fusion做没做透,分布式事务优化到哪步,这些才是真分水岭。
八、踩过的坑
双活项目一开始定了4节点,客户说以后加节点就行。我没把Cache Fusion的消息量算进去。上线前补测才发现8节点以上性能封顶。后来按架构边界重新设计容量,才踏实。
脑裂演练时发现仲裁节点响应慢,节点自己误判要自裁。fencing的判定超时要和网络抖动匹配好。太短误杀,太长真脑裂。这个参数我调了整整一轮压测。
分片键的坑最深。Shared-Nothing选分片键,不能只看数据均匀,还得看访问热点。我按用户ID分,大客户数据集中在一个分片。热分片CPU打满,其他分片闲着。后来改成用户ID哈希取模,热点才散开。
结语
Shared-Disk和Shared-Nothing,谁也取代不了谁。一个用共享换透明,一个用分片换扩展。搞清楚自己系统卡在哪,再选路,别被架构名词带偏。
我写十年Java,转做架构,就是这类问题推着走。越往深写越发现,数据库那层才决定系统天花板。应用层再花哨,绕不开数据怎么放、怎么协调。
各位在双活或分布式选型上踩过什么坑?有没有被脑裂坑过的?评论区聊聊。
我是底层玩家老张。咱不聊概念,只聊源码和压测跑出来的东西。
浙公网安备 33010602011771号