做者:伴鱼技术团队程序员
技术选型是由技术方向和业务场景 trade-off 决定的,脱离业务场景来讲技术选型是没有任何意义的,因此本文只是阐述了伴鱼技术团队数据库选型的过程,这并非 MySQL、MongoDB 和 TiDB 之间直接的比较,只能说明 TiDB 更适合伴鱼的业务场景和技术规划,另外因为 TiDB 是很是新的数据库技术,因此这也能体现出伴鱼技术团队对新技术的态度、技术后发优点的理解、成本与效率的衡权和技术生态与红利的思考。数据库
伴鱼是 2015 年成立的,那个时候 NoSQL 还如日中天,关系型数据库为了应付海量的数据只能业务侵入式的分库分表,虽然 Google 在 2012 年发布了 NewSQL 数据库 Spanner 的论文,可是工业界尚未一款可使用的 NewSQL 数据库,综合当时的各类状况,伴鱼选择的是 MongoDB。后端
不过,在 2015 年到 2017 年之间,对于伴鱼来讲 MongoDB 确实是一个上佳之选,主要有如下几个方面的缘由:缓存
整体来讲,在伴鱼产品的探索期,为了效率牺牲一点数据约束性和事务能力是值得的,可是 2017 年末伴鱼产品方向比较明确后,业务场景从探索期转变到快速发展期,对数据库的需求从效率优先转变为效率、事务能力与生态并重:安全
到产品快速发展期,因为业务场景对数据库的需求已经发生了很大的改变,因此在这个时候,伴鱼技术团队开始谨慎思考数据库从新选型的问题,咱们理想型的数据库是这样的:微信
基于上面这些需求,咱们开始了数据库的从新选型之路。架构
早在 2015 年的时候我就很是关注分布式数据库,当时已经经历太高并发高 QPS 的场景,利用分布式架构解决无状态高并发高 QPS 场景是不复杂的,可是分布式存储因为涉及到一致性问题是很是有挑战的,若是还想支持 ACID 事务那就更难了,因此当时就对分布式数据库技术特别感兴趣,开始关注 OceanBase 而且收集和研究相关的理论和架构文档。并发
后来同事推荐说有个叫 TiDB 的数据库,目前有些公司也在用了,反馈也不错,因此咱们决定调研一下。TiDB 官网的文档作的很是友好,不管是理论仍是架构的文章都很是齐全,几乎一口气就把全部的文章都看了一遍(当时文章比如今要少),完备的理论支持、优雅的架构设计、与 Google Spanner 一脉相承的设计思路让咱们对 TiDB 的前景很是看好,而且功能上彻底知足咱们的要求,因此当时就决定长期关注 TiDB,而且准备进行初步验证。运维
经过调研咱们发现,TiDB 是经过 raft 协议来保证多副本数据的一致性( ACID 中的 C ),经过 2PC 协议来保证事务的原子性( ACID 的 A ),经过乐观锁加 MVCC 来实现可重复读的事务隔离级别( ACID 中 I ),这意味着 TiDB 每一次事务的成本是比 MySQL 要高不少的,特别是有事务冲突的时候(乐观锁的缘由),因此性能是须要验证的关键点。异步
当时伴鱼全部的业务都部署在阿里云上(如今有自建机房),就直接在阿里云上面按 TiDB 的配置要求购买了机器,当时安装的是 TiDB 1.x 的版本。由于 TiDB 官网已经有 Sysbench 的压力测试数据,这个性能数据是符合咱们需求的,因此决定对咱们的业务场景进行一次彻底模拟的长期测试:伴鱼 IM 的并发比较高,而且采用写扩散的设计,对数据库的要求会比较高,因此适合进行验证。经过对 IM 业务的 inbox 表进行双写,业务同步写 MongoDB 和异步写 TiDB,业务读只读 MongoDB,这样若是 TiDB 有问题也不会影响线上业务。
在低峰期对 IM 业务开启双写后,TiDB 监控的 999 线和 99 线还知足要求,可是全部 TiKV 节点的 io 使用率一直在 90% 附近波动,这个若是到高峰期是绝对会有问题的,经过重读 TiKV 的配置,在修改配置项 sync-log = false 后,TiKV 的 io 使用率维持在 5% 如下,当天的高峰期也一切正常,没有出现问题。
在这以后,咱们对 IM 的双写观察 2-3 个月的时间,在确认一切正常后,再将同步读写都修改成 TiDB 而且异步写 MongoDB,一切正常而且持续观察。
sync-log 配置是控制 TiKV 数据多副本进行 raft 协议同步的时候,若是 sync-log=false,则内存中处理完成就返回 ack,对于 3 副原本说,单节点故障是不会丢失数据的,同一个 raft 集的 2 个副本同时故障可能会出现丢数据的状况,这个问题除了金融等对数据安全性要求很是高的场景外,其余的业务场景是能够接受的,而且 MySQL 等其余数据库的集群方案在 master 节点故障的时候问题更大。
在前面初步验证 TiDB 的过程当中,一个看似很严重的问题可是调整一个配置就能够解决,这让咱们发现了咱们对 TiDB 的理解和控制力还不够,在对每个配置都进行理解研究外,还有一些咱们很是关心的问题但没有官方答案。若是对这些问题没有官方答案,那么咱们直接使用 TiDB 就是有很大风险的,因此咱们决定和 TiDB 团队进行一次深度的交流。
咱们当时很是关心的问题列表为:
收集了大概 20 多个问题,得益于伴鱼和 TiDB 都在北京,离得还很是近,在线上联系上而且约好时间后,和 TiDB 进行了第一次深度的交流。
大概是 2018 年上半年的一天,我和 TiDB 的 3-4 个同事聊了一整个上午,基本都是我将收集到的问题一个个抛出来,你们一块儿讨论。整个交流过程解答了不少咱们关心的问题,也了解到当前业界对 TiDB 的使用状况,大大加强了咱们对 TiDB 的信心,对于数据库的选型来讲,这是很是关键的事情。
通过对 TiDB 的调研、试用和深刻交流后,在传统的关系型数据库 MySQL 和 NewSQL 数据库 TiDB 之间,咱们须要作出本身的选择了,这不只仅是两个数据库之间的选择,这其实也体现了伴鱼对新技术的态度、技术后发优点的理解、成本与效率的衡权和技术生态与红利的思考。
伴鱼对新技术的态度是很是积极的,若是业务场景须要的新技术咱们都会去了解它、研究它和掌握它,咱们相信咱们对新技术趋势的判断能力和掌控能力,因此在 TiDB 和 MySQL 的选型的过程当中,MySQL 确实是很是稳的选择,而且对咱们的需求目前都有现成的解决方案,好比高可用,好比水平扩展能力,只不过不是很是优雅的解决方案,可是 TiDB 不管是理论层面和架构层面都比 MySQL 高出一个时代(MySQL 是面向单机数据库设计的,是这个领域很是优秀的数据库,只是如今伴鱼想要解决的是单机没法存储的海量数据场景,在这个维度上比较确实 TiDB 更好一些,可是这并非 MySQL 的问题,是由于它们的设计目标不一样而已),可是稳定性和成熟度会比 MySQL 要差一些,这个时候,咱们选择相信咱们对 NewSQL 技术方向的判断力和掌控力,相信 TiDB 的进化能力,相信时间站在咱们这边,让子弹再飞一会。
伴鱼在以前用的数据库是 MongoDB,MySQL 和 TiDB 都没有用过,若是咱们判断 TiDB 更面向将来的数据库,那么咱们是先从 MySQL 开始,走一遍 MySQL 的道路,在后面可预见的将来再迁移到 TiDB 上来;仍是直接深刻研究和掌握 TiDB,直接 All in TiDB?
初创公司在技术沉淀和积累上是远远不及一些成熟公司的,这些沉淀和积累就是成熟公司在技术上的先发优点,当技术没有出现变革的时候咱们没有选择,可是当技术正出现重大变革的时候,若是咱们还作一样的技术选型,那么也须要花一样的时间和成本才能达到成熟公司的水平,而后等你们都开始迁移到新的技术上的时候,这些技术沉淀和积累就可能会变成技术债务。
因此初创公司应该去预判技术趋势,选择面向将来的技术,在技术上弯道超车,避免本身的技术债务,这个是伴鱼技术团队对技术后发优点的理解。
成本和效率是技术选型绕不过的关键点,对于数据库来讲更是如此,由于数据库须要的机器等资源成本会占总资源成本的很大一部分,因此伴鱼技术团队在 TiDB 和 MySQL 作选择的时候,对成本与效率进行了深度的评估。
Unix 哲学是通过时间和实践的锤炼设计原则,不少时候也是伴鱼技术团队的实践原则,好比 Rule of Economy :「宁花机器一分,不花程序员一秒」。在技术选型上,咱们是老是指望基础软件作更多的事情,业务研发作更少的事情,若是业务研发须要在业务层去作本来基础软件应该作好的事情,那其实就是基础软件的抽象泄漏了。若是基础软件抽象泄漏,必然会致使业务层重复去解决这个问题,这个实际上是很是大的隐性成本。
MySQL 相比较 TiDB 而言,集群的高可用和大表须要分库分表其实就是 MySQL 在对面当前需求的抽象泄漏,MySQL 的集群高可用须要 DBA 和基础架构团队花成本去解决,MySQL 的大表分库分表方案须要 DBA、基础架构团队和业务研发团队花成本去解决,只不过这些都是隐性成本,不像在搭建数据库集群的时候,TiDB 比 MySQL 可能须要更多的机器来的简单直接,因此很容易被忽略了。
因此,对于成本与效率的衡权,伴鱼技术团队更关注工程师的效率,更关注工程师的心情(在业务上层重复解决一些底层软件抽象泄漏的问题是很影响心情的),更关注隐性成本,而不只仅是帐面明显能够比较的资源数字,特别是在机器愈来愈便宜,人才愈来愈值钱的趋势下。
选择一个技术,其实也是选择了这个技术的生态,若是技术生态完善,作事情每每会事半功倍,极大地提升研发效率。TiDB 在这个方面作的很是好,全面兼容 MySQL 协议,让 TiDB 的用户享受到 NewSQL 的能力的同时也享受到 MySQL 的生态,这个是很是正确的决定,MySQL 生态是几十年的积累,不是一朝一夕能够作到的。
另外一方面,在选择面向将来、优雅高效的解决方案,仍是选择成熟的但不够优雅和高效的解决方案,若是选择成熟的解决方案,对技术的掌控会比较高,可是会在效率方面持续的进行付出;若是选择面向将来的解决方案,须要花时间和精力来掌握新技术,可是新技术会优雅和高效的解决问题,咱们认为这个就是技术的红利。好比对于大表的解决方案,MySQL 提供的解决方案是分库分表,业务研发和 DBA 一块儿配合很是低效地解决这个问题,可是对于 NewSQL 的 TiDB,单表几乎能够理解为无限大的(业界已经存在 100 亿以上的表),从根本上解决了这个问题。如今伴鱼的大表都从 MongoDB 迁移到 TiDB 上面,业务研发和 DBA 再也不为数据的增长而不停地进行分库分表,这个就是巨大的技术红利。
因此,基于上面的一些讨论与思考,伴鱼决定 All in TiDB,MongoDB 再也不增长新的库和表,正在使用 MongoDB 的业务继续使用,而且对 MongoDB 上的大表进行有计划的迁移,避免进行分库分表操做。
在彻底掌握一项新技术前,享受新技术的红利是有代价的,特别是伴鱼在 TiDB 比较早期的时候就决定 All in,这很考验技术团队的学习和进化能力、新技术的社区和官方提供的技术支持的能力。在 TiDB 这件事情上,伴鱼技术团队和 TiDB 的技术支持团队都作的很是优秀了,可是咱们从 TiDB 1.x 到目前的 3.x 的过程当中依然仍是踩了一些坑。
单表数据 30W+,查询请求并发约 10+,某次业务上线,新增一个索引后,致使原有的查询索引选择错误,TiKV 实例所在机器 cpu 迅速被打满,引起故障。
线上某张大表,请求量比较大,偶尔出现个别条件走不到索引,致使全表扫描,从而引起接口响应时间的抖动,影响业务。
线上某张 14 亿的大表,查询条件区分度很高,某天出现特定条件忽然走不到索引,致使全表扫描,引起故障。后面通过 TiDB 同窗排查,系 bug 致使。
优化器选择索引问题,TiDB 从 1.x 到 3.x 的过程当中,优化器表现愈来愈好,同时伴鱼 DBA 团队经过性能监控和慢日志监控提早快速地发现问题,而且对大表采用强制索引的方式避免隐患,目前这个问题已经比较完全的解决了。
为了进行数据分析,咱们把上游各 TiDB 集群的数据经过 Pump / Drainer 汇聚到一个 TiDB 集群供大数据分析使用,在使用过程当中,遇到数据不一致、数据同步慢和编码不一致致使同步失败等问题。
随着伴鱼的 DBA 团队深度研究 TiDB 而且和 TiDB 的同窗进行持续的深刻沟通,目前对 TiDB 的掌控力愈来愈强,大数据同步问题目前已经获得解决。
如今伴鱼有 10 套 TiDB 数据库,110+ 数据库实例,6 个 TPS 过万核心集群,999 线基本维持在 16ms 左右,响应时间和稳定性都达到预期。从目前的状况来看,伴鱼选择 TiDB 是一次很是正确的选择,咱们在数据库技术方面弯道超车,避免了对 MySQL 技术的重复建设与积累,享受了 NewSQL 数据库 TiDB 在高可用和水平扩展等方面的技术红利,大大提升了业务研发和 DBA 的工做效率。 固然,这是伴鱼技术团队(特别是 DBA)和 TiDB 技术团队共同努力的结果。
这里还要特别提一点,TiDB 每一次版本升级都会带来惊喜,这是一个能够持续享受的技术红利。
目前,在摩尔定律失效、业务的高可用要求和成本优化等综合的大环境下,分布式架构是技术潮流的大势所趋,流量路由策略加多副本部署(微服务是其中的一种架构形式)解决了无状态服务的分布式架构问题,Redis Cluster 和 Codis 等方案解决了缓存的分布式架构问题,Kubernetes 完成了操做系统的分布式进化,数据库领域天然也不会例外,它的分布式架构趋势必定是不可阻挡的。要特别说明一下,这里所说的解决问题是指系统性的解决问题,MySQL 业务侵入式的分库分表确实是一个能够解决问题的分布式架构方案,可是须要业务研发配合一个业务场景一个业务场景的去解决,这就不能称之为系统性的解决方案,由于在解决这个问题方式上,业务侵入式的分库分表方案将本应由数据库处理好的大表抽象泄漏给业务层了,在这个问题上,咱们认为 NewSQL 是一个系统性的解决方案,而 TiDB 就是当下很是不错的一个选择。
另外还须要说明一点的是,这是一篇数据库选型的文章,因此只记录了与之相关的内容,好比详细描述了伴鱼技术团队在将数据库迁移到 TiDB 后踩的坑,由于这是咱们数据库选型 TiDB 付出的代价,因此必定要详细记录;没有记录在使用其余数据库踩的坑,这并不表明咱们没有踩到,好比在使用 MongoDB 的过程当中也踩过一些坑,可是由于这并非咱们决定从新作数据库选型的缘由(决定从新选型的缘由见文章「为何放弃 MongoDB」部分),因此就没有在文章中记录。
本文转载自 InfoQ 微信公众号,点击查看原版文章 《咱们为何放弃 MongoDB 和 MySQL,选择 TiDB》。