分库分表vsNewSQL数据库
最近与同⾏科技交流,经常被问到分库分表与分布式数据库如何选择,⽹上也有很多关于中间件+传统关系数据库(分库分表)与NewSQL分布式数据库的⽂章,但有些观点与判断是我觉得是偏激的,脱离环境去评价⽅案好坏其实有失公允。
本⽂通过对两种模式关键特性实现原理对⽐,希望可以尽可能客观、中⽴的阐明各⾃真实的优缺点以及适⽤场景。
NewSQL数据库先进在哪⼉?
⾸先关于“中间件+关系数据库分库分表”算不算NewSQL分布式数据库问题,国外有篇论⽂pavlo-newsql-sigmodrec,如果根据该⽂中的分类,Spanner、TiDB、OB算是第⼀种新架构型,Sharding-Sphere、Mycat、DRDS等中间件⽅案算是第⼆种(⽂中还有第三种云数据库,本⽂暂不详细介绍)。
基于中间件(包括SDK和Proxy两种形式)+传统关系数据库(分库分表)模式是不是分布式架构?我觉得是的,因为存储确实也分布式了,也能实现横向扩展。但是不是"伪"分布式数据库?从架构先进性来看,这么说也有⼀定道理。"伪"主要体现在中间件层与底层DB重复的SQL解析与执⾏计划⽣成、存储引擎基于B+Tree等,这在分布式数据库架构中实际上冗余低效的。为了避免引起真伪分布式数据库的⼝⽔战,本⽂中NewSQL数据库特指这种新架构NewSQL数据库。
NewSQL数据库相⽐中间件+分库分表的先进在哪⼉?画⼀个简单的架构对⽐图:
1. 传统数据库⾯向磁盘设计,基于内存的存储管理及并发控制,不如NewSQL数据库那般⾼效利⽤。
2. 中间件模式SQL解析、执⾏计划优化等在中间件与数据库中重复⼯作,效率相⽐较低;
3. NewSQL数据库的分布式事务相⽐于XA进⾏了优化,性能更⾼;
mysql下载的vs库放在那个文件里4. 新架构NewSQL数据库存储设计即为基于paxos(或Raft)协议的多副本,相⽐于传统数据库主从模式(半同步转异步后也存在丢数问题),
在实现了真正的⾼可⽤、⾼可靠(RTO<30s,RPO=0)
5. NewSQL数据库天⽣⽀持数据分⽚,数据的迁移、扩容都是⾃动化的,⼤⼤减轻了DBA的⼯作,同时对应⽤透明,⽆需在SQL指定分库分表
键。
这些⼤多也是NewSQL数据库产品主要宣传的点,不过这些看起来很美好的功能是否真的如此?接下来针对以上⼏点分别阐述下的我的理解。分布式事务
这是把双刃剑。
CAP限制
想想更早些出现的NoSQL数据库为何不⽀持分布式事务(最新版的mongoDB等也开始⽀持了),是缺乏理论与实践⽀撑吗?并不是,原因是CAP定理依然是分布式数据库头上的颈箍咒,在保证强⼀致的同时必然会牺牲可⽤性A或分区容忍性P。为什么⼤部分NoSQL不提供分布式事务?
那么NewSQL数据库突破CAP定理限制了吗?并没有。NewSQL数据库的⿐主Google Spanner(⽬前绝⼤部分分布式数据库都是按照Spanner 架构设计的)提供了⼀致性和⼤于5个9的可⽤性,宣称是⼀个“实际上是CA”的,其真正的含义是系统处于 CA 状态的概率⾮常⾼,由于⽹络分区导致的服务停⽤的概率⾮常⼩,究其真正原因是其打造私有全球⽹保证了不会出现⽹络中断引发的⽹络分区,另外就是其⾼效的运维队伍,这也是cloud spanner的卖点。详细可见CAP提出者Eric Brewer写的《Spanner, TrueTime 和CAP理论》。
推荐⼀篇关于分布式系统有趣的⽂章,站在巨⼈的分布式肩膀上,其中提到:分布式系统中,您可以知道⼯作在哪⾥,或者您可以知道⼯作何时完成,但您⽆法同时了解两者;两阶段协议本质上是反可⽤性协议。
完备性:
两阶段提交协议是否严格⽀持ACID,各种异常场景是不是都可以覆盖?
2PC在commit阶段发送异常,其实跟最⼤努⼒⼀阶段提交类似也会有部分可见问题,严格讲⼀段时间内并不能保证A原⼦性和C⼀致性(待故障恢复后recovery机制可以保证最终的A和C)。完备的分布式事务⽀持并不是⼀件简单的事情,需要可以应对⽹络以及各种硬件包括⽹卡、磁盘、CPU、内存、电源等各类异常,通过严格的测试。之前跟某友商交流,他们甚⾄说⽬前已知的NewSQL在分布式事务
⽀持上都是不完整的,他们都有案例跑不过,圈内⼈⼠这么笃定,也说明了分布式事务的⽀持完整程度其实是层次不齐的。
但分布式事务⼜是这些NewSQL数据库的⼀个⾮常重要的底层机制,跨资源的DML、DDL等都依赖其实现,如果这块的性能、完备性打折扣,上层跨分⽚SQL执⾏的正确性会受到很⼤影响。
性能
传统关系数据库也⽀持分布式事务XA,但为何很少有⾼并发场景下⽤呢? 因为XA的基础两阶段提交协议存在⽹络开销⼤,阻塞时间长、死锁等问题,这也导致了其实际上很少⼤规模⽤在基于传统关系数据库的OLTP系统中。
NewSQL数据库的分布式事务实现也仍然多基于两阶段提交协议,例如google percolator分布式事务模型,
采⽤原⼦钟+MVCC+ Snapshot Isolation(SI),这种⽅式通过TSO(Timestamp Oracle)保证了全局⼀致性,通过MVCC避免了锁,另外通过primary lock和secondary lock将提交的⼀部分转为异步,相⽐XA确实提⾼了分布式事务的性能。
SI是乐观锁,在热点数据场景,可能会⼤量的提交失败。另外SI的隔离级别与RR并⾮完全相同,它不
会有幻想读,但会有写倾斜。
但不管如何优化,相⽐于1PC,2PC多出来的GID获取、⽹络开销、prepare⽇志持久化还是会带来很⼤的性能损失,尤其是跨节点的数量⽐较多时会更加显著,例如在银⾏场景做个批量扣款,⼀个⽂件可能上W个账户,这样的场景⽆论怎么做还是吞吐都不会很⾼。
Spanner给出的分布式事务测试数据
虽然NewSQL分布式数据库产品都宣传完备⽀持分布式事务,但这并不是说应⽤可以完全不⽤关⼼数据拆分,这些数据库的最佳实践中仍然会写到,应⽤的⼤部分场景尽可能避免分布式事务。
既然强⼀致事务付出的性能代价太⼤,我们可以反思下是否真的需要这种强⼀致的分布式事务?尤其是在做微服务拆分后,很多系统也不太可能放在⼀个统⼀的数据库中。尝试将⼀致性要求弱化,便是柔性事务,放弃ACID(Atomicity,Consistency, Isolation, Durability),转投
BASE(Basically Available,Soft state,Eventually consistent),例如Saga、TCC、可靠消息保证最终⼀
致等模型,对于⼤规模⾼并发OLTP场景,我个⼈更建议使⽤柔性事务⽽⾮强⼀致的分布式事务。关于柔性事务,笔者之前也写过⼀个技术组件,最近⼏年也涌现出了⼀些新的模型与框架(例如阿⾥刚开源的Fescar),限于篇幅不再赘述,有空再单独写篇⽂章。
HA与异地多活
主从模式并不是最优的⽅式,就算是半同步复制,在极端情况下(半同步转异步)也存在丢数问题,⽬前业界公认更好的⽅案是基于paxos分布式⼀致性协议或者其它类paxos如raft⽅式,Google Spanner、TiDB、cockcoachDB、OB都采⽤了这种⽅式,基于Paxos协议的多副本存储,遵循过半写原则,⽀持⾃动选主,解决了数据的⾼可靠,缩短了failover时间,提⾼了可⽤性,特别是减少了运维的⼯作量,这种⽅案技术上已经很成熟,也是NewSQL数据库底层的标配。
当然这种⽅式其实也可以⽤在传统关系数据库,阿⾥、团队等也有将MySQL存储改造⽀持paxos多副本的,MySQL也推出了官⽅版MySQL Group Cluster,预计不远的未来主从模式可能就成为历史了。
分布式⼀致性算法本⾝并不难,但具体在⼯程实践时,需要考虑很多异常并做很多优化,实现⼀个⽣产级可靠成熟的⼀致性协议并不容易。例如实际使⽤时必须转化实现为multi-paxos或multi-raft,需要通过batch、异步等⽅式减少⽹络、磁盘IO等开销。
需要注意的是很多NewSQL数据库⼚商宣传基于paxos或raft协议可以实现【异地多活】,这个实际上是有前提的,那就是异地之间⽹络延迟不能太⾼。以银⾏“两地三中⼼”为例,异地之间多相隔数千⾥,延时达到数⼗毫秒,如果要多活,那便需异地副本也参与数据库⽇志过半确认,这样⾼的延时⼏乎没有OLTP系统可以接受的。
数据库层⾯做异地多活是个美好的愿景,但距离导致的延时⽬前并没有好的⽅案。之前跟蚂蚁团队交流,蚂蚁异地多活的⽅案是在应⽤层通过MQ 同步双写交易信息,异地DC将交易信息保存在分布式缓存中,⼀旦发⽣异地切换,数据库同步中间件会告之数据延迟时间,应⽤从缓存中读取交易信息,将这段时间内涉及到的业务对象例如⽤户、账户进⾏⿊名单管理,等数据同步追上之后再将这些业务对象从⿊名单中剔除。由于双写的不是所有数据库操作⽇志⽽只是交易信息,数据延迟只影响⼀段时间内数据,这是⽬前我觉得⽐较靠谱的异地度多活⽅案。
另外有些系统进⾏了单元化改造,这在paxos选主时也要结合考虑进去,这也是⽬前很多NewSQL数据库⽋缺的功能。
Scale横向扩展与分⽚机制
paxos算法解决了⾼可⽤、⾼可靠问题,并没有解决Scale横向扩展的问题,所以分⽚是必须⽀持的。NewSQL数据库都是天⽣内置分⽚机制的,⽽且会根据每个分⽚的数据负载(磁盘使⽤率、写⼊速度等)
⾃动识别热点,然后进⾏分⽚的分裂、数据迁移、合并,这些过程应⽤是⽆感知的,这省去了DBA的很多运维⼯作量。以TiDB为例,它将数据切成region,如果region到64M时,数据⾃动进⾏迁移。
分库分表模式下需要应⽤设计之初就要明确各表的拆分键、拆分⽅式(range、取模、⼀致性哈希或者⾃定义路由表)、路由规则、拆分库表数量、扩容⽅式等。相⽐NewSQL数据库,这种模式给应⽤带来了很⼤侵⼊和复杂度,这对⼤多数系统来说也是⼀⼤挑战。
分库分表模式也能做到在线扩容,基本思路是通过异步复制先追加数据,然后设置只读完成路由切换,最后放开写操作,当然这些需要中间件与数据库端配合⼀起才能完成。
这⾥有个问题是NewSQL数据库统⼀的内置分⽚策略(例如tidb基于range)可能并不是最⾼效的,因为与领域模型中的划分要素并不⼀致,这导致的后果是很多交易会产⽣分布式事务。举个例⼦,银⾏核⼼业务系统是以客户为维度,也就是说客户表、该客户的账户表、流⽔表在绝⼤部分场景下是⼀起写的,但如果按照各表主键range进⾏分⽚,这个交易并不能在⼀个分⽚上完成,这在⾼频OLTP系统中会带来性能问题。
分布式SQL⽀持
常见的单分⽚SQL,这两者都能很好⽀持。NewSQL数据库由于定位与⽬标是⼀个通⽤的数据库,所
以⽀持的SQL会更完整,包括跨分⽚的join、聚合等复杂SQL。中间件模式多⾯向应⽤需求设计,不过⼤部分也⽀持带拆分键SQL、库表遍历、单库join、聚合、排序、分页等。但对跨库的join以及聚合⽀持就不够了。
NewSQL数据库⼀般并不⽀持存储过程、视图、外键等功能,⽽中间件模式底层就是传统关系数据库,这些功能如果只是涉及单库是⽐较容易⽀持的。
NewSQL数据库往往选择兼容MySQL或者PostgreSQL协议,所以SQL⽀持仅局限于这两种,中间件例如驱动模式往往只需做简单的SQL解析、计算路由、SQL重写,所以可以⽀持更多种类的数据库SQL。
SQL⽀持的差异主要在于分布式SQL执⾏计划⽣成器,由于NewSQL数据库具有底层数据的分布、统计信息,因此可以做CBO,⽣成的执⾏计划效率更⾼,⽽中间件模式下没有这些信息,往往只能基于规则RBO(Rule-Based-Opimization),这也是为什么中间件模式⼀般并不⽀持跨库join,因为实现了效率也往往并不⾼,还不如交给应⽤去做。
这⾥也可以看出中间件+分库分表模式的架构风格体现出的是⼀种妥协、平衡,它是⼀个⾯向应⽤型的设计;⽽NewSQL 数据库则要求更⾼、“⼤包⼤揽”,它是⼀个通⽤底层技术软件,因此后者的复杂度、技术门槛也⾼很多。
存储引擎
传统关系数据库的存储引擎设计都是⾯向磁盘的,⼤多都基于B+树。B+树通过降低树的⾼度减少随机读、进⽽减少磁盘寻道次数,提⾼读的性能,但⼤量的随机写会导致树的分裂,从⽽带来随机写,导致写性能下降。NewSQL的底层存储引擎则多采⽤LSM,相⽐B+树LSM将对磁盘的随机写变成顺序写,⼤⼤提⾼了写的性能。不过LSM的的读由于需要合并数据性能⽐B+树差,⼀般来说LSM更适合应在写⼤于读的场景。当然这只是单纯数据结构⾓度的对⽐,在数据库实际实现时还会通过SSD、缓冲、bloom filter等⽅式优化读写性能,所以读性能基本不会下降太多。NewSQL数据由于多副本、分布式事务等开销,相⽐单机关系数据库SQL的响应时间并不占优,但由于集的弹性扩展,整体QPS提升还是很明显的,这也是NewSQL数据库⼚商说分布式数据库更看重的是吞吐,⽽不是单笔SQL响应时间的原因。
成熟度与⽣态
分布式数据库是个新型通⽤底层软件,准确的衡量与评价需要⼀个多维度的测试模型,需包括发展现状、使⽤情况、社区⽣态、监控运维、周边配套⼯具、功能满⾜度、DBA⼈才、SQL兼容性、性能测试、⾼可⽤测试、在线扩容、分布式事务、隔离级别、在线DDL等等,虽然NewSQL数据库发展经过了⼀定时间检验,但多集中在互联⽹以及传统企业⾮核⼼交易系统中,⽬前还处于快速迭代、规模使⽤不断优化完善的阶段。
相⽐⽽⾔,传统关系数据库则经过了多年的发展,通过完整的评测,在成熟度、功能、性能、周边⽣态、风险把控、相关⼈才积累等多⽅⾯都具有明显优势,同时对已建系统的兼容性也更好。
对于互联⽹公司,数据量的增长压⼒以及追求新技术的基因会更倾向于尝试NewSQL数据库,不⽤再考虑库表拆分、应⽤改造、扩容、事务⼀致性等问题怎么看都是⾮常吸引⼈的⽅案。
对于传统企业例如银⾏这种风险意识较⾼的⾏业来说,NewSQL数据库则可能在未来⼀段时间内仍处于探索、审慎试点的阶段。基于中间件+分库分表模式架构简单,技术门槛更低,虽然没有NewSQL数据库功能全⾯,但⼤部分场景最核⼼的诉求也就是拆分后SQL的正确路由,⽽此功能中间件模式应对还是绰绰有余的,可以说在⼤多数OLTP场景是够⽤的。
限于篇幅,其它特性例如在线DDL、数据迁移、运维⼯具等特性就不在本⽂展开对⽐。
总结
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论