ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

YashanDB架构解析:Oracle兼容与分布式迁移实战

YashanDB架构解析:Oracle兼容与分布式迁移实战 第一次认真去研究YashanDB的技术架构是因为一个客户的Oracle扩容报价把预算吓了一跳。那套系统跑了十来年日常负载不算夸张可商业数据库的许可和维保费用一年比一年贵领导层想看看有没有“既能平滑迁移又不让业务重写”的替代方案。那段时间我把市面上能接触到的几款自研数据库都过了一遍YashanDB给我的印象比较特别。这篇不是官方白皮书的复述而是我从架构评估者、DBA和团队实践者的角度把YashanDB技术架构拆成7个关键问题来聊。适合正在给存量系统找替换方案的架构师、要选型分布式数据库的DBA以及想搞明白自研数据库和MySQL/Oracle底层差在哪的开发同学。涉及原理的部分我会尽量大白话解释也会顺手写一些我踩过、或者看别人踩过的坑。1. 问题一YashanDB要解决的架构问题到底是什么1.1 从存量系统的真实痛点说起YashanDB并不是从零硬造的一款“概念数据库”它的定位很明确一款面向分布式场景的关系型数据库重点解决传统商业数据库和开源数据库在扩展性、易用性、成本之间的失衡。传统商业数据库功能强、性能稳但横向扩展基本靠堆更强的小型机或更高配置的存储扩容一台机器的成本可能就是小团队半年的预算。开源数据库虽然免费但真要自己做跨节点分布式事务、高可用切换和统一运维监控时往往得拼装一大堆周边组件架构复杂度和维护成本并不比商业软件低。这就给YashanDB留下了一个非常清晰的目标场景以存量Oracle为主的系统既想继续用熟悉的SQL开发习惯又想获得分布式扩展能力同时不希望把业务代码整体重写。YashanDB对外一直强调对Oracle生态和MySQL生态的兼容本质上就是在降低这类系统的迁移门槛。1.2 一张架构总览接入、计算、存储三层解耦从架构形态看YashanDB采用目前自研数据库里很主流的三层解耦接入层负责协议解析和会话管理客户端用标准SQL接口连进来SQL在这里完成身份校验、参数绑定后进入下一层计算层包含查询优化器、执行引擎和事务管理模块负责把一条SQL变成可以在分布式环境里执行的计划存储层才是真正落数据的地方数据按分片策略分布在多个存储节点上每个节点管理自己的副本和日志。这里有一个容易被忽略的关键点计算层最好做成无状态。只有计算节点不持有数据才能通过加节点来扩展SQL并发处理能力而不用迁移数据。数据节点则负责存储、复制和一部分计算下推。这种“计算弹性扩、存储按数据量扩”的模型和传统“买更大机器”的思路完全是两种玩法。还有一个细节是接入层不是简单把SQL文本转给下层就完事它要做协议级别的兼容包括连接方式、预处理语句、事务控制语句的语义。同样是“BEGIN”在Oracle兼容模式里可能代表显式事务块的开始在MySQL兼容模式里语义又不一样。这类差异只能在接入层用不同的会话上下文去化解。1.3 共享什么、不共享什么决定了架构上限YashanDB走的是“无共享”路线主要指存储侧不共享每个数据节点只访问本地数据节点之间通过网络交换数据和中间结果。好处是扩展性接近线性坏处是必须自己处理分布式事务、故障恢复和副本一致性问题这些复杂度不会消失只是从DBA身上转移到了数据库内核里。为了减少跨节点通信计算层会把能下推的算子尽量压到数据节点比如等值过滤、聚合前的分组统计。这像把一个项目拆给几个小组各小组先完成自己那一份并输出简报最后汇总的代价就小得多。理解这一点再看YashanDB宣传里的“高并发、低延迟”就明白它不是靠某种魔法而是靠减少不必要的数据搬运。在实际评估时我会把“每个数据节点的本地缓冲池命中率”和“跨节点数据重分布流量”作为两个核心指标前者能看出负载是否均衡后者能发现分片策略是否合理。2. 问题二存储计算分离具体怎么实现数据分片和弹性伸缩又靠什么2.1 Hash分片和Range分片怎么选把数据分布到多个节点第一个问题就是“数据放哪”。YashanDB这类分布式数据库通常支持两种主流分片策略Hash和Range。Hash分片把分片键做散列好处是数据分布均匀适合按主键做点查和等值更新坏处是范围查询可能要跨分片扫描。Range分片按分片键的连续区间切段对按时间扫描的日志类数据很友好但容易碰上“热点段”——比如最近写入的全是当天数据那一个区间会特别忙。我的建议很直接订单这类强事务场景优先考虑Hash时间序列类分析场景优先考虑Range。一个库里的不同表也完全可以采用不同策略别指望一种分片策略通吃所有表。分片键的选择更是要反复想清楚它必须是业务里最高频的查询条件否则路由优势根本发挥不出来。2.2 一条SQL如何被路由到正确的分片假设orders表按customer_id做了Hash分片你执行“WHERE customer_id123”优化器看到条件里带分片键就能算出数据在哪个节点只请求那一个节点。反过来如果查询条件是“WHERE statusPENDING”没有分片键优化器就只能广播到所有分片再做聚合。这条路由规则直接影响建表设计。我在很多项目里见过分布式数据库性能不好最后查下来根本不是数据库的问题而是开发团队把表结构照搬了单机时期的建法高频查询条件都没有落在分片键上导致大量查询在全分片广播。设计阶段的这个决策比后期调优重要得多。2.3 在线扩缩容数据再平衡如何不打断业务存储计算分离带来一个直接好处增加数据节点时不需要像传统分库分表那样手工搬运数据。新节点加入集群后管理节点会重新审视数据分布通过后台任务把部分分片复制到新节点并切换路由这个过程通常叫再平衡。再平衡期间业务还在写所以迁移必须以分片为单位做增量拷贝而不是整表锁住重灌。每完成一个分片的迁移旧分片就能释放。这里有两条实战经验扩容最好选业务低峰期手动触发同时要盯住集群内部网络带宽否则大量分片同时迁移会把带宽占满影响在线服务的P99延迟。另外多一句嘴“数据库同步软件”这个词在项目里经常被混淆。分布式数据库内部节点之间的分片复制和异构数据库之间的同步软件不是一回事。迁移项目里往往两类都要用先做全量逻辑导入再用同步链路追增量最后切换流量靠单一工具想解决全部问题是很容易翻车的。3. 问题三多副本强一致靠什么实现Raft、WAL和RPO0背后的逻辑3.1 异步复制和共识协议的差别很多传统数据库的高可用靠异步复制主库提交事务后把日志异步发给备库。这套方案简单但主库宕机时备库可能丢最后一小段数据。对核心交易系统来说“丢几秒”就是大事故。YashanDB这类面向金融级场景的分布式数据库普遍选择用共识协议来做强一致复制最常见的是Raft。每个数据分片保存多份副本写入必须先到LeaderLeader把日志发给Follower拿到多数派确认后才回复客户端“提交成功”。这样只要多数派副本还在任何单点故障都不会导致已提交数据丢失。3.2 WAL承上启下组提交摊薄网络成本这里必须提WAL预写日志。数据库在改数据页之前先把事务操作追加到日志崩溃恢复时靠重放日志把数据还原。在分布式场景里日志同时承担了副本复制的载体Leader发给Follower的那条日志就是写入的原子单元。RPO0是这套机制的直接结果任何已提交事务无论哪个节点宕机都能从多数派副本或日志里找回来。代价则是每次提交都要等至少一次网络往返写延迟天然比单机库高一点。为了缓解这个问题很多库会做组提交把一小段时间内的多个事务日志合并成一批批量发给多个副本确认把网络开销分摊到多笔事务上。3.3 跨分片事务两阶段提交的代价没法回避数据分散到多个分片后一个事务要改不同分片上的数据就得靠分布式事务协调。最常见的是两阶段提交先让所有参与者把改动写进日志并锁住资源然后统一决定提交或回滚。难点在于协调者故障和网络分区时如何恢复状态处理不好就会出现部分提交、部分回滚的不一致。我个人在业务设计上的原则是尽量把事务限制在单个分片内能用聚合根模型的别跨分片。跨分片事务越多锁等待、协调超时、回滚的概率就越大。分布式数据库不是让开发者随意放大事务而是把“该在本地完成的事留在本地”。4. 问题四Oracle兼容只是翻译语法吗SQL、PL/SQL和迁移的真实难度4.1 兼容性不是正则替换而是引擎语义很多开发同学对数据库的理解停留在单机环境下的增删改查以为Oracle兼容就是把函数名和关键字做一张映射表。真正做起来远不是这样。要让同一句SQL在Oracle和YashanDB上得到一致结果解析器、绑定器、优化器都要跟着改。举几个典型例子ROWNUM伪列、CONNECT BY层级查询、dual空表、NVL和TO_DATE的隐式类型转换。这些语法在标准SQL里可能压根不存在内核里要有对应的执行算子。难点还不在于单个语法点而在于它们组合起来之后语义仍然一致。所以我评估兼容性时从不停留在迁移报告里那句“语法通过率99%”而是把业务里最具代表性的一批SQL搬到测试环境逐条核对执行计划和结果集。4.2 PL/SQL运行态兼容才是重头戏比SQL更难的是存储过程、触发器、包这类PL/SQL对象。它们不只是语法还包含游标行为、异常处理、自治事务、DBMS_系列内置包等运行时语义。要让一个全新内核模拟出这套运行环境工作量比写几个执行算子大得多。我在实际测试里发现简单过程很容易通过但只要涉及动态SQL、批量绑定、异常堆栈传播几乎都要手工调整。做迁移验收不能只看“对象创建成功”要放到真实业务链路里跑观察触发器触发时机、包状态重置、异常分支是否符合预期。4.3 从“能跑”到“跑好”的三阶段把Oracle迁到YashanDB我习惯分三步。第一步是全量迁移用数据迁移工具和数据库同步软件把表结构、字段类型、约束、序列和数据搬过去这个过程的基本要求是字符集和字段精度不能缩水。第二步是增量追平和业务联调新旧系统并行通过日志或双写把增量数据同步过去直到两边数据一致。第三步才是切换流量切换前压测切换后留够回滚窗口。最容易被低估的是隐性依赖。比如某个报表依赖Oracle的优化器提示某个过程依赖DBMS_SCHEDULER迁过来不一定有同名同义对象。这些问题兼容性解决不了只能提前摸底、逐项改造。总之一句迁移项目的核心工作量不在数据库在业务代码里的Oracle私有用法。5. 问题五高并发TP场景下MVCC、数据库并发锁和死锁是怎么处理的5.1 读不阻塞写写不阻塞读的底层机制OLTP系统里最常见的冲突是读写并发。如果读请求拿住共享锁写请求就得排队系统吞吐量马上掉下来。现代关系型数据库普遍用MVCC多版本并发控制来解决这件事写事务修改数据时生成新版本读事务读取的是符合其隔离级别的旧版本读写各走各的版本。MVCC的代价不是完全没有。旧版本需要空间存放回收旧版本也要额外开销。如果集群里有几个跑几个小时的长查询Undo和系统表空间会持续增长。所以生产监控里一定要盯两件事长事务数量和Undo空间增长曲线别等磁盘告警了才去翻慢查询。5.2 行锁、锁语义差异和死锁检测事务并发写同一行时行锁绕不开。这里要注意YashanDB在Oracle兼容模式下锁语义会向Oracle看齐这和MySQL InnoDB的间隙锁、插入意向锁逻辑并不完全一样。跨库迁移的老司机都知道不能让团队的MySQL经验直接套到YashanDB上猜锁行为。死锁在分布式环境里更容易出现因为一个事务可能涉及多个分片的多把锁加锁顺序不一致就会互相等待。数据库通常靠等锁图周期性检测发现环之后回滚代价较小的事务。我有一条很土但有效的经验批量更新任务统一按业务主键排序后再提交从源头杜绝加锁顺序不一致导致的死锁。5.3 小事务优先时刻小心热点行把大事务拆小是业务侧改善并发最有效的手段。一条SQL更新1000行可能因为锁范围大把后面的写请求全堵住拆成每100行一批提交整体吞吐反而更高。这个经验放单机库也对放分布式库更明显毕竟大事务意味着更长时间的跨分片协调。另一个容易忽略的是热点行并发更新。秒杀里对库存那一行的更新不管架构多分布式最终所有请求都落在同一行上。解决思路要么是预扣库存、异步对账要么在应用层做本地缓冲后批量扣减指望数据库靠魔改锁粒度扛住热点多半要翻车。6. 问题六分析型负载靠什么提速列存、向量化执行和资源隔离6.1 行列混合存储为什么一套库里要放两种形态事务型查询是“按主键找几行”分析型查询是“扫上千行取两列做聚合”前者适合行存后者适合列存。从我看到的公开资料和产品能力看YashanDB在HTAP方向上下了不少功夫存储引擎需要同时支持两种物理形态同一份逻辑数据既按行组织也按列组织由优化器根据查询特点选访问路径。一套库里同时放两种形态写入成本和存储成本都会上升所以这不是无代价的“全能”。选型的判断标准很简单如果你的系统90%是TP只有零星报表就没必要为双形态付出双倍存储如果AP占比明显双形态的收益才真正体现出来。这里要顺便说一句最近总有人把列存和向量数据库混着聊。列存解决的是结构化数据的大表聚合问题向量数据库解决的是非结构化内容的相似度检索。如果你的业务是给文档、图片做embedding检索应该去选向量数据库而不是指望关系库的列存顺手把这件事干了。6.2 向量化执行和并行执行把CPU用起来分析查询耗CPU传统“一行一行取数计算”的模式对CPU很不友好。向量化执行把一批行打包成向量批量做表达式计算减少函数调用和分支判断配合SIMD指令一次能处理多个数据元素。多核并行执行再把这些任务摊到多个CPU核上大查询的优势立刻体现。我见过的实测里这类优化对大表扫描加聚合的提升最猛确实可以比行式执行快一个数量级。但前提是内核实现到位。压测时我会专门构造大表聚合SQL看执行计划里有没有出现真正的向量化算子和并行度而不是看厂商PPT里的“支持HTAP”标签。6.3 资源隔离别让一条烂SQL拖垮在线交易HTAP系统最大的敌人不是数据量大而是一条失控的分析SQL。分布式架构下可以通过把分析查询调度到指定节点组合来隔离也可以在引擎层做资源组、优先级、并发限制。生产上更彻底的做法是物理隔离单独部署一组分析节点只承担AP查询。如果你迫于成本把TP和AP放在同一批节点上那就要在晚高峰跑批时盯着TP的延迟曲线看隔离策略是不是真的有效。我的经验是这类问题的表现常常是“平时没事、跑批就抖”不主动压测根本发现不了。7. 问题七从架构图到生产环境部署、高可用与选型避坑7.1 几种部署形态怎么选架构讲得再明白部署时第一个问题还是“几个节点”。我的建议很直白开发环境单机可以生产环境至少三节点。有些人图省事只做一主一备但在基于多数派选举的强一致机制里两节点集群一旦网络分区谁都没法形成多数派会出现“谁也不敢继续写”的局面。三节点里挂一个剩下两个还能正常服务这是质变。部署形态最小节点容忍故障适合场景单机1节点故障即停机开发、测试一主一备2可切换但脑裂风险高成本极敏感的小业务三副本3容忍1个节点故障生产标配两地三中心5节点起容忍单机房故障金融、核心交易如果牵扯容灾还要考虑机房维度的布局常见的是两地三中心或三地两中心。规划时先把跨机房网络延迟和带宽算清楚否则每次事务提交都背上一次真实的远程往返性能预算会很难看。7.2 备份恢复和定期演练别让“高可用”背锅多副本再强也替代不了备份。副本解决的是硬件故障下的数据可用性备份解决的是误操作、逻辑删表、软件故障下的数据恢复。生产上至少要有全量备份加连续日志归档并且要定期做恢复演练。我见过最典型的翻车现场备机一直正常同步但半年没做过恢复演练真出事了发现备份文件损坏、日志归档有断点恢复窗口根本不够用。高可用和可恢复是两件事前者让业务不中断后者让数据找得回来缺一个都不行。7.3 选型前最后再问自己几个问题最后归纳一下我自己的选型判断。适合上YashanDB的场景有三个特征第一存量系统以Oracle为主对迁移成本非常敏感第二业务有明确的横向扩展需求单机数据库已经撑不住写入或并发第三对容灾和强一致要求很明确需要“提交成功就是真成功”的保障。不适合的场景也有团队全是MySQL经验业务代码又写满了MySQL特有的语法细节或者就是一个几百G的小库没什么分布式需求那直接用单机库更省心。分布式架构带来的运维复杂度是客观存在的选型不只是选一个数据库还要评估你的团队能不能驾驭这套监控、排障和容量管理。最后说点个人体会。我帮客户做POC的时候固定会做三件事看监控大盘能不能直观展示每分片负载和延迟故意杀掉一个节点观察切换时间和数据校验结果再放一批跨分片复杂SQL看它们的资源占用。YashanDB在这些测试里的表现让我觉得它的架构思路是站得住的。但在真实环境里架构对不对和好不好用从来是两码事搞清楚自己的水位再决定往不往这套架构上靠才是最稳妥的路。
返回列表