编者按
本文摘自由网易 DBA 团队撰写的《效率的选择——分布式数据库 TiDB 网易内部选型介绍》一文,对比了以 TiDB 为基础的创新架构和 MySQL + DDB 传统架构的差异,从业务适配、降本增效、技术创新等多个维度阐释了网易考虑引入 TiDB 的原因。
作者倪山三 ( hznishansan@corp.netease.com ),网易数据库专家,杭研数据库运维团队负责人。
TiDB 是⽬前开源数据库领域最热⻔的技术热点之⼀,无论是从发展势头、技术迭代速度还是社区活跃度等⽅⾯来说,在国内一直保持着领先水平。⽹易 DBA 团队本着好奇⼼和尝鲜的⼼态始终关注着 TiDB 技术发展,也一直在进行着 “⼩打⼩闹” 的尝试。但是如果要从线上选型角度去严谨地调研⼀款关系型数据库产品,其动机和预期成效⽅⾯的讨论应当是非常严谨的。
直⽩点说,就是我们有什么理由要⽤⼀款新技术尝试挑战稳定使⽤的现有技术⽅案,特别是在⽹易⾃研分布式数据库 DDB 能满⾜我们当前需求的前提下。TiDB 对我们来说并不是分布式数据库 0 到 1 的改变,⽽是 ⼀系列痛点上 1 到 1.1 创新的集合 ,更需要细致地加以阐明,本⽂即是对这⼀问题较全⾯的讨论。
DBA 团队希望将 TiDB 逐渐引入⽹易数据库核⼼选型,对相关技术感兴趣,或者有具体需求的同学请与 DBA 保持沟通,也希望本⽂起到⼀定的解答疑问和推⼴作⽤。
DDB 是网易内部自研的 MySQL 之上的水平分布式中间件,可以类比为 ShardingShpere 或者 Vitess。
分布式数据库技术发展背景
随着各⽅⾯成本有着显著优势的 PC Server 趋于绝对主流,现在提到数据库,很少有⼈会想到⼩型机和盘柜时代的 Oracle 或 DB2 这样⼀个柜⼦⼏百 T 的⼤型集中式数据库了。但是业务数据量和请求量仍然在不断增⻓,因此近年来我们就要依赖分布式数据库技术, 利⽤⼩规格的 PC Server 资源,提供⼤体量的集群式服务 。
- 分布式数据库有着多种实现⽅式,对比单体数据库时代我们能够提供的接入体验,业务通常要求分布式数据库⽅案满⾜以下基本特性:
- 要尽可能完整地⽀持包括 CRUD 和 DDL 在内的 SQL,同时要⽀持事务特性,满⾜这两点才能算的上是⼀个(关系型)数据库
- 通过统⼀集群入⼝提供服务,屏蔽内部分布式细节
- 要有伸缩能⼒,⽆论通过何种⼿段,数据库要能满⾜持续增⻓的存量数据和吞吐能⼒要求
- 作为最重要的中间件,服务应对软硬件故障的⾼可⽤特性也是重要考虑点
利⽤零碎资源组装⼤型服务的分布式技术可以说是⽬前服务端软件设计的标配,理论与实践⼀直在不断发展,但是其实关系型数据库分布式技术的发展可能没有⼤家想象的那么成熟与完善。关系型数据库本⾝虽然发展较早,但是却是在分布式技术⽅⾯是发展爆发较晚的那⼀个。在⼴义存储领域,2006 年⼤概是分布式技术最重要的⼀年,当时 Google BigTable、Amazon Dynamo、Hadoop ⼏乎同时出现,奠定了⽬前整个业界分布式存储从技术原理到基础设施实现的半壁江⼭。⽽关系型数据库直到 2012 年 Google Spanner 论⽂发表前,⻓期处于商业⽅案垄断,分布式技术理论发展较慢的阶段。可能就是由于上述 4 点特性要求使得分布式数据库的技术⻔槛显然比其他不需要⽀持事务、⽀持 SQL 的服务来的高。
在我看来,关系型数据库分布式技术发展可以分为三个主要流派线路,其各⾃有多个阶段:
⽬前整个业界现状基本如此,三个路线虽然发展有早有晚,但是⽬前都处于被⼴泛接受并且⼀直活跃的情况,并不是⼀般认为的换代取代的关系。同时可以看到选择其实并 不是很多,⾄少比⼤数据那庞杂的技术栈清晰多了。我们进⼀步分析⼀下我们可能的选型:
- sharded storage(线路 3)⽅案虽然技术含量很⾼,从性能到吞吐能⼒都⽆可指摘,但终归是完全的商业化⽅案。我们并不排斥,将在公有云场景中适时地充分利⽤,但是依赖特殊供应商的商业⽅案显然并不能作为孤注⼀掷的唯⼀选型,除非有相对开放的⽅案出现(好消息是⽹易数科也确实在这⽅⾯进⾏研发,并已经取得进展)。
- DDB 是⽹易⾃研的,基于 MySQL 的分库分表型(线路 1)中间件,也是当前我们的主流选型。在这⼀⼤类型的分布式⽅案中,各种开源中间件的功能,实现⽅式都非常雷同,其他任何⽅案与 DDB 相比都不存在同质竞争的明显优势,⽽各⾃缺点都很突出,不如 DDB 普适。因此在中间件这⼀流派,DDB 就是最优解。但是分库分表中间件在如今的业务使⽤场景中逐渐遇到⼀些效率⽅⾯的问题,这也本⽂接下来的主要论述重点,为啥我们有 DDB 分布式⽅案的情况下还需要尝试新的分布式数据库技术。
- 这样剩下的就只有 NewSQL(线路 2)了,要看是否能解决我们在 DDB 中间件⽅案中遇到的痛点了。⽽ NewSQL 三⼤代表中只有 TiDB 是主打 MySQL 兼容,特别是 YugabyteDB ⼲脆 Postgres 为主,所以我们聚焦的重点⾃然⽽然变成了 DDB VS TiDB。
所以看着像是数据库技术间的世代竞争,其实也没这么复杂,对我们的现状来说, 传统数据库 = DDB + MySQL,眼下的新⽣代 = TiDB 。
TiDB 选型优势与传统分布式⽅案⽐较分析
最本质的问题其实是我们是否需要,为什么需要引入 TiDB 技术。如上所言,我们希望通过新⼀代数据库运⽤,来解决或改善当前 MySQL 分布式中间件模式使⽤中的⼀些问题。都有哪些问题、TiDB 如何改善,我们将展开详细介绍。
优势概览
⾸先先看选型调研下来关于 TiDB 优势的结论总结,接着按照相关分类逐⼀进⾏论述:
- 提供 DDB 同等的⽔平扩容能⼒
- SQL⽀持能⼒较 DDB 好
- 资源扩缩容粒度更加灵活,不需要像 DDB,每次都翻倍扩容
- 扩容⾏为效率和安全性
- 数据存储成本⼀定程度降低(不需要 raid10+rocksdb 压缩-rockdb 写放⼤)
- 在线 DDL⽀持更好,除了加索引基本都是秒回,⼤表增加修改列成本显著降低
- 主从复制效率显著提⾼,降低写负载下⼀致性和⾼可⽤降级的⻛险
- 数据⼀致性下限提升
- ⾼可⽤⾃动恢复可靠性与效率显著提升
- HTAP 能⼒能够减少数据传输环节的成本和⻛险, 提供业务更⾼效的实时分析能⼒
SQL ⽀持能⼒较传统 hash 分表模式得到提升
TiDB 虽然也并不是完全兼容 MySQL 所有 SQL 功能和语法,依然有⼀定限制,其中相对重要的限制包括:
- 不⽀持存储过程/触发器, 不⽀持 select into 变量不⽀持 MySQL 较新的 WITH ROLLUP 开窗
- 不⽀持外键约束
- 不⽀持视图上的 DML 更新基表
- 不⽀持显式 XA 流程控制 (因此虽然 MySQL 兼容但⽆法作为 DDB 的存储节点)
- 不⽀持 savepoint 制
- 5.0 之前的版本不⽀持 DECIMAL 精度修改
但是对于我们来说,这些限制⼏乎没有影响,因为分布式中间件 DDB 也⼤部分不⽀持或者限制很多。我们 可以认为 TiDB SQL 能⼒是 DDB 的超集 ,业务仅需要更换驱动,从 DDB 专有驱动 DBI 更换为开源 MySQL 驱动如 jdbc + 连接池即可完成业务迁移。
这个超集部分 体现最直接的就是⼦查询和 join 的⽀持能⼒有显著提升 。DDB 模式下由于所有表都做了指定字段的 hash 分布,join 语句如果 join 字段正好是两个表的均衡字段,则能够完成分布式数据库内连接查询,性能尚可;但如果 join 字段必须跨节点匹配,在 DDB 中只能通过客户端 DBI 集中缓存全部数据的⽅式进⾏中⼼化计算,极易造成 DBI OOM 进⽽崩溃。进⼀步地,⼦查询由于优化器⼀直没有完成相关功能,直接是不⽀持的。这⽅⾯TiDB 的⽀持显然要优秀很多。
但是 TiDB 使⽤过程中还是有⼀些其他的 注意点 :
- ⾃增 ID(AUTO_INCREMENT), 由每个 TiDB server 独立分配, 能保证全局唯⼀, 且单个 TiDB server 内递增, 但是⽆法保证全局递增, 以及没有任何连续性保证。这个其 实和 DDB 的批量分配唯⼀ID 造成结果类似的。
- 单⾏单列⻓度限制, 都是定死的 6MB, 也就是 KV 的单个 key entry 上限就是 6MB, MySQL ⾥可以通过 longtext/longblob 等突破到 G 级的记录⻓度, 在 TiDB 不适⽤(虽然数据类型是预留了,但是⽂档描述有误)。
- 事务⻓度限制,在使⽤乐观事务并开启事务重试的情况下默认限制 5000,可调整,同时我们不太可能⼴泛使⽤乐观锁模式,因此影响不⼤。其他以前很坑的事务⾏数限制 30W,总⼤⼩ 100MB 等在 4.0 后不存在了。
⽔平扩容实际效率和能⼒显著提升
DDB 和 TiDB 理论上都可以通过增加存储节点,并且重均衡存量数据,实现存储容量近乎⽆限的扩展能⼒,但是实现⽅式上⼤相径庭。客观来说,DDB ⽬前在⽹易的使⽤规模已经使得⽔平扩容在部分场景下困难重重。
传统分布式中间件(比如 Vitess)的扩容形式⼤同⼩异, 你需要先为集群添加扩容前资源成倍的新资源, 但是这些资源暂时还不可对外提供服务, 然后通过各种⼿段将存量数据以及实时增量数据同步并拆分到新资源,然后找某⼀时刻完成新老资源的替换,老资源下线,完成扩容全部流程。
由于有⼤量的经验和⼯具开发,DDB 传统模式扩容⽅⾯我们有着非常完善的⾃动化辅助能⼒和可靠性保障,因此能⼒⽅⾯是没有问题的。关键在于效率:
- ⾸先是必须成倍的资源投入。我们内部较⼤规模的 DDB 集群数据存储量有百 T 这个量级,这是 8 年存量的结果,这个存量情况下数据的增量很难再出现成倍爆发式增⻓。但是传统⼀拆⼆模式下的扩容通常要求成倍的新资源投入,拆完后⽔位从 100% ⼀下回到 50%,⽽⼀年实际增⻓可能还不到 15%,这个⼀次扩容的投入成本效率可⻅⼀斑。当然我们可以同重新 hash 等⽅式使⽤比例扩容,技术上是做的到的,但是下⾯就要讨论时间和稳定性成本了。
- 其次是扩容过程效率太低了,我们有多种⽅式完成存量数据的迁移以及增量数据实时同步,技术上没有问题,但是效率实在太低了。在保障线上负载相对稳定的前提下,我们的经验数据是算上增量补偿时间,每 2T 数据迁移完成物理⽅式约 10
20 ⼩时,逻辑⽅式约 3040 ⼩时。当然分布式集群这些传输都是并⾏的,由于磁盘容量因素,我们数据库通常以 6T 为⼀个并⾏单位,即便如此,整个时间也得以周来计算了。 - 然后就是扩容成功率的问题,⼤部分情况下⾜够的资源投入和⾜够⻓时间的准备周期让我们扩容相对来说还是靠谱的, 但是近年来我们确实遇到了扩容⽅案⽆法实施的问题。例如有⼀次扩容需求来⾃于业务逻辑调整,数据写入吞吐量剧增,负载和容量都不够需要扩容,但是 MySQL 孱弱的主从复制效率造成了扩容后增量数据补偿永远跟不上数据写入量,甚⾄换了更⾼效的内部逻辑并⾏ CDC ⽅案也跟不上,导致数据源切换⽆法完成的情况。也就是我们即使紧急准备了⾜够的资源打算扩容现有集群,依然可能出现⽤不上的情况。
综上,我们可以看到 DDB ⽅式的扩容在⼀些实际场景在投入成本,效率,可⾏性⽅⾯都有⼀些难题,⽽ TiDB 的引入则能够为我们解决这些问题。TiKV 的扩容从运维角度上来 看是机器简单的⼀个操作:
- TiDB server 由于⽆状态,其 扩容相对容易 ,⽽ PD 作为管理服务本⾝⼤概率不需要扩容,因此通常来说的扩容主要是存储服务 TiKV 的扩容。
- TiKV 扩容操作仅需要在新增服务器上合理配置并启动服务即可, 新启动的 TiKV 服务会⾃动注册到现有集群的 PD 中, PD 会⾃动做在线的逐步负载均衡, 对业务⽆感知地, 逐步地把⼀部分数据迁移到新的 TiKV 服务中。⽽新投入的 TiKV 资源可以认为在启动的⼀瞬间就已经将资源添加到了现有集群, 不需要再等待漫⻓的, 外部控制的数据重分布过程 。
- 顺便提⼀下, 传统分布式形式中数据库的缩容和扩容基本同样⿇烦, 都需要⾯临数据重分布效率低下的问题。⽽在 TiDB 中缩容 TiKV 节点, 只要不违反相关约束, 安全关闭前 TiKV 会先通知 PD, 这样 PD 可以先把这个 TiKV 上的数据迁移到其他 TiKV 实例, 保证数据有⾜够的副本数后完成⽆感知缩容, 效率和⾃动化程度也较传统模式有巨⼤提升 。
因此我们看到,⽆论是从扩容操作效率,过程的⾃动化程度,还是过程的可靠性来看,TiDB 都是比传统模式有着很⼤的提升,能够将以天乃⾄周计算的扩容流程效率提升到分钟这个级别。
schema 变更⽀持能⼒提升
类似上⾯⼀条⽔平扩展,在采⽤MySQL 底层的基础上的传统分布式中间件还存在着显著的 schema 变更瓶颈,⽽且问题也是出现在存储资源和性能上。
schema 变更有些是相对容易便捷的操作,例如新建⼀个表这样,在任何情况下都不是太⼤的问题。⽽有些在 MySQL,或者说传统块⾏存储数据库中⼀直是相对⿇烦的⾏为,例如加字段,修改字段类型属性,加索引,改键等。在 Oracle 中通过正常 DDL 或者在线重定义两种比较正规的形式就能统⼀所有操作需求,⽽在 MySQL 中这类变更功能⼀直是技术难点,⼿段多,坑也多,⼤家可以通过下⾯的图感受⼀下:
主要痛点包括:
- MySQL 的 online DDL 始终让⼈难以完全信任,即使在 online DDL 随着版本完善的过程中,我们也不得不为了规避某些情况坚持使⽤外部变更⼯具。
- 由于稳定性⻛险, 虽然 online DDL 并不会如传⾔所说锁表时间同增量更新有线性关系, 但是依然有其他⽅⾯的⻛险, 例如我们不太远的过去遇到过 online ddl 中 inplace 算 法 要 求 刷 脏 导 致 写 负 载 型 数 据 库 卡 顿 影 响 稳 定 性 的 ⻛ 险 (想 了 解 的 同 学 可 以 参 考 : http://www.percona.com/community-blog/2020/04/23/unexpected-slow-alter-table-mysql-5-7 /)。我们已经在哪种情况使⽤哪种⽅式做了非常多的策略判断了, 多年尝试, 实在难以根据每个特定业务场景做出完全可靠的智能策略,有时候为了避免不必要的⻛险,不得不依然依靠业界⼴泛使⽤,⼴受考验的外部⼯具继续做为统⼀变更⼿段。
- 由于不确定性⻛险,我们⾃研运维平台⾃动化处理的数据库⼤⼤⼩⼩变更⼀年接近⼗万量级, 如果说⼀种每天都在频繁使⽤的核⼼功能其成功率要依照⼀个默认 128MB,实际不知道多⼤合适的参数的限制,在部分业务场景会经常遇到
RROR 1799 (HY000): Creating index 'idx_xxx' required more than'innodb_online_alter_log_max_size' bytes of modification log……
类问题,不但失败还要浪费⼤量资源进⾏回滚的。这个功能是⼀个可靠的功能吗? - 实际上在业界对 online DDL 的⻓年不敢⼴泛使⽤是 DBA 这边的常态,比如阿⾥云等公有云⼚商和我们是基本相同的做法: 如果你要⼚商提供变更⽀持,则⼀律采⽤外部⼯具,即使在 PolarDB 时代依然如此。
- MySQL 内部机制不太靠谱, 外部⼯具也问题多多, 特别是效率问题, 外部⼯具变更需要比变更表更⼤的磁盘剩余空间来完成操作, 因为外部⼯具和原始 DDL 的 copy 模式是⼀样的, 只是不锁 DML⽽已。我们需要完全拷⻉⼀份原表数据应⽤变更, 并且期间还会造成⼤量 binlog。比⽅说, 你想变更⼀个 500G 的表, 我们的经验是数据库本地需要⾄少还有 1T~1。5T 以上空余空间, 我们通常认为才是完全安全的。同时拷⻉数据同上⾯扩容是类似的情况, 需要⼤量时间。实际情况是核⼼业务存量表往往较⼤, 导致你还得先扩容再变更, 这就造成了变更的时间成本和资源成本经常让业务难以接受——翻倍的资源, 以周计算的时间, 变更期间读写分离⼀致性失效, ⾼ 可⽤失效……我们的业务通常望⽽⽣畏,让本该随⼼所欲的数据库变更变成⼀种仅在理论上可能,实际难以实现的需求。
- 其他的性能冲击,约束键导致的⼀致性⻛险,变更期间⾼可⽤⻛险,DDB 环境下分布式变更的调度和原⼦性控制,极端情况下⼤家都会遇到的 MDL 阻塞,对备份机制的影响 ……各种各样问题不⼀⽽⾜。
以上痛点是致命的,严重影响业务迭代,稳定性,效率的。我们迫切希望⼀种新的模式来改变现状,顺便⼀提,变更的部分痛点即便在 PolarDB 和 Aurora⽅案下依然还是难 点,因为他们的上层使⽤的还是 MySQL。我们 DBA 团队随着多年采坑,为了能够提供线上可靠的⾃动化变更能⼒,不算⼯具,流程,前端代码,仅后端调度和管控代码就投入了两万多⾏,⽬前除了资源吃不消难以变更的情况外,能够基本保证⽇常变更⾼效安全。虽说这是我们吃饭的本事,但是我还是要说这个模式复杂的没有价值,效率也随着业务存量增加,逐渐显得不可接受,希望技术上能够得到突破。
⽽ TiDB 在这块以我们调研和⽬前应⽤结论来看,就有较⼤的优势了。
简略来说,TiDB 主要有如下优势:
- 由于 kv 模拟⾏表的数据结构,以及 LSM 存储⽆法更新的特点,⼤量数据类型,加减字段,默认值类的操作都可以通过仅元数据变更实现完全 instant,相较 MySQL 8.0 的 instant 范围显然要⼴,效率非常⾼,都是 1s 级别完成变更,且业务感知⼩ 。
- 加索引这类必须产⽣新持久化数据,⽆法 instant 的操作,采⽤后台任务,异步线程的机制实现对业务影响相对⼩。⽽且 ADD INDEX 时 tidb 有明确参数记录⽬前索引 创建的进度和速度,能够较好安排调度。
- 上述两者都比 MySQL copy 或外部⼯具模式显然节省空间。⽽且 TiDB 本⾝扩容就要比 MySQL 中间件⽅式容易的多,变更的效率和可⾏性都将巨⼤提升。
- 更不会有主从问题带来的⼀系列延伸问题。
当然虽然效率提升了,但是也不能说 TiDB 的变更对业务完全没有影响,具体来说是有些新的情况:
- 由于 schema version 的变化,执⾏的 DML 语句中涉及的表和集群中正在执⾏的 DDL 的表有相同的,那么这个 DML 语句就报错Information schema is changed,⼀次性,但是需要业务使⽤连接池连接数据库,并且业务端有重试机制避免事务完全失败。
- ADD INDEX 操作,根据压测,⽬标列被频繁读写,特别是写多时对性能影响较⼤(即 对业务原有字段加索引时可能会对性能有较⼤影响),QPS/TPS 极端情况下下降 23% 左右,这个其实和 pt-osc 近似了。
总体来看,我们是非常希望通过引入 TiDB 来解决⽬前业务表结构变更中的痛点,提升相关效率,进⽽帮助业务更快更安全地实现迭代。
⾼可⽤可靠性与效率显著提升
MySQL 虽然是业界最⼴泛使⽤的数据库种类, 但是在 MGR 技术完全普及(⽬前还谈不上)前其服务⾼可⽤实现⼀直是有问题的。具体设计上的问题各位可以 KM 搜索我之前的数据库⾼可⽤⽂章,我们就不展开了,直接介绍业务痛点。
- 主从⼀致性虽然可以做到相对安全,但是下限非常低,需要许多相关参数和机制配合,例如多种 log 持久化,半同步,复制信息表记录,半同步 ack 模式,non-loss 等……⼀项问题都可能导致主从不⼀致,进⽽影响可靠性。
- 不⽤ MGR 则集群没有内部协调机制,切换需要外界参与,⽽不能向 ZK,redis cluster ⼀样集群内部完成,这就导致了切换成功率,资源漂移可⾏性,以及如何防⽌极端 情况脑裂双写⽅⾯⼤量的坑。并不是不能做,但是要做到完全靠谱并不容易,这块我之前的⽂章有非常详细机制原理的介绍,如感兴趣请参考。
- ⽤了 MGR,虽然集群内部角⾊和⾃治切换问题得到了解决,但访问模式官⽅⼀直没有给出非常好的解决思路,⽆论是堪比 sidecar 的 proxy 模式还是⾃⼰改客户端,或者像过去⼀样外部控制资源漂移,都没有很好地解决客户端切换的问题。这块MySQL一直没有和 Redis 或 MongoDB 学习,让人比较郁闷。
- 外部切换还存在效率问题,也就是切换对客户端恢复服务的时间间隔。有可能是域名切换,客户端缓存导致的问题,也可能是 DDB 这⾥元数据更新串⾏化导致的。特别是⽹易内部 DDB ⼴泛使⽤的 DDB 模式下,由于通过更新路由配置中⼼实现,存在通知客户端⽹络超时和配置中⼼更新只能串⾏两⽅⾯的痛点,导致硬件故障造成的最基本切换场景所需的时间只能保证在 1 分钟级别,5 分钟以内,这就是切换效率的问题了。
- 最⼤的痛点,即便是 MGR,MySQL binlog 复制是⾼可⽤功能上⽆法回避的梦魇。这块接下来要单独讲。
单独来说 MySQL 最核⼼的问题之⼀,基于 binlog 主从复制的性能问题 ,这⼀问题并不能通过升级 MGR 技术改进:
- 相对 Oracle 的数据⻚逻辑复制,MySQL 的 binlog 逻辑复制性能简直让⼈⽆法忍受。即便是并⾏复制情况下,根据业务特征,⼤部分情况下,⽆论哪种并⾏模式都⽆法让复制效率实现质变,为了提高效率我们不得不折腾日志持久化,组提交等周边性能要素,甚至造成一些持久化风险。通常我们认为在 CPU,IO 和⽹络都没有瓶颈的情况下,单组 MySQL 实例⾄多也就只能保证简单更新 3000~5000 tps 的复制效率,随着逻辑复杂,部分业务可能超过 2000 tps 就可能产⽣延迟,如果在所有安全措施特别是从库⽇志持久化相关全部严格要求下,性能可能更糟……复制延迟意味着⾼可⽤⾃动切换失效——虽然⽇志到了从库,但是数据尚未被更新,不能让业务切换后读写延迟的数据。
- 线上⾼负载可能导致复制延迟,例如我们⼀些电商类的活动⾼峰期间,订单等数据的写入⾼峰造成延迟,再最关键的时候数据库⾼可⽤实际上是没有保护的。
- 变更可能造成延迟,⽆论是 online DDL 还是外部⼯具变更,都会随着变更对象规模变化,造成不可控的延迟,严重的可能以天计算,在变更期间⽤于读写分离分流负载的从库⽆法读,同时主库缺乏⾼可⽤保护,挂了就挂了……⼤家知道真相是不是会出⼀⾝冷汗?
- MySQL 解决延迟我们认为唯⼀可⾏的办法就是实例级别的⽔平拆分,每个实例来撑尽可能⼩的 tps 负载,⼀种非常另类的并⾏化。但是这并不是⼀种非常可⾏的模式,例如 DDB 为代表的分布式中间件场景下,⼀个数据库从 64 分片拆到了 640 分片,每个客户端连接对象,分布式事务损耗,集群变更和管控难度都会不断正在,⽽且也⽆法保证真的能彻底解决延迟——比如问题是热点造成,如果业务热点写集中在⼀个分片呢?
TiDB 在⾼可⽤和数据复制⽅⾯同样有着巨⼤的优势:
- ⼀致性下限就非常⾼,raft 机制保证数据副本可靠,想要造成不⼀致的可能反⽽困难。
- TiKV raft group ⾃治选举,⽆状态的 TiDB server 层⾃动更新路由,⾃治切换和业务连接漂移都不再是难事。
- 切换效率也非常好,虽然每个 group 都要选举,但是⾼度并⾏化,稳定的 10s 数量级内完成。
- raft group 级别⾼度并⾏的复制效率,我们做过相关压测,写压⼒在 MySQL 等量集群延迟⽔位 10~20 倍以上的情况下依然没有相关⻛险。
TiDB 的数据多副本⼀致性,⾼可⽤在机制上对于传统 MySQL,特别是非 MGR 模式来说堪称 跨时代的进步——终于进入了合格的分布式集群时代。
未来,特别是业务可能⼤量使⽤公有云设施的情况下,可能 TiDB 这类⾼效和可靠机制是强需求,因为公有云虽然整体资源池有优势,但是单点资源的可靠性根据我们的经验和 SLA 标准来说,是不如我们现在的⾃有机房的。如果在成本考虑,不完全依赖 RDS 的前提下,资源问题概率的提升会放⼤以前⾼可⽤机制上的多种问题,⽽TiDB 可说根治性地解决了这些问题,这也是我们希望换代的关键理由之⼀。
存储成本有优势
TiDB 和传统数据库在存储硬件选型上没有太⼤区别,基本我们⼀般都是使用 SSD。那么存储成本可以这样来对比估算。
以⼀块单独的 SSD 磁盘为最⼩单位,MySQL 模式即便是最⼩冗余⼀份的前提下,我们也会有 4 块磁盘,⽽ TiDB 这边由于⾼度的⼀致性保障,我们可以磁盘就不做 raid1 了,这样最⼩单位虽然是三副本,但实际投入是 3 块磁盘。也就是⾄少节省 25% 的空间。
进⼀步地,TiDB 相较 MySQL 还有另外⼀个优化点,MySQL 的 innodb 由于历史原因,我们并没有⼴泛采⽤压缩格式,⽽ TiDB 的 RocksDB 存储引擎默认是压缩的。虽然 kv 逻辑上有着较⼤区别没有办法直接比较,不过总归来说,压缩总是可以⼀定程度上节省空间的。
根据我们具体测试量化来看,TiDB 压缩相较 MySQL 非压缩情况下根据业务数据不同,差距很⼤。比如 sysbench 类随机字符串⽆意义数据,压缩比例不⾼,
5 亿 68487932199-96439406143-93774651418-41631865787-96406072701-20604855487-25459966574-28203206787-41238978918-19503783441
这种类似的随机字符数据 innodb 114G,⽽ TiDB 102G。
但是如果是有⼤量数字,浮点,时间戳,有意义短单词的实际业务数据对比,如果数字特别多,压缩比例⼜非常惊⼈,
非压缩的 innodb 要 398G,而 TiDB 不到 30G。所以还是要看数据类型,虽然并不是压缩比⼀定非常⾼,但是肯定比 innodb 非压缩情况要好。根据我们实践经验保守来看,压缩节省比 例来看综合在 30%~50% 左右。
这样 25% 的 raid 节约,结合 30% 以上的压缩节约,综合起来我们可以认为 MySQL 换 TiDB 存储上可以有 35~50% 左右的存储硬件成本节约。这对存量预增的业务显然也有⼀定的意义。
另外顺便提⼀下, 在新型(其实也没那么新, 只不过我们⽤的不算多)硬件, 例如 NVMe 存储设备⽅⾯, 由于 PCIE ⽆法再接 raid 了, 因此天然适合 TiDB 这样软件层强⼀直冗余, ⽽完全放弃 raid 硬件层冗余的模式。
HTAP 创新模式
以上可能都是 1 到 1.1 的改进,HTAP 应该算是 0 到 1 的⼤型场景创新了。 我们强烈地希望 TiDB 相关特性能在⽹易发挥业务价值。
传统数据库我们通常认为有 MySQL 这样的纯 OLTP 数据库,由于⾏存,优化器功能局限,没有 MPP 引擎,中间件功能有限,资源利⽤率⼀般……等多种技术原因,是完全跑了不 了 OLAP 分析请求的。也有 Clickhouse 这样专注 MPP 和资源利⽤率,但写多⼏个并发或 SQL 没有批量就有稳定性⻛险,完全跑不了 OLTP 请求的。可谓泾渭分明。
在我们当前绝⼤部分当前业务场景下,都是类似上图,都需要从 OLTP 系统将数据录入专⻔负责处理 ad-hoc 类分析的在线 OLAP,以及专⻔处理任务式计算的离线数仓。虽然图看的很简单,但是其中利⽤到的技术栈相当庞杂,在⽹易内部数科团队,DBA 团队,业务算法团队,中间件研发团队等多个团队全拴在这⼀个链路上,可以说是技术含量最⾼的业务链路之⼀。在业界相信很多公司也是类似的情况。
- OLTP 部分主要就是 MySQL 及其分布式中间件。
- pipline 环节通常也可能是有逻辑过程的 ETL 环节,技术栈可能有定期批量的 sqoop 或 datax ⽅式,实时的 CDC(内部是 NDC)方式,处理过程中为了进⾏清洗和逻辑过滤等需求,还得⽤上 kafka 等队列和业务代码。
- OLAP 光处理 ad-hoc ⽅⾯⽬前我们就有 Oracle,greenplum,clickhouse,kudu+impala,presto 这⼀堆技术栈;其他 SQL 引擎如 doris,keylin,druid,hive 都有应⽤; 如果流式需要还有补上消息队列,flink,spark 等; 离线任务侧 yarn,spark……
上图来自小米的技术分享 , 你会发现这⾏业就是以罗列技术栈和链路架构为乐, 这个现状是业界主流。在我的角度(包括其他参与团队的角度)来看其实挺有意思的,⼤数据嘛,多⾼⼤上,⽽且技术上确实也有必要性,⼤数据确实需要适才适⽤。但是其实也是有⼀些显⽽易⻅的痛点的:
- ETL 过程时效性与数据⼀致性。
- 逻辑上的变更往往也是难点,⽆论是服务架构,存储⽅式,或是最上游表结构变更,都需要链路上⼤量改动⽀持。
- 服务技术栈特征是典型的多、专、深,依赖⼤量富有经验的研发和运维投入。
- 投入资源较⾼,中间过程和存储都是如此,如果需求需要多种技术栈才能满⾜要求,则投入成倍增⻓。
- 架构和团队复杂化带来的⼀些效率问题。
业界也有数据库不断在兼容 OLTP 和 OLAP 两种模式间探索,前有 Oracle 内置 MPP,后有 kudu 尝试兼容 OLTP。 ⽽ TiDB 依靠其特有的⾏列双存储技术特点,似乎走在了更加合理的道路上 。
TiDB 提出的⽬标是 100% 的 OLTP 和 80% 的 OLAP 场景,我不敢说这个⽬标是否切实,但是现状来看替代上述庞杂的 ad-hoc 分析需求中的⼀部分技术栈应当是合理的⽬标。TiDB 的技术⽅案也在短短的⼏年内也是经过⼀次重⼤迭代的,19 年以前的单纯的 TiSpark ⽅案实际上适⽤性⼀般,但是当前 结合了 TiFlash 列存存储的⽅案则真的是走出了⾃⼰的特⾊ 。
简单来说我们之前谈到过 TiDB 底层是有 TiKV 中的 kv 数据模拟⾏表 OLTP 数据库, TiKV 的写入则是通过 raft 协议和⽇志同步保证了多副本⼀致性, 那这个思路下同样可以通过⼀致性写入的⽅式完成⾏存 TiKV 和列存 TiFlash 存储的数据同时写入, 这样 TiSpark OLAP 引擎和 TiDB OLTP 引擎可以在完全⼀致, 但存储异构的两种数据源间⾃由选择访问⽬的,我们知道列存对于 OLAP 本⾝就是极⼤的提升,加之研发团队在相关领域的其他专业优化,⼀个真正在存储和计算层同时做到既保证数据⼀致,又能适才适⽤的 HTAP 数据库⽅案就出现了。
这⼀架构有⼀些显著的优势:
- 架构简单紧凑,管理和实施⽅案非常完善,且 TiFlash 功能的启⽤很灵活,业务任何阶段都可以调整,任何线上表可以不开启节约成本,可以随时开启⽀持新增分析需求。
- 集群实施成本也从 HDFS 级别缩减到了正常数据库级别,你不⽤非得⼀下⼦找⼗⼏台来搞最⼩线上部署,按需投入资源即可。
- 分析⽤数据从表结构到内容基本同在线表完全⼀致,如果分析需求就是需要基于在线结构,那么直接写 SQL 即可,可以完全省下同步环节相关的资源和维护开销。当然客观来讲,ETL 当然还有 T 的需求。
- 优化器⽀持,查询到底走哪种形式可以通过⾃定义,也可以交给优化器判断,⼀定程度上把纯粹 SQL 暴露做的更彻底,业务可以更简单地实现需求。
- OLAP 部分非常专业的深度优化,例如 TiSpark 可借助类似 clickhouse 的向量化引擎,按照和 TiKV 相同的 coprocessor 协议下推任务到 TiFlash,提升资源利⽤和性能。
- 扩展与 TiKV ⼀样容易。当然除了⼀⼩部分 (点名 clickhouse) 外的⼤部分分布式⼤数据集群⽅案在这⽅⾯还是可以的。
我们在公司内部有⼀些实践,随后会做简单介绍。同时我们也并不指望 TiDB 的 HTAP ⼀下⼦能起到多⼤作⽤,只是 希望在⼀些特定场景下提升服务能⼒,并简化架构,提升效率 :
- 替代现有相对老旧的 Oracle 和 GreenPlum 技术,主要是 roll up 类可能有些麻烦,但是绝大部分联表类肯定是可以的。GreenPlum 还好,Oracle 以我们现在的硬件条件,扩容都很困难
- 解决一些不合适的 SQL 直接在 MySQL 或者 DDB 集群里跑的问题,让 OLAP 处理效率合理化,促进更多数据分析能力和需求
- 如下图,部分替代 Impala on Kudu 和 Presto on HDFS。数据都来自线上导入,就可以尝试所见链路,提供更标准的 SQL 入口应该有的吸引力。
TiDB 内部实践
适⽤场景推荐
由于并不是分布式⽅案唯⼀选择,所以 TiDB 严格来说对我们有比较确定的适⽤场景,我们总结如下:
-
有明显淡旺季,周期性,需要⾼峰保障类型的业务
- 如电商有促销活动的场景,如⼀些业务专⻔⽀持临时活动的模块,如有显著周期性的教育类业务等,可以充分享受灵活扩缩容的优势。
-
对⾼可⽤和数据⼀致性需求特别强烈的业务
- 记账对账,消费凭证,外部⽀付回调等,⾼可⽤和⼀致性较⾼⽔平的保障能够帮助业务尽可能提⾼可靠性。 公有云上由于资源可靠性不如内部机房,如果未使⽤ RDS,可以尝试 TiDB。
-
核⼼模块两地三中⼼⽅案
- TiDB 提供⼀种非常有针对性的两地三中⼼实施⽅案, 参考: https://docs.pingcap.com/zh/tidb/stable/three-data-centers-in-two-cities-deployment 。意味着同城机房做跨机房的实时⾼可⽤冗余切换,异地机房提供⼀份非常可靠的最终数据冗余兜底。这⼀场景可以活⽤于重要性⾼的系统元数据,比如私有云服务元数据,像内部对象存储元数据这块再合适不过了,极⼤规模的关键数据,还能充分利⽤快速⽔平扩展的能⼒。
-
对 HTAP 有需求的业务
- 前⾯提过,如果对任何线上数据有分析查询需求,完全可以尝试不再使⽤传统导数据流程,使⽤ TiDB 单系统内搞定。
但是,由于我们的⽬标还是把 TiDB 尽可能地引入核⼼数据库选型,因此我建议⽬前对 TiDB 感兴趣的业务不⽤太拘泥于必须是完全匹配的场景。能⽤上匹配场景当然是最好,如果并不确定适⽤性质,那只要:
- 计划使⽤ MySQL/DDB, 但也对 TiDB 非常感兴趣
- 确实遇到存量⼤变更扩容难痛点
- 单纯想尝鲜⼀下
- 想要降低存储和运维成本的
- 想要学习分享新技术的
都可以积极尝试⼀下。保险考虑,无论是何种新技术的尝试,那种⽤途相对单⼀或边缘,但是业务和存量数据⼜相对⼤的场景作为起步肯定是最好的。
技术迁移和配套⽀持⽅案
使⽤ TiDB 与其他原有数据库的区别:
- 业务使⽤ TiDB 主要考虑 SQL 兼容和客户端连接⽅案。
- 如果是⾃研系统,业务在⽹易内部习惯于使⽤ MySQL 或公私有云的 RDS,⽽非使⽤ DDB,那么 TiDB 使⽤上和过去项⽬没有任何差异,使⽤普通驱动和连接池,更新数据库地址即可。以我的经验中,TiDB 不⽀持的 SQL 功能我们正常研发也基本不会⽤到。
- 如果要作为其他开源系统的底层元数据存储,可能要考虑下 SQL 兼容性,因为业界使⽤ SQL 的复杂程度有较⼤区别,我们⻅过⼀些国外开源项⽬ SQL 使⽤深度比较复杂的情况。
- 如果过去习惯使⽤ DDB,是 DBI 也就是特有驱动模式的,需要更换为 jdbc 驱动,并增加连接池,因为 DBI 客户端是内置连接池,jdbc 没有。
- 替换 DDB 的 SQL ⽅⾯⼤致没有问题,TiDB ⽀持是 DDB 的⽗集。需要注意的主要是 DDB ⼀些老式的唯⼀ ID 分配模式,要替换为 MySQL 兼容类型,例如隐式分配等。
- 如果过去习惯使⽤ QS 代理⽅⾯模式连接 DDB, 使⽤了 LBD 的要去掉 LBD, 改成正常 jdbc 连接⽅式即可。过去使⽤ QS 但未使⽤ LBD 模式 (比如 NLB 模式) 的不需要做任何修改。
TiDB server 分布式集群⼊⼝访问
由于我们知道 TiDB server 是⼀组⽆状态的计算节点,过去的 MySQL 类数据库我们都会提供⼀个唯⼀的入⼝,例如是虚拟 IP,域名或 DDB master 地址等形式,业务不需要关 系后端服务的漂移切换等细节。TiDB 这边的 TiDB server 对外暴露服务。我们可以选择如下⽅案:
⽅案⼀ ,传统 HAProxy,LVS 等负载均衡软件,配合 VIP,域名等切换资源,这是最常⽤的⽅案。
该⽅案的主要问题是负载均衡代理程序⾃⾝⾼可⽤如何保障,逐级堆叠很可能最后堆到 OSPF 去了。不过⽬前依然是最简单最可靠的接入⽅式,推荐使⽤。
⽅案⼆ ,采⽤原⽣ MySQL jdbc 驱动的 multi-host 配置⽅法,该⽅案在连接数据库的时候采⽤如下的写法:
static final Srting DB_URL = "jdbc:mysql:loadbalance://10.170.161.65:4121,10.200.166.102:4121/zane?useSSL=false&failOverReadOnlly=false";
也就是⼀次性连接提供的多个 TiDB server 服务。经过测试,可以实现多个 TiDB server 间的负载均衡和⾃动排除故障节点与连接恢复,详情请参考上述链接。主要问题是 TiDB server 列表如果发⽣改动,例如扩缩容或迁移,业务就需要修改链接并重启,会很⿇烦。
⽅案三 ,由于 TiDB server⽆状态的良好特性,我们将 TiDB server 集群移植到了 K8s 内,作为⼀个 service 对 K8s 内外进⾏服务。
⽆状态 TiDB server 的 K8s 化非常顺利与合适,通过 Ingress 的⽅式也可以提供 K8s 外业务访问的能⼒,相关准备和验证⼯作都已经完成。我们最终的⽬标肯定是 TiDB 的完全云原⽣化,⽬前部分云内部分云外的⽅案只是稳定性考虑的过渡模式。
综合来说,三个⽅案都可⽤,我们会根据实际情况和业务讨论确定具体使⽤哪种模式。
监控与其他运维⽀持
从 DBA 的角度来看,TiDB ⽬前有着较完善的监控机制与配套⼯具,并且完全基于业界同⾏的开源技术,因此我们⽬前也不打算再像传统数据库那样为它再重新做⼀套采集脚本与展⽰界⾯,⽽是直接复⽤原⽣的⽅案。
TiDB 各组件(除了图中⼏个主要服务外, 其他⽇志⼯具, 管理⼯具等配套⼯具都包括)均提供标准的 Prometheus 数据接⼝, 监控服务采⽤原⽣ Prometheus 拉取模式即可;另外 Grafana 有针对 TiDB 的完整模板, 并且区分度⾼, 同时数据逻辑联系强, 属于经过实践的⾼度有效模板。因此后续我们对 TiDB 监控展⽰和告警将直接使⽤原⽣⽅案, ⽽不 会迁移到哨兵或其他⾃建系统。并且报警系统对接当前 popo 或内部电话告警等接⼝也调试可⽤。
除了监控外,TiDB 作为数据库其他基本监控需求,包括不限于: 备份恢复,扩缩容⽀持,⾃动化集群操作⼯具,⽇志处理⼯具,数据导入导出,集群配置修改管理,版本滚动升级……等等,均有针对性⼯具,最可贵的是 TiDB 社区非常重视 SOP ⽂档⼯作,让社区经验能够转化为实践指导,这在开源数据库是非常难得的,同时我们内部也经过充分演练。我们团队与 PingCAP 的⽀撑和⼯具研发团队接触也较多, 深刻体会到 PingCAP 相关研发和社区⽀持同学都是资深 DBA, 对数据库使⽤过程中的需求和难点有着非常深刻地认识与⼤量实践经验,因此相关产品⼯具也相当实⽤,且相对其他开源项目可靠。
进⼀步地,内部⽇常使⽤中⼀些常⽤点,例如 OWL 的⽩屏数据访问能⼒,以及⽇常变更的⾃动化⼯单⽀持能⼒均已准备就绪,经过线上验证。业务⽇常使⽤过程中应当不会感受到 TiDB 与其他 MySQL 数据库的差异。
结论上看,我们认为 从运维⽀撑能⼒上,TiDB 也完全具备在内部推⼴的各项条件 。
现有业务迁移⾄ TiDB ⽅案
新上业务比较容易,但是针对已有数据和应⽤的业务将现有服务前移到 TiDB 上就是相对有难度的事情。除了上述⼀些接入⽅式和 SQL 适应性可能需要做⼀些改造,应⽤代码需要修改发布外,主要就是存量数据如何从 DDB 或 MySQL 录入 TiDB 了。⼏个考虑点:
- 我们肯定不希望采⽤⻓期停服(⾄少停写)的迁移⽅案, 最好数据能实时同步
- 并且肯定要考虑可随时回滚应⽤以起到回滚数据库的⽬的,因此要保证切换到 TiDB 后的增量数据还得实时回流原数据库集群,实现随时回滚切换回数据源的⽬标。
- 要有⼀定的灰度发布空间,以验证业务对 TiDB 的连接和使⽤是否可⾏。
经过⼀些内部实践,我们充分利⽤了内部现有⼯具和 TiDB 配套⼯具,相关需求⽬前都是可⾏并且得到⼀定经验验证的:
我们通过⽀持 DDB 分布式集群和 MySQL 单体集群的内部 CDC ⼯具 NDC 同步全量数据⾄⽬标 TiDB 集群,并保持增量数据的持续实时同步。再通过 TiDB 提供的 TiCDC 订阅 TiDB ⽇志,同步到 MySQL(使⽤ blackhole 引擎,仅做⽇志中转)再通过标准 NDC 同步回 DDB。这样就实现了⼀个双向实时复制的⽅案。
NDC 是⽹易内部⾃研的多数据源迁移和 CDC 平台,可以类比 xdata+canal 的平台化产品
业务迁移的时候可能的步骤是:
- ⽬前两个数据源双向同步核⼼问题是没有冲突解决和循环复制解决机制,因此⽆法实现全⾯的双写,应当保持单数据源单写,这样⽅案就是安全的。也是业务迁移步 骤最关键考虑点。
- ⾸先准备好 DDB->TiDB 的实时同步,直到数据⼀直追上。⾄此并不开启 TiDB->DDB 的反向链路。
- 如果可能,业务灰度发布只读业务⾄ TiDB,验证服务可⽤性。
- 正式发布切换在低峰期,业务 DDB 集群禁写,同时暂停 DDB->TiDB 链路,开启 TiDB->DDB 反向链路,业务发布 TiDB 数据源版本。服务不可写时间仅发布期间。
- 如果上⼀步顺利,则线上回归应⽤后迁移基本成功。
- 如果切换数据源后发现任何问题,确定要回滚应⽤和数据源解决,由于反向链路保证 DDB 同 TiDB 数据⼀致,因此 TiDB 禁写,DDB 开写,应⽤回滚即可。
另外,同⼀些业务沟通过程中我们发现,⽬前线上有⼤量数据 ETL 或消息总线是依赖 DDB/MySQL 的 binlog 订阅的,因此 NDC 兼容 TiDB 也是必须的,我们采⽤与切换相同⽅案:
我们会先将 TiDB ⽇志通过专⽤⼯具回放⾄⼀个中转 MySQL,再⽤ NDC 订阅,保证原有数据链路基本不变。
近期 TiDB 相关业务应⽤情况简介
这次我们的技术推⼴实践并不是划划⽔,⽽是真的期望 TiDB 能为数据库技术和使⽤效率带来⼀些质变。 TiDB 近期已经或者即将上线在网易支付、网易云音乐的多个业务模块中,TiDB 的 HTAP、秒级 DDL、快速扩缩容等能力也将不断提升用户体验 。
总体来说,TiDB 在⽹易内部的运⽤还处于起步阶段。⻓期以来我们⼀直苦于在两个问题上纠结,⾸先是 “有了 DDB 为什么还需要新的分布式系统” 以及 “HTAP 在哪些业务有价值”。经过⼀些探索和努⼒推⼴,这两个问题的认识上我们有了⼀些进展,也因此有了本⽂。希望我们近期的⼯作能够起到抛砖引⽟的作⽤,把数据库技术发展带来的能⼒ 提升真正落实到业务实际需求中去,提升⽹易数据库服务和能⼒⽔平。也欢迎对 TiDB 相关技术感兴趣的团队与同学能够与我们 DBA 组保持积极沟通,⼤家⼀起来推动相关技术验证与应⽤。