下图列举了在相同机器环境下,读写混合场景(读 50%,写 50%)下,Bytable1.0 TabletServer 与 HBase RegionServer 的延时对比。可以看出,Bytable1.0 在平均延时和 p99 延时上均有大幅降低。
2.3 优化细节
2.3.1 点读优化
因为我们在 RocksDB 的 KV 模型之上封装了 Table 数据模型,所以无法利用其内置的 BloomFilter 以优化点读性能,我们为每一个 SST 在 Flush 和 Compaction 的过程中手工生成一个 BloomFilter 存储在其 TableProperty 中,并关闭了内置的 BloomFilter 以节省空间。在查询时利用 TableFilter 功能,查找到 SST 对应的手工生成 BloomFilter 进行判断,以优化点读的性能。
2.3.2 热点写入优化
因为我们使用了 Raft 作为副本复制协议,而 Raft 的 Apply 流程是串行的,当出现写入热点时需要通过热点 Tablet 分裂来扩展性能。因为我们的分裂合并操作相对比较重,热点分裂的决策并不适合过于实时和敏感,为了扩展单个 Tablet 的写入性能,我们实现了一种新型的 RocksDB MemTable,写入时仅写入队列中实现了 O(1) 复杂度的在线写入,靠后台线程池将数据并发的写入实际的 SkipList 中,在读取的时候使用 ReadIndex 的机制进行等待。将单线程的最大承载能力扩展到单机的最大承载能力。
2.3.3 写入反压优化
当单个 Tablet 写入过快时,由于硬件资源的略微差距总会有一个副本的速度赶不上其他副本,逐渐累积引起慢副本重装快照。当出现这种情况的时候,如果速度快的两个副本有一个副本机器 Down 机,就会出现这个 Tablet 的短期不可写的情况(其中一个副本正在重装快照)。为了避免这种情况,我们会在一定的条件下进行慢节点反压,限制整体的写入速度,防止慢副本落后过多,实现了极限情况下的可用性提升。此外,我们会设定一定的限制避免磁盘降速故障引起的慢节点反压。
2.4 分布式事务
目前有些业务场景下存在分布式事务的使用需求,我们团队按照 Percolator 的事务模型,在 Bytable 上层实现了一套分布式事务解决方案,相关内容将在后续专题文章中详细描述。
3. Bytable2.0 追求极致的第二代表格存储系统
=============================
随着 Bytable1.0 的上线与稳定,业务对表格存储系统的成本、稳定性和性能都有了更高的要求。从成本角度来考虑,目前使用三副本方式来存储数据相比分布式文件系统的 EC(Erasure Code) 方案需要多消耗将近一倍的存储空间,此外目前存在三副本独立 Compaction 的情况多消耗了两倍的 CPU。从资源利用率的角度来考虑,目前存在读写请求和磁盘空间占用不匹配的情况,会出现 CPU 资源剩余但磁盘空间用尽或者 CPU 资源用尽但磁盘空间剩余的情况。从与离线 Hadoop 生态系统打通的角度来看,现在做备份、导出和数据加载都比较麻烦。从稳定性的角度来考虑,目前在分裂与合并的过程中仍然存在一定的延时抖动,我们也希望将尾延时优化到极致。从运维复杂度的角度来考虑,基于分布式文件系统可以将我们的服务无状态化,结合 K8S 的调度技术,我们不再需要考虑机器和磁盘的故障报修和重新上线,将极大地降低我们的运维成本。因此设计和实现基于共享存储的分布式表格存储系统势在必行。
3.1 技术选型
与 Bytable1.0 设计目标仅仅是希望满足当前业务需求不同的是,我们希望可以在更大的范围内寻求最优解,构建世界领先的分布式表格存储系统。随着字节跳动分布式文件存储系统逐渐向在线模式演进,我们拥有了可供在线使用的分布式文件存储系统 ByteStore。此外字节跳动还研发了使用 Quorum 协议的分布式日志存储系统 ByteJournal ,它拥有类似 Paxos 的日志乱序复制和提交的特性以尽可能的降低延时。此外 ByteJournal 还能提供总共 5 副本写入 2 副本成功即可提交,但需要 4 副本 Recover 的高级特性,以提供比 Paxos 协议更加极致的尾延时优化。这一次我们选择站在巨人的肩膀上,使用 ByteStore 存储引擎文件,使用 ByteJournal 管理复制日志,依赖这两个分布式存储系统实现基于共享存储的第二代表格存储系统 Bytable2.0。此外,国际化业务也拥有全球一致的表格存储需求,并希望可以细粒度的设置和变更部分数据的复制配置,借此控制对应数据在访问时的读写延迟(通过访问数据时的距离)。
3.2 系统架构
在 Bytable2.0 的系统设计中借鉴了 Google 第二代分布式表格存储系统 Spanner 的设计思路。在本节中我们将介绍 Bytable2.0 的系统架构,如下图所示我们将 Bytable2.0 划分为数据读写层(TabletServer)、全局管理层(GlobalMaster),计算调度层(GroupMaster)和数据调度层(PlacementDriver)。
Bytable2.0 与 Bytable1.0 的主要不同有如下几处:
-
与 Bytable1.0 中将 Tablet 分布信息存储在 Master 中不同,Bytable2.0 为每一张表都会建立一个对应的 MetaTable 存储在 TabletServer 中。这样做一个好处是可以为每一个表的 Tablet 分布信息访问做好隔离,另一个好处是如果 MetaTable 成为瓶颈可以在以后的实现中加入 RootTable 使其可分裂。
-
与 Bytable1.0 中一个 Tablet 即对应一个复制组不同,Bytable2.0 中一个复制组中会包含多个 Tablet。最终表现为一个 TabletServer 拥有多个 ReplicationGroup 的某一 Replica (Replica 是 ReplicationGroup 的一个副本),一个 ReplicationGroup 拥有多个 Tablet。这样做的好处是允许将多个不连续 KeyRange 的数据放置在同一个 ReplicationGroup 中,以方便极细粒度的分区,并允许不连续 KeyRange 的数据进行单 ReplicationGroup 的局部事务处理。将 ReplicationGroup 的复制能力和 KeyRange 的切分解耦,即使 KeyRange 的切分非常多依然可以使 ReplicationGroup 的数量保持收敛。
-
与 Bytable1.0 中仅有一个 Master 不同,Bytable2.0 引入了 GlobalMaster 和 GroupMaster 两个组件。GlobalMaster 负责记录所有 Table 和 ReplicationGroup 的元信息。GroupMaster 不断同步 GlobalMaster 管理的元信息,在本地冗余保存,它只管理自己对应 Region 内 TabletServer 实例的探活与 Replica 分配,实现了 Region 内部的自治,去除了 Region 间网络状况对 Region 内部可用性的影响。
Bytable2.0 与 HBase 的主要不同之处有如下几处:
-
HBase 仅支持同步或异步的主从复制,读取时仅保证集群内一致不保证集群间一致。而 Bytable 2.0 可以支持跨 Region 的 Quorum 数据复制,保证全球一致。
-
HBase 中 Region 和 KeyRange 的映射关系是一一映射,因此如果希望细粒度的设置 KeyRange 的复制关系则会创建大量的小 Region,而这对 HBase 则是不友好的。而 Bytable 2.0 可以支持细粒度的 Tablet 数据复制关系设置。
Client 读写数据的时候会首先跟 GroupMaster 通信获得要访问数据对应表的 MetaTable 对应的 ReplicationGroup 各个 Replica 的位置信息,然后请求对应的 MetaTable 从中定位对应的 Tablet 所属 ReplicationGroupId,然后根据其去 GroupMaster 查询对应 ReplicationGroup 各个 Replica 的位置信息,最终根据此位置信息找到对应的 TabletServer 进行读写。
Bytable2.0 Global架构图
在单机房部署的场景下,上面的架构就显得过于臃肿,因为我们实现时模块化做的足够好,所以可以将 GlobalMaster, GroupMaster 和 PlacementDriver 三个模块编译到同一个 Master 二进制文件中,以降低部署和维护的复杂度,如下图所示,部署时一个集群中可以仅拥有 Master 和 TabletServer 两种服务。
Bytable2.0 精简部署
3.2.1 数据读写层 TabletServer
与 Bytable1.0 中 ReplicationGroup 与 Tablet 的一一对应关系不同, Bytable2.0 的一个 TabletServer 中包含若干 ReplicationGroup 的 Replica,每一个 ReplicationGroup 中包含了若干 Tablet。这样的设计可以使 Tablet 的分裂与合并变得非常轻量,仅仅是修改元数据,不需要任何停顿。在这种设计下迁移不再是将一个 Tablet 从一个 TabletServer 迁往另外一个 TabletServer,而是从一个 ReplicationGroup 将这个 Tablet 的对应数据导入另外一个 ReplicationGroup,我们使用 SST 文件 Range 抽取的方式轻量地完成对应的工作。
在写入的流程中 Leader Replica 首先通过 ByteJournal 写入 WAL,当日志写入成功后写入 MemTable。Follower Replica 从 ByteJournal 中读取 WAL 并写入 MemTable。Leader Replica 定期进行 Checkpoint 和 Compaction 操作,将 SST 文件写入 ByteStore 中。在 Leader Replica 和 Follower Replica 共享分布式文件系统的时候,仅仅 Leader Replica 进行 Checkpoint 和 Compaction 操作。当 Leader Replica 和 Follower Replica 不共享分布式文件系统时,则在每一个分布式文件系统上都会选出一个 Compaction Leader 分别进行 Checkpoint 和 Compaction 操作。这样我们就解决了之前多副本分别 Compaction 引入的额外 CPU 损耗,于此同时我们也可以拥有 Follwer Replica 解决了早期 HBase 版本存在的没有主从冗余的问题。
在读取流程中,Leader Replica 和 Follower Replica 都从对应的 ByteStore 中将 SST 数据读取出来与内存中的 MemTable 归并最后返回给用户,其中 Follwer Replica 可以指定版本进行读取,也可以使用 ReadIndex 的方式从 Leader Replica 获取最新的日志号并等待其在本地 Apply 后进行读取。
3.2.2 全局管理层 GlobalMaster
GlobalMaster 是整个集群全局的管理模块,负责对运维人员暴露操作接口,主要负责表和 ColumnFamily 的创建和删除。其中存储了所有表和 ColumnFamily 的元信息,同时保存了每个表包含的所有 ReplicationGroup 的元信息。GroupMaster 从 GlobalMaster 同步这些元信息,以便获取需要其调度的 Replica,以便管理 ReplicationGroup 在对应 Region 内的副本放置。
3.2.3 计算调度层 GroupMaster
GroupMaster 是某个 Region 内的管理模块,管理 Region 内多个 TabletServer 实例和各个 ReplicationGroup 在本 Region 内分配的 Replica。除了注册到这个 GroupMaster 的多个 TabletServer 的心跳与保活的工作,它还要根据从 GlobalMaster 同步的元信息中得出需要其调度的 Replica 信息,在注册到这个 GroupMaster 的多个 TabletServer 上进行调度,告知 TabletServer 打开或关闭对应的 Replica。
3.2.4 数据调度层 PlacementDriver
PlacementDriver 是进行数据调度的决策模块,其会和 TabletServer 通信,收集各个 TabletServer 的负载信息并扫描各个表对应的 MetaTablet,进行负载均衡计算,最终进行决策需要是否需要对某些 Tablet 进行分裂、合并或迁移操作。
3.3 未来展望
3.3.1 离线 Compaction
Compaction 操作和流式的数据读写相比,其实是一个 Batch 类型的离线操作,而这个离线作业跑在在线服务中,往往会降低在线服务的有效资源利用率和 Qos。所以,我们计划允许将这个 Compaction 过程的执行递交给 Yarn 或其他离线作业运行平台,以降低其对在线服务 CPU 的消耗。Aliyun X-Engine 团队使用的 FPGA 的方案,将本机的 Compaction CPU 负载 Offload 给 FPGA,也是利用类似的方式。不过其对特定机型和硬件依赖较重,可以考虑利用 Yarn 调度平台对 FPGA 资源进行调度的方式更加合理与充分对其资源进行利用。
3.3.2 分析型列存引擎
在 Spanner: Becoming a SQL system 的论文中提到,目前 Spanner 提供了一套块内列存的分析型引擎,在部分场景下取得了不错的效果。TiDB 也通过为 Raft 挂一个 ClickHouse (Yandex 开源的分析型数据) 从节点的方式提供了分析型查询的解决方案。Bytable2.0 也有一些分析型的使用场景,我们计划将来提供一套分析型列存的引擎,逐步发展为一个 HTAP 的系统。
3.3.3 多模数据库
目前数据库市场上拥有多种多样的 API 接口,比如 Redis, MongoDB,MySQL 等。与此同时,在开源市场中,图数据库 JanusGraph 、时序数据库 OpenTSDB 、地理信息数据库 GeoMesa、关系型数据库 Phoenix 等数据库底层都是基于 HBase 进行数据存储的。这给我们带来了一些启示,Bytable2.0 将来也可以作为通用的底层存储服务,在上层实现各种各样的 API 层,为这些 API 的服务提供大容量低成本的解决方案。
3.3.4 新型分布式事务机制探索
分布式事务在业界的实现中,往往需要在吞吐和延时中进行权衡。在 Bytable 的分布式事务解决方案中,使用了 Percolator 事务模型,其依赖了单点授时服务 TSO,在吞吐和延时之间做了一定权衡。在后续 Bytable2.0 的分布式事务方案中,我们希望进一步优化 Bytable1.0 分布式事务方案中 Percolator 模型的吞吐问题和跨 Region 延时问题,探索新的解决方案。
4. 总结
======
随着字节跳动搜索和推荐场景的飞速发展和业务需求的不断丰富,我们在前期快速的构建了第一代分布式表格存储系统 Bytable1.0,解决了大量的业务问题。但同时因为一期系统的简化和权衡,仍然存在一些需要优化的成本和扩展性等问题,我们在第二代类 Spanner 的表格存储系统 Bytable2.0 中解决这些问题。欢迎感兴趣的同学们加入表格存储团队打造极致的分布式表格存储解决方案,一起构建字节跳动坚实的基础设施,为公司的高速发展的保驾护航。
5. 参考文献
========
[1] Chang, Fay, et al. “Bigtable: A distributed storage system for structured data.” ACM Transactions on Computer Systems (TOCS) 26.2 (2008): 1-26.
[2] Apache HBase: An open-source, distributed, versioned, column-oriented store modeled after Google’ Bigtable.
[3] TiDB: An open source distributed HTAP database compatible with the MySQL protocol.
[4] Taft, Rebecca, et al. “CockroachDB: The Resilient Geo-Distributed SQL Database.” Proceedings of the 2020 ACM SIGMOD International Conference on Management of Data. 2020.
[5] Dong, Siying, et al. “Optimizing Space Amplification in RocksDB.” CIDR. Vol. 3. 2017.
[6] Corbett, James C., et al. “Spanner: Google’s globally distributed database.” ACM Transactions on Computer Systems (TOCS) 31.3 (2013): 1-22.
[7] Bacon, David F., et al. “Spanner: Becoming a SQL system.” Proceedings of the 2017 ACM International Conference on Management of Data. 2017.
[8] Huang, Gui, et al. “X-Engine: An optimized storage engine for large-scale E-commerce transaction processing.” Proceedings of the 2019 International Conference on Management of Data. 2019.
更多分享
====
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
片转存中…(img-vr65R7d2-1715891325382)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!