《MySQL冲冲冲》是由 IMG 社区和爱可生开源社区联合举办的一款专门针对 MySQL 技术话题的节目,以下是第五期的直播内容。
第一期回顾:现在是不是升级 MySQL 8.0 的好时机??
第二期回顾:MySQL DBA 职业生涯发展规划,35 岁到底会不会失业??
第三期回顾:MySQL 高可用 VS Oracle 高可用,MySQL 能否取代 Oracle 在金融行业的垄断局面??
第四期回顾:MySQL Group Replication 能否在生产环境中大规模使用??
第五期话题:分库分表 VS 中间件,哪个架构更好?
+
第五期文稿
开场白
欢迎大家来到《MySQL 冲冲冲》,本节目是由有态度的 IMG 社区和有深度的爱可生开源社区联合举办直播节目。爱可生是业界领先的 MySQL 服务提供商,大家对 MySQL 有任何的问题可以向他们咨询,他们提供的服务非常棒,我个人觉得爱可生也是一家非常坚持的公司,我认识他们是十多年前,一直在做 MySQL,那时候的 MySQL 份额真的非常小。大家感兴趣的话,去关注爱可生开源社区公众号,对本节目的大力支持,很多同学在前几期收到了我们的奖品。姜老师自己的 IMG 社区公众号:InsideMySQL,另外一个公众号“破产码农“,欢迎加入我们的社区。
话题时间
今天的话题,更有实战意义。分库分表 VS 中间件,你选择哪一个?我们今天还邀请了嘉宾,稍后连线。
对于本期节目的主题,我想说的是 MySQL 分布式架构,一种是基于业务层的分库分表,一种是基于中间件技术的分库分表。都是分库分表,简单说就是:由谁来完成路由访问的工作?
在讲主题之前,我们来讲一下分布式架构的概念。在我看来,分布式数据库和数据库没有什么太大的区别。它解决的是在互联网行业中,在线、海量数据存取的服务需求。举个例子,淘宝 11.11 活动。去年 11.11 一共成交了 12.92 亿笔订单,在电商领域是核心业务。算了一下,差不多每秒 15000 笔下单的操作。看起来还好并不高,但这是个平均值,我们要看峰值。11.11 前 1 小时肯定是最高峰的,根据我的经验,峰值少说应该是平均值的 10 倍,但 11.11 少说是 20 倍。也就是说,高峰期下单的 TPS(事务的数量)要达到 30 万,而且有所保留。每笔事务里有 5 - 6 次 SQL Query 操作,那 QPS 就可能达到 150 万。30 万 TPS 的话,当中又涉及到扣库存这样的热点操作。单台数据库,哪怕是 Oracle RAC 也扛不住。互联网公司像:美团、京东、淘宝等电商,在搞活动时数据量非常高,且有明显的热点。在这样的需求下,就要做分布式架构。银行也逐渐有面向互联网的业务,所以访问量也会比较高,这也是银行业要做分布式的原因,但相对互联网的量级还是小很多。
所谓分布式非常简单,数据库的分库分表就是把原来的一张表去拆分成很多张。比如说,对订单表进行拆分。拆到很多台服务器上面去,这样每台服务器都能一起承受负载。比如,需要承受 300 万的 QPS,我去把它拆到 100 台服务器上,每台 3 万 QPS,就能扛住了。
但引入分布式数据库架构,也会带来很多问题。比如说,分布式事务、聚合查询等等。就像上一期讲的 MGR,我们的业务要根据新的解决方案来进行适配,不能停留在单实例使用的思维,要用分布式的理念去看待。比如我们前面说的订单表,如果我要做分布式架构的话,我要进行水平拆分。我们要选择一个分区键进行拆分,再根据业务选择拆分算法。简单来说,分布式架构就是为了解决互联网业务中,高并发、海量数据的问题。
分库分表就是我们前面说的,把数据打散。打散之后我要去访问数据,就两种方式。一种是业务层根据规则访问数据,比如拿到条件 ID 后,根据分片规则计算出在哪一个分片去访问。业务层如果觉得麻烦,希望有一个代理层,透明的帮我解决这些问题,这就是中间件技术。业务不是直接访问数据库,由中间件解析 SQL,再访问数据。中间件就变成了传统数据库中的 SQL 执行器的感觉。很多功能就可以在中间件实现了,想做好、做稳定,还是非常非常有难度、有意义的。
那无论哪种方案都好,都要解决一个非常致命的问题:分布式事务。原来事务在单节点上很好做,要么 Commit 要么 Rollback。分布式事务就蛮难的,通常是用差异事务去做,把中间件当作一个协调器在业务层做分布式事务。这是一个难点,因为我们不可能所有的数据都是打散的,有些是不需要打散的,比如订单表可以拆分成很多份,但库存表就是一个全局表。每次下单,订单表 Insert,库存表 Update,但订单表和库存表肯定是不在一个实例上的,我要把它们做成一个事务的话,是一个难点,特别是针对互联网业务海量并发场景。
从我个人的感受来说,中间件是一个比较好的产品,但是业界成熟稳定的中间件又不多,这是一个主要的矛盾。在我看来 MySQL 的中间件主要就是一款 Mycat,DBLE 就是更好的 Mycat。给我们的选择很少,所以我觉得在中间件这块,MySQL 是存在“空白”的。① 互联网公司会使用 MySQL;② MySQL 会使用分布式。但推导不出 ③ 怎么去选择一个好的中间件产品。我们讲过 Router 是不支持分库分表的,这一块是缺失的。
如果你想在 MySQL 开发有所作为,我个人觉得中间件会比做 MySQL 内核更吃香一些。因为内核这件事情,已经没有多少空间了,官方能做的都做了。在中间件这一层是有需求的,而且需求是百花齐放的。每个公司需求都有差异,中间件直接拿来也不一定马上用得上,一定要业务 DBA 参与进来,深度整合才能用好。所以中间件层面的开发和使用,对个人成长是非常有价值的。相对单机来说,对业务方面你的价值会更大。
那我们今天邀请了资深的数据库中间件专家、DBLE 开发负责人、爱可生开源社区专家 —— 阎虎青先生,来给我们解答一些有关分布式数据库的问题。
DBLE 在中国的一些知名银行内部的部分核心业务上已经使用了。那我们来看一下,在一线的开发专家对分布式数据库是怎么理解的,对中间件产品又是怎么理解的?
阎虎青:
大家好,我是爱可生的阎虎青,江湖 ID 是蓝寅,主要负责 DBLE 的开发相关的工作。非常荣幸能够做客姜老师的直播节目,希望和大家一起学习分享 MySQL 相关的知识。
姜老师:
请问阎同学,怎么看待业务进行分库分表,或者说分库分表要考虑哪些问题?
阎虎青:
姜老师刚才已经说了很多了,我这边狗尾续貂一下。
分库分表前最重要的事就是扪心自问:你真的需要分库分表吗?很多时候大家觉得分库分表是个潮流,我也要搞一套。其实是看你最终要解决什么问题。有时是吞吐量,单机达到了性能瓶颈,可能那我考虑用分库分表解决。但往往还没到这一步,可能一个索引就解决问题了。或者把业务剥离开,做个垂直拆分就行了,并不需要真的分库分表。还有可能你需要的是一套 OLAP 的方案,而不是分库分表,用了分库分表也不一定能解决问题。
假设扪心自问之后,无愧于分库分表了,那接下来我能考虑到的就是三个问题:拆谁?怎么拆?拆完了业务怎么处理?
①拆谁?换句话说拆分列怎么选
我们要关心一下业务在做什么,引起性能或者吞吐量的问题症结在哪里。举个例子,如果电商数据我按照订单号来拆分,是不是仓储数据就会被选择性的遗忘了。比如,我的某个表的主键是自增序列,真正业务模型的关联关系是逻辑主键或者外键,那么我们拆分主键就不是很合适。再比如,如果你的业务是当天是热点数据,其他时间的是冷数据,那么可能按照时间列拆分就比较合理?
总的来说,需要找到业务涉及到的表的核心因素(字段等),用它拆分,可能会起到比较好的效果。
② 怎么拆?也就是拆分算法的问题
解决了拆谁的问题,然后就是怎么拆的问题,大的的原则是让你的 Query 尽量命中少的分片。比如说我拆了 100 个分片,一个 Query 下去广播 100 个分片,有一个网络读写的放大,性能是不会好的。像单条数据查询,用 Hash 拆分就能满足你的需求。假如你的业务是 批量增删改、范围查询、小范围的聚合,那么按照范围拆分可能比较合适的。
③ 拆完了业务怎么处理?
我先卖个关子,我们一会儿细聊。以上就是分库分表要考虑问题的一些问题。
姜老师:
虎青总结的非常非常好,更加的体系化。那接下来我想问:分库分表,业务层做比较好,还是中间件做比较好?
阎虎青:
刚才我也听了很多直播间小伙伴的选择。有一位同学说的比较好,运维就站中间件,开发就站业务层拆分。我是一个开发,但我是站中间件的,因为我是中间件的开发 ^_^
开个玩笑,实际的生产环境大多数是组织架构决定了技术方向。有时候选择不是依据哪种方式更优秀更好,而是看谁说得算。那现在我们抛开这个角度去看,可以从这几个方面看。
① 看你的业务 / 架构体量有多大?
如果是一个单一简单业务,你又是一个什么都负责的全栈开发,那可能业务层分库分表就对你来说会更简单些,引入中间件会让架构变得更复杂。当然稍微复杂一点儿的业务,有多个开发或者项目的话,业务层分库分表就会变得有点重。你们需要团队统一配合,统一开发,而且每个开发都需要知道拆分的具体细节。有一个理解不同可能就是在写 Bug。而中间件对业务侵入性比较小,业务需要变更的地方也少,甚至不需要变更。
② 你需要运维吗?
可能直播间 DBA 同学比较多,那问题是开发写完代码了,你需要运维么?如果你从业务层做了分库分表,那么运维同学怎么去知道你涉及到了哪些库表,这些库表的健康状况如何,出了问题如何诊断,是不是做高可用?即使你的开发承担了 DevOps,那么有一些运维工具和运维监控的观察窗口,其实也是会很有助益的。中间件这一层有个功能就是抽出来,为运维同学提供一个观察的机制和窗口,而不需要具体了解应用的代码。
③ 你想过下车吗?
设想一种场景,我们的硬件得到了极大的发展,或者单体数据库性能有了质的飞跃,原来需要分库分表的场景现在不需要了,像改回单体数据库,毕竟分布式会带来一些限制,比如分布式事务。那么用中间件的同学们把数据汇聚到一起,直接替换回单体数据库上就好了。分库分表写在业务层的话,对不起,需要重构一下业务了。关于下车这件事,采用中间件的方式,把应用和分库分表这件事解耦,用于减轻开发和运维各自的负担。
姜老师:
我也是非常非常认同你的观点。我以为你会从技术角度去谈,实际谈的比较发散,从组织架构的角度来谈这个事情,讲的非常非常好。除了技术,在其它细节上可以感受到今天的嘉宾感觉到就是在一线做过的。我们可以再发散的讨论另外一个问题,我知道蚂蚁金服,并没有用中间件,直接访问下面的数据库。那为什么他们没有用中间件呢?而是采用业务直接去连数据库分片,这个问题是怎么看的?
阎虎青:
虽然我不知道他们具体的场景是在做什么,但肯定有特殊的场景。如果非要想一个理由的话,那就是有些情况在业务层是可控的,而不是中间件做代理。比方说分布式事务,我看到阿里也开源了他们的分布式事务框架。中间件虽然帮你封装了一层分布式事务,但不一定是你想要的。特别是金融方面,我并不在意它的一致性要完全那么强,但我会在乎在事务中顺序的要求。这一点中间件就难以去理解,或帮助你去实现。如果是在业务层去做就完全可控。举个例子,我转账失败能接受延迟,我估计没有业务方能接受我转账了,对方先接收到了钱。需要在业务层把粒度控制得更细去解决。
姜老师:
说到了分布式事务,那我想知道:DBLE 是怎样解决分布式事务这个难题的?
阎虎青:
DBLE 在这方面做了一个封装,使用的 2PC 协议。具体是用 MySQL 5.7 以上 XA 事务来实现。XA 事务的实现的一个好处就是,第一阶段(prepare)不会丢,2PC 协议有一个问题就是第二阶段遇到网络等故障,要怎么去处理?DBLE 主要的精力放在了故障的处理,第二阶段的无限重视机制来防止参与者或者网络的故障。对于协调者的可能故障,采用 WAL 也就是日志先行的方式,以及日志的组提交技术来保证基本功能以及不错的性能。
分布式事务是一个比较大的话题,如果想使用这个功能,要仔细地评估能否承担数据有可能不能实现强一致性的风险。我们有些客户在 TPS 不高的情况下是正常使用的,但如果像电商的 TPS 很高的场景下是没办法实现的。
姜老师:
DBLE 是无状态的吧?那也就是我可以开很多个 DBLE 是不是会好一些?
阎虎青:
是的,无状态。开多个 DBLE 性能确实会更好。我们在给一些客户做 POC 测试时,有时会采用这种方式去把机器的性能榨干。
姜老师:
那最终一致性是个什么样的概念呢?
阎虎青:
在某段时间内,比如说一条跨多节点的 Update,可能会出现一个成功,另外一个 Commit 的时候网断了。那这一瞬间是一个成功,一个失败,但失败的会不停的重试提交,MySQL 5.7 XA 事务是一直在的。直到网络恢复或从库替换后,提交成功。这样就达到了最终一致性。
姜老师:
这个其实也没问题,因为这条记录也上锁了。比如转账钱还没扣,钱就转出去了,接下来一个变更操作也是执行不了的。对于分布式事务是一个很大问题,但在业务这一侧还能接受。
第四个问题:有哪些问题是分布式事务也无法解决的?
阎虎青:
这个问题能解答的点非常多,本人的认知也有限,只能举几个例子,有些问题是很难去解决的。
① 光速不能突破
这个问题会因为物理距离而放大,分布式架构多节点之间要做数据传输。一个 RTT 的时间最少也要 2 倍网线的距离除以光速,所以一旦异地部署,那么网络延迟问题就一定会发生。有同学问加了中间件单条 SQL 还慢了,因为多了一层中间件,网络延迟一定会变大,但收益是吞吐量的提高。
② 单机高性能自增序列
分布式架构中,如果想满足唯一性、递增性、单调性,就不得不引入一个单点来实现自增序列。一点引入单点,性能问题和高可用问题就又会如影随形的跟来。所以,分布式场景下,大家只能关注一部分,大多关注的是唯一性,至于递增性和单调性选择性忽略。包括 Twitter 这样的大公司提出的算法也没能满足后两个特性。
③ 高性能和高级别的事务的一致性
刚刚提到过这个话题,很难做到。如果要想保证事务一致性,也就是高一点儿的隔离级别,NewSQL 的做法基本上是全局时钟来做 MVCC,然后用 Percolator 之类的技术来增加 2PC 协议的可用性。中间件在这一点上可以做的事情比较少,因为存储依赖于成熟的单体数据库,很难去做 MVCC。就算是全局时钟的方式,性能也会受到一定程度的影响,所以需要其他地方的收益大于这里的成本,才是适合用分布式架构的。当然,我们也可以加一把大锁来实现序列化的隔离级别,但是这基本上是个玩具,由于性能问题,不可能在生产环境上使用。
姜老师:
非常认同虎青的观点,特别是第三点和 NewSQL 全局时钟的一个对比。后面几期有关于 NewSQL 的话题。
我再补充一个分布式架构解决不了的问题:热点问题。比如说,库存和热点商户。比如 PDD 的一个商户,余额也好,库存也好,就一条记录无法拆。分布式无法解决这个问题,因为关系型数据库要有事务这个概念,有锁的存在,就导致性能不是特别好。热点问题在互联网业务中又是广泛存在的,一旦有热点,在架构设计中就要考虑到。
那我们回到中间件的话题。你觉得有哪些好的中间件产品推荐?
阎虎青:
我当然是推荐 DBLE 了!首先它是开源的,大家都可以看到源代码,哪里有问题,哪里写得好,都看得到。第二个就是它经过了实践,有些银行业务在用了,你我都敢往里面存钱,说明是能撑得住的。从技术层面看,DBLE 在 Mycat 基础上修复了一些没人维护的 Bug,并且扩展了对复杂查询的支持,增强了分布式事务的支持,增加了很多方面运维的监控和运维命令。我曾经对 DBLE 和 Mycat 有过专门的对比。不久的将来,还会支持纯读写分离的模式,做一个多位一体的中间件。尽量对运维和 DBA 友好,能观测到我想要的信息,去发现分析问题解决问题。希望大家都去玩玩。
姜老师:
其实并不是因为是爱可生的产品我才推荐。我觉得业界用的比较多的还是基于 Mycat 衍生出来的产品。如果说要选开源的,有人持续运维的,有业界成熟核心案例的,实话是只有 DBLE。中间件产品大家的选择面并不是特别宽。
有同学问虎青对 shardingsphere 这个产品有什么看法?
阎虎青:
以我们今天的话题来说,它更像是在业务层的处理,而不是一个中间件的方式。其实就是对 sharding JDBC 的一个改写。在业务侧把分库分表帮你做掉了。很直观的一个判断就是,我怎么看你分到哪个库呢?其实是看不见的,我只能觉得你的业务是做对了。其实他们的长远规划是两个方向都有,产生两个产品,很难保证两个产品的视角一样。
姜老师:
我也觉得他最后还是要做 sharding proxy,因为 JDBC 还是对业务有侵入的。驱动升级业务跟着升级,代价是非常非常大的。如果未来 shardingsphere 做的好我也会推荐,判断依据就是上面我推荐 DBLE 的三个理由,目前离真正的企业级还有差距。
那我想问虎青的是,你现在如果不写 DBLE 了,重新设计一个 MySQL 中间件,你会怎么做。
阎虎青:
我考虑一下~ 首先是 Mycat 和 DBLE 存在解析过程有依赖其它组件,对于 SQL 的支持很难做到 100%,这样就不得不去业务侧改。如果有精力会把解析部分重构。
第二个,目前的优化策略主要是基于代数优化,比如写了一个很复杂的子查询,现在的方法是把子查询看是否能通过简单的代数变换,变成一个 Left Join 或者其它的方式,更适合分布式下发。如果重构我会希望在 MySQL 侧,把元数据维护到我的中间件中,这样我选择下发 SQL 还是保持子查询,就有了更好的依据,而不是纯粹的转换。
在一个就是 Java 语言的问题,对于这种前面业务、后面数据的链接没有太好的方案,现在 DBLE 也是继承 Mycat 用手写的方式处理,如果重构会看一下其他语言,对于这部分功能的处理有没有更好的方案。很多问题到最后都是回到网络 IO 上,这是一个死结,目前解决不了。
姜老师:
非常认同特别是后两条在中间件设计上的问题。前面有同学问到以下几个问题:
- ProxySQL 和 DBLE 的区别?
- DBLE 有哪些监控性能项?
- DBLE 的网站?
阎虎青:
- ProxySQL 不是很了解,不适合回答~
- DBLE 监控性能项多到很难列举出来,官方文档有专门的一章讲这个。如何查看中间件内部暴漏的问题。
- opensource.actionsky.com
姜老师:
最后一个问题:DRDS 支持了全局二级索引,DBLE 会考虑么?
阎虎青:
从我的角度看,暂时不会支持。引入二级索引,那我就要把索引维护在中间件层,维护索引的成本非常高,DBLE 也会变得很重。DBLE 后面带 MySQL,MySQL 就可以自己用二级索引。既然我们已经采用了分库分表,就应该用分布式的思维去解决问题,而不是把中间件想象成一个单体数据库。
姜老师:
非常感谢虎青的连线,今天讲的非常好。本次和嘉宾的问题,只是给了一个框架。问答过程中,明显感觉到虎青在中间件产品方面有沉淀,也很高兴爱可生开源社区有这样的人才。
下次节目我们将讨论业界这些中间件产品,以及如何进行选择。未完待续……
+
今晚预告
第六期话题:
MySQL 中间件的选择,ProxySQL、Spider、MyCAT、DBLE 怎么选?
同时,爱可生开源社区也会赞助本次节目的分享,每场直播都有礼物赠送。
相关链接:
1. 深度分析 | MyCat与DBLE的对比性能调优
2. DBLE用户故事 | 工商银行MySQL数据库架构解密
3. DBLE 公开课
直播信息