ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

无共享vs共享磁盘:数据库架构核心对比与选型实践

无共享vs共享磁盘:数据库架构核心对比与选型实践 系统架构师圈子里的争论往往不是哪个产品好而是底层架构思想的分歧。我印象比较深的是几年前参与一次数据平台选型评审业务方说得很直白你们技术团队别把简单事搞复杂我们就想找个地方把数据存进去、查得快一点。结果到方案评审两边吵起来了。一边说上Oracle RAC共享存储对应用透明主库挂了一个节点另外一个节点秒切另一边拍桌子说现在数据量一年翻三倍都往SAN堆预算和市场部都饶不了你必须上Hadoop这类无共享架构一堆普通服务器扛住PB级。这两派的底气分别来自数据库和数据工程两个完全不同的技术传统。它们争论的焦点正是Share Nothing无共享和Share Disk共享磁盘这两种架构。今天这篇就把这套东西从头到尾讲透从资源拆分、数据访问路径、真实系统形态到选型时容易踩的坑一次说明白。1. 先拆开来看CPU、内存和磁盘各自到底归谁1.1 CPU和内存两种架构其实没有本质区别很多人一开始会把这两个架构理解反总觉得Share Disk就是所有东西都共享。其实拆到硬件层面看CPU和内存这两样资源在绝大多数分布式系统里本来就是各节点私有的。一个节点自己跑自己的进程、用自己内存里的缓存不会有两台物理机同时在同一个内存地址上做读写硬件上也不允许。所以无论是Share Nothing还是Share Disk每个节点都拥有独立的CPU和独立的内存。这两个架构的核心分歧不在CPU也不在内存而在最后一个维度磁盘或者说底层存储。拿实际场景来说一台跑Oracle RAC的数据库服务器和一台跑Hadoop DataNode的普通服务器它们各自都有本地内存做Buffer Pool或Page Cache这部分逻辑差别不大。真正区分开来的是当内存里没有目标数据时这个节点到底从哪里把数据块读进来是读自己机箱里插着的那块SATA/SAS盘还是通过光纤交换机去读一个远端的、所有节点共享的LUN。这一条路径的差别后面会引发一连串连锁反应。1.2 分水岭在存储本地盘和共享LUN的天壤之别Share Nothing的名字已经说得很清楚——节点之间什么都不共享每个节点拥有自己独立的磁盘数据被切分成多个分片分散存放在各个节点上。节点之间通过网络通信平时各干各的数据在本地读、在本地写互不干扰。Share Disk则反过来所有节点共享同一个外置存储系统。存储可能是一台SAN阵列也可能是一个NAS文件系统所有节点通过存储网络访问同一份数据。对操作系统和数据库来说它就像插了一块超大容量的本地硬盘但真正的物理数据在存储阵列里躺着任何一个节点都能看到。不要小看这个差别。共享存储成为一个公用的数据地基之后系统就不得不同时回答两个问题第一多个节点同时去读写同一份数据怎么保证不会写坏第二每个节点在自己的内存里缓存了一份数据块另外一个节点改了盘上的数据这个节点的缓存怎么失效这两个问题是所有Share Disk架构绕不开的噩梦。而Share Nothing就没有这个问题数据在谁手上谁就完整管理这部分数据的读写别人根本碰不到也不需要碰到。代价则是一个跨多个节点的查询需要把数据协调起来问题从并发写同一块数据转化成了数据怎么分组、怎么路由、怎么合并。1.3 顺带说清Share Everything这套理论谈论这两个架构时还会遇到第三个词Share Everything。它通常指传统的SMP对称多处理单机架构。一台服务器里插着多颗CPU、共享一块内存、共享一块或多块磁盘操作系统和数据库天然认为整个机器是一个整体资源完全共享。严格对比的话Share Everything是资源向上聚合Share Disk是硬件各自独立、存储向下统一Share Nothing则是所有资源完全打散。三者之间没有明显高下之分只是面对不同问题的不同解法。如果你在跟人聊分布式数据库选型时能把这三层分清楚就已经比不少只盯着高可用扩展性这两个营销词的人强了。2. 数据访问路径一变整个设计都会跟着变2.1 Share Nothing数据在哪计算就去哪Share Nothing架构的一个核心原则是数据本地性。数据按某个维度比如用户ID的哈希值、主键范围、地理位置拆成N个分片每个分片落在一个固定的节点上。计算任务发下去之后尽量让每个节点只处理自己本地的那部分数据这样能最大限度减少网络上的数据传输量。Hadoop MapReduce就是这种思路的极致体现。JobTracker分配任务时会把Map任务调度到数据块所在的节点上原则是移动计算比移动数据便宜。因为存储和计算在同一个节点上数据完全不需要经过网络搬运。这个思想后来也延续到了Spark、Presto/Trino等引擎里虽然具体实现不同但底层对数据位置的利用逻辑一脉相承。当系统需要跨多个分片做关联查询或者聚合时代价就开始浮现了。比如一个订单表按用户ID哈希到128个节点上现在要统计某一天的全国订单总额你的查询会打给128个节点每个节点各自计算本地汇总再把128个中间结果合并到一起。数据量一旦大起来这一步的耗时就取决于最慢的那个节点以及合并层的网络吞吐任何一个掉队者都会拖慢整体。这个架构里还有一个隐藏前提数据分片一旦做好如果后续要按另一个维度频繁查询就可能需要全表扫描所有分片或者引入二级索引、全局索引来支撑。很多团队做完分片之后才发现业务要的不是单维度查询而是多维查询最后不得不回到宽表冗余的老路这其实是Share Nothing方案里最容易低估的一块成本。2.2 Share Disk计算和数据分割多个处理器去抢同一个仓库Share Disk好比多个收银台共享一个大仓库。收银台计算节点自己有人手、有零钱盒内存但所有货品都存在同一个仓库里哪个收银台接到顾客需求就去仓库取货。问题在于如果两个收银台同时想改同一个货架上的同一件商品的标价怎么办数据库领域的解法是锁。Oracle RAC这样的共享磁盘数据库在多个实例之间维护一套分布式锁机制全局缓存服务GCS / Global Cache Service任何数据块在同一时刻只能被一个实例以写模式持有其他实例如果要读要么等锁要么通过私有网络把数据块从一个实例的缓存里传过去。这里有个很巧的设计叫Cache Fusion缓存融合。它解决的问题是节点A刚把数据块读进内存节点B也想要这块数据按照传统思路B只能等A把数据刷回磁盘再读盘磁盘IO很慢。Cache Fusion允许B直接在私有网络上向A要这份缓存A把内存里的数据块发给BB就能直接使用不需要落盘。这个设计大大降低了共享存储架构下节点间数据交换的延迟。但代价也很明显一旦实例数量增多私有网络上传输的块数量会急剧膨胀节点间的缓存协调开销会盖过扩展带来的收益。这也是为什么共享磁盘数据库集群很少能无限制扩到几十个节点——它不是不能加计算节点而是加了之后大量时间都花在互相传数据、互相等锁上了。2.3 扩展逻辑加节点和加存储是两条完全不同的路两种架构面对容量和性能压力的扩展路径走向了完全相反的方向。Share Nothing的扩展叫横向扩展。存储不够了加一台服务器把一部分分片迁移过去计算不够了也一样加节点分担压力。容量和算力同时提升整体系统理论上可以无限扩展。当然现实没有那么美好分片再平衡期间数据迁移会占用网络和磁盘IO元数据协调服务也可能出现瓶颈但总体而言扩展能力是它的核心优势。Share Disk的扩展则更接近纵向扩展。存储不够用了通常不是靠增加计算节点而是升级存储阵列——换更大的磁盘、上全闪、增加二级缓存。计算能力不够了可以增加数据库实例数量但正如前面说的实例多了之后缓存融合和锁协调的开销会越来越大。另一个致命的瓶颈是存储阵列本身的性能上限以及光纤交换机、存储网络的整体带宽。所有节点共享一个后端存储大家再多也受到这一条公共水管的总容量限制。一句话概括Share Nothing是每一台机器都带着自己的粮仓打仗Share Disk是后方一个总粮仓前线有再多人也要排队领粮。2.4 一致性的两种难法一致性是分布式系统永恒的话题两种架构在这里体现的是两种完全不同的痛苦。Share Nothing因为数据天然分散跨分片事务必须引入分布式事务协议常见的比如两阶段提交2PC或者像TiKV这类系统使用的基于Raft的多副本同步加Percona事务模型。分布式事务的难处在于协调者需要让多个节点同时提交任何一个节点失败整个事务都要回滚而且把网络分区考虑进来之后问题会变得非常复杂。也正因如此很多NoSQL系统选择放弃分布式事务只提供单行或单分片级别的事务跨分片操作用最终一致性来兜底。Share Disk反而在事务层面比较轻松因为所有数据本质上放在同一个逻辑库里单个事务可以完全由数据库自身的锁管理器控制跟单机数据库没有太大区别这也是金融、电信这些对强一致要求极高的场景至今离不开这类架构的原因。它的难处在另一个方向当多个实例同时操作同一份共享数据时要维护跨越所有节点的全局缓存一致性同时要防止脑裂——网络抖动导致两个节点都以为自己是主节点各自去写共享盘把数据写坏。所以你看两种架构没有谁真正省心只是把复杂性写在了不同的地方。3. 落到真实系统上这些形态你都见过3.1 Hadoop、Cassandra这些无共享大军的共同点大数据生态里绝大多数组件都是Share Nothing的忠实信徒。HDFS把文件拆成128MB的块块的副本散落在不同DataNode的本地磁盘上NameNode只管元数据数据本身从始至终不经过它。Cassandra用一致性哈希把数据均匀地分布在节点环上每个节点持有部分数据分片和副本。Elasticsearch把索引拆成多个分片shard每个分片是一个独立的Lucene索引散落在数据节点上。这些系统的共同点非常明显都构建在普通x86服务器上数据以分片为基本管理单位节点之间通过Gossip协议或中心化元数据服务通信单点数据局部性极高。它们的扩展方式几乎一样——加节点然后把分片迁移过去让负载均衡。它们都默认节点是不可靠的所以设计了多副本机制一个节点挂了其他节点上的副本继续提供服务。但这套架构也带来了一个在很多场景下不太舒服的限制跨节点强事务能力普遍偏弱。Cassandra直到今天LWT轻量事务也只适合做单行级别的原子操作HDFS干脆不做随机写只适合追加写Elasticsearch的更新本质上是删除旧文档写入新文档。如果你拿这些系统去承载强事务型业务就像拿一把电锯去削铅笔——工具挺好就是不太顺手。3.2 Oracle RAC共享磁盘架构的老牌代表要说Share Disk最典型、也最成功的产品非Oracle RAC莫属。RAC的形态是多台服务器实例共享同一个物理存储存储通过ASM管理每个实例都运行完整的Oracle数据库代码都可以对外提供读写服务任何一个实例宕机其他实例继续工作应用几乎无感知。RAC能把这个事情做成靠的就是前面提到的Cache Fusion机制。每个数据块在全局资源目录GRD里有记录谁是当前持有者、谁是主节点系统清清楚楚。普通读请求优先访问本实例缓存命中不了再通过网络去其他实例要实在不行才读共享盘。这套机制设计精妙但也对底层网络提出了苛刻要求RAC集群的私有网络通常要万兆起步延迟越低越好因为缓存融合刷一次盘的代价比网络传输高好几个数量级。实际维护过RAC的人会告诉你这套系统是真金白银堆出来的。共享存储阵列、光纤交换机、多路径软件、集群软件、私网网卡绑定哪一环出了问题都会直接影响核心交易链路。所以它通常只出现在金融、电信、制造业核心ERP这类业务不能断、预算不是第一考虑因素的场景里。它的天花板也很明显常见生产环境跑4到8个实例已经算很多了再多实例缓存融合和全局锁的开销会让性能曲线明显走下坡。3.3 主从复制和共享存储双机常被混为一谈很多人会问MySQL主从复制是不是Share Disk还真不是。主从复制里每个节点保存着一份完整的数据副本主库写自己的数据文件从库通过binlog并行回放各自在各自本地磁盘上读写没有共享的存储。从架构分类上说它更接近Share Nothing的复制形态只是它复制的是完整数据不是分片而且每台机器都有冗余。更纯粹的Share Disk形态是什么呢是MySQL跑在共享存储上。两个MySQL实例同时挂载一块SAN LUN通过OCFS2/GFS2这样的集群文件系统来管理共享盘节点之间用分布式锁保证文件一致性。某个节点挂了另一节点接管共享存储上的数据继续服务。在真实生产里这种玩法比主从复制少见得多因为实现和运维复杂度一点不低。区分这两者有一个很简单的判断方法如果两个节点各自有自己的一套数据文件并且互相拷贝数据来同步那是复制模式属于无共享思路如果两个节点共享同一份物理数据文件靠锁和集群文件系统来避免写乱那才是真正的共享磁盘模式。3.4 存储形态变化之后架构界限也在模糊近几年云计算和对象存储改变了这个二分法的边界。像Snowflake、ClickHouse Cloud这类系统把数据放在了S3这类对象存储上多个计算集群共享同一个数据湖里的文件。从存储共享的角度看它有Share Disk的影子但计算节点之间不共享内存、不共享块级设备数据文件本身也是以不可变对象的形式存在每次写入产生新文件通过元数据层切换可见版本。这种新形态其实已经不完全等同于传统多个数据库实例挂同一块LUN的Share Disk它更像是把Share Nothing的计算独立性和对象存储的容量弹性结合起来。它们之间不会出现两个计算节点同时改写同一个数据块的问题因为对象是不可变的写即新建最后的可见性由一个强一致的元数据服务决定。这套逻辑绕开了传统共享磁盘最痛苦的锁和缓存一致性问题代价则是查询时数据本地性变差了——计算节点访问远端对象存储有一定网络开销所以要靠缓存、裁剪、预取来兜住性能。我提这个例子是想说架构不是一成不变的标签谈Share Nothing和Share Disk时重点不是谁属于谁而是要看清楚数据放在哪里、一致性怎么保证、扩展和容错分别牺牲了什么。4. 选型判断和个人踩坑记录4.1 动手之前先回答三个问题每次遇到团队问我们该用哪种架构我不会直接推荐某个产品而是让他们先回答三个问题。第一个问题数据未来会有多大增长是否可预测如果未来两三年还在单机磁盘容量的舒适区间比如一两TB以内完全没有必要为了可能扩展去背分片和分布式事务的包袱。反过来如果数据天生就是日志、埋点、订单流水这类无限增长型那从一开始就别指望共享存储来兜底直接按分片思路设计。第二个问题业务的强事务特征明显吗账务、库存、订单都是对强一致极其敏感的场景分片后跨分片事务每增加一次都会给开发和排查带来巨大成本。这类业务放在共享磁盘架构里一个逻辑库解决很多复杂性都被数据库自己消化了。而如果业务本身就是写完一篇文章能被读记录一条日志能被查询那最终一致性完全够用Share Nothing的高扩展优势会发挥得更自在。第三个问题你是要高可用还是要高扩展高可用靠的是多副本和切换能力两种架构都能做高扩展要的是容量和性能随时跟着业务走这个只有Share Nothing体系真正擅长。问清楚这个很多争论当场就能结束了。4.2 踩坑一分片键选择失误带来的热点事故我见过最典型的Share Nothing翻车事故是分片键选错了。有个业务把用户消息表按用户ID哈希成了64个分片每次查询都是查某个用户的消息列表从设计上看非常合理。但运营团队隔三差五搞活动热门活动账号在短时间内接收海量消息这些账号的哈希值恰好集中在两三个分片里于是那两三个节点的CPU直接被打满整个表的写入都开始堆积其他节点却很悠闲。用户侧的体感就是系统变慢甚至打不开。分片键的设计决定了整个系统能承受多极端的不均匀。只按业务主键均匀散列解决不了天然的热点实体问题。后来的整改方案是把热门活动账号拆成多个子账号分别落库同时在消息表增加了活动ID作为二级分片维度让流量再打散一层。这个教训让我记住一条做分片之前一定要统计清楚最高频访问的那几个Key它们的QPS会落在哪个节点上没有这步分析所谓均匀分片只是均匀在账面上而不是均匀在流量上。4.3 踩坑二共享存储的单点从来不止是一块磁盘有些人觉得既然用了Share Disk存储就是高枕无忧的因为他们花了高价上了双控制器SAN甚至做了双活。但共享存储架构里真正的单点远不止那块磁盘。有次一个系统故障根因出在光纤交换机上。一台交换机固件升级触发异常导致两个数据库节点到存储阵列之间的多路径链路同时被切断共享存储瞬间不可见整个集群直接脑裂。数据库层面做了完好的ASM镜像但底层PATH全断再好的设计也白搭。这让我意识到在Share Disk架构里存储网络和存储阵列本身是一等公民。扩容、升级、链路割接都必须纳入变更管理流程。很多团队的服务器运维功底很强但对存储组网、FC交换机端口的链路聚合、多路径软件的路径切换策略理解不够出了故障都不知道从哪排查。选这个架构运维团队必须能扛住存储网络数据库的三重技能叠加。4.4 踩坑三对分布式事务的成本预估太低还有一次踩坑是在Share Nothing系统上强行实现了跨分片事务。分片做好之后业务提了一个新需求一个操作要同时变更一个订单、更新用户账户余额、写一条积分流水这三个数据在不同的分片上。开发同学硬是手写了一个两阶段提交协调逻辑。结果第一版上线后经常出现某个分片超时导致整个事务回滚下游业务大量重试日志里全是死锁和锁等待。改了一轮又一轮最后才意识到问题不是代码写得不够好而是这个分布式事务的复杂度本来就不该由业务代码来扛。后来我们调整了数据模型把订单、余额、积分流水绑定在同一个用户聚合根下从设计上保证三个数据落在一个分片里程序的复杂度和故障率同时大幅下降。这个经验让我明白Share Nothing里真正需要下功夫的往往不是某个分布式事务中间件的配置而是根据业务边界来设计分片单元。把一起变的数据放到同一个分片里就能绕开大多数分布式事务。4.5 运维技能栈的隐性要求提到运维不少团队选型时只看架构优点不看运维负担。Share Nothing体系的日常运维围绕的是分片管理、数据再平衡、节点扩缩容、副本修复。你要看得懂分区路由规则、理解数据迁移对带宽的占用、能处理某个节点掉线后的集群自愈。这套技能栈偏向分布式系统和自动化运维日常打交道的是监控面板、Prometheus告警、配置管理工具。Share Disk体系的日常运维核心则是对存储和网络的理解。你要知道怎么规划LUN、怎么配多路径、怎么调整缓存融合参数、怎么监控光纤交换机端口光衰。很多DBA出身的人第一次接触SAN常常一头雾水因为这完全不在原来的技能树里。选型之前冷静评估一下自己团队的人擅长什么、短板在哪往往比看架构对比文章更重要。5. 决策参考按这几个维度去对号入座5.1 一张表看清两种架构的适用边界下面这张表是根据过往项目经验做的整理维度不一定覆盖所有场景但对大多数业务系统选型足够参考对比维度Share NothingShare Disk数据规模适合TB级到PB级可无限横向扩容几十TB以内尚可再往上受制于存储性能事务强度跨分片事务成本高尽量在单分片内闭环天然支持强事务适合交易类核心系统查询模式适合单分片定位查询和并行聚合多维查询需额外设计全局查询透明像用一台超大单机扩展方式加服务器容量与算力同步提升升级存储阵列或有限增加实例数量硬件成本普通服务器本地盘起步成本低高端SAN/分布式存储初始投入高一致性实现多副本协议或最终一致需要应用配合全局锁与缓存融合由数据库统一协调高可用设计分片多副本单点故障影响范围小存储是全局依赖需重点保障存储链路典型系统Hadoop、Cassandra、TiDB、ClickHouseOracle RAC、DB2 pureScale、共享盘双机运维要求分布式调度、分片管理、自动化运维存储组网、多路径、数据库集群调优对照这张表你会发现很多争论其实根本不算争论纯粹是拿错了尺子。拿海量日志场景去要求强事务回头骂分布式数据库不好用属于用错了工具还怪工具不趁手。5.2 什么时候果断选Share Nothing什么时候别硬分片如果业务属于以下情况可以不用太犹豫直接朝Share Nothing方向设计数据量增长几乎没有上限比如用户行为日志、IoT采样数据、系统监控指标业务能接受最终一致或者可以通过补偿机制处理短暂不一致查询可以按明确维度如用户ID、设备ID很方便地定位到分片团队有较强的分布式系统运维能力。反过来如果业务属于以下情况我建议你对Share Nothing保持克制核心交易链路里有大量复杂的多表关联和强事务约束数据量虽然不小但可以通过归档、冷热分离控制在合理范围内业务方对查询延迟极度敏感比如秒级响应以下团队没有任何分布式系统经验却在谈将来扩展。还有一个偏中性的建议如果业务还在早期团队又没完全想清楚未来怎么发展你可以先用Share Disk形态的单库设计来承载核心交易同时把日志、检索、分析类的旁路数据放到Share Nothing体系里。两套架构并用让数据流清晰分流而不是希望一套架构包打天下这是我经历过的项目里最务实的解法。6. 最后谈谈我个人的选型习惯说几条实际经验吧给还在纠结的团队一个参考。我个人的习惯是凡是涉及钱、库存这类强一致诉求高的业务或者数据量可以在很长一段时间内被单库扛住的场景我都不太愿意为了扩展性提前上复杂度。上线一个分片系统容易最难的是分片规则一旦定死后续数据迁移、跨分片查询改造、新老模型切换都是伤筋动骨的大手术。如果你现在只有几百GB的数据却去做几十个分片CPU和内存还没被数据吃满先被元数据协调、跨节点网络开销拖垮了得不偿失。反过来凡是日志、指标、分析类、数据量明显没有上限的场景我会上来就按Share Nothing设计而且会要求业务在设计表结构时就把天然的隔离维度带进主键。比如多租户系统用租户ID业务ID作为分片键让同一个租户的数据尽量落在同一个分片里应用层写聚合查询时大部分请求都能在单分片内完成从原理上绕过分布式事务。最后分享一个小技巧做技术选型答辩时只列优点没有说服力把每个方案未来三年的维护成本、迁移代价、痛点都摆到桌面上再让团队投票。很多架构之争争到最后其实不是技术问题而是团队愿意长期承担哪种复杂度。看清这一点比选对哪一个架构更要紧。
返回列表