无论是信息量还是浏览量,OceanBase都不能再是单机系统,即使单机可以服务数字TB的数据,提供数万QPS的服务能力,分布式结构也是不可避免的。然而,实现内部表反汇编(数据库反汇编)和海量数据库交易是一个巨大的挑战,也是一个非常困难的选择:
一种选择是目前数据库中常见的横向拆解,淘宝在这方面做了很多实践。一般来说,主键是哈希或模型计算(实际上是一个特殊的哈希),数据分布在不同的DB服务器上,客户端通过路由或规则浏览特定的数据库,将整个系统的数据和访问负荷分布在多个服务器上,从而减轻单个机器的负荷压力。然而,这种方法存在一些缺陷:
第一,加机操作在数据和负载增加后复杂;
第二,很多跨行/跨表修改一般涉及多台机器,难以支持事务;
第三,有些范围的查询需要浏览绝大多数机器;
第四,单一的RDBMS信息量较小(例如,当MySQL在许多情况下支持200GB左右的数据时,它可能会消耗大量的机器资源;
很重要的是,这种方法在许多年前就被大多数relationships海量数据库制造商选择并积累了丰富的经验,而OceanBase项目组却没有理由做得更好。
还有分布式B树木(类似于BigTable和HBase),根据主键的类别动态拆分数据库,即将整个表格看作是一个主键B树木,每个叶节点(约200MB)对应一个连续的主键范围。由于修改、删除等原因,叶节点可能会变得过大或过小。以及拆分或合并。叶节点周围包括容错、故障恢复和负载平衡(更多关于Bigtable的信息,请参考另一个博客:云计算分布式表系统或BigTable论文:《BigTable:结构化数据的分布式存储系统)。
这种结构的优点是系统容易扩展:只需添加机器,少数突发机器故障甚至对用户透明。负载平衡优于之前的方案,范围查询容易实现,效率高。
然而,这种结构最大的困难在于事项的实现,因为BigTable只有单行事务,而OceanBase需要跨行跨表事务。项目组花了很长时间来解决这个问题(参考“系统结构(2)”)。这种方法简单高效地解释了理论分析和代码实现。
之后有机会看了谷歌关于分布式事务的文章(《使用分布式事务和通知的大规模增量处理》),感受到了它出色的设计和复杂性。与此同时,我也发现,尽管11200tps使用了15000个CPU核来实现创纪录(TPC-E标准),但其平均事务响应时间为2s-5s,不符合淘宝平均响应时间为几ms至几十毫秒的需要。另外,开发类似的系统及其底层BigTable和GFS系统所需的时间、人力、物力和技术挑战是巨大的。
如上所述,只有分布式结构才能支持当前和未来信息量和浏览量的不断增加。与此同时,OceanBase还必须支持跨行和跨表交易。看起来OceanBase需要实现分布式事务。
但是,分布式事务不仅实现了复杂性,而且在行业内还没有得到广泛的应用,其效率和性能需要更多的生产实践来验证。
对许多业务进行了仔细的分析,发现海量数据库system的数据量非常大,比如几十亿、几百亿甚至更多,但是某一段时间(比如一天)的修改量并不大,一般不超过几千万到几亿。所以OceanBase决定使用单个服务器(称为UpdateServer)来记录这个时间(比如一天)中的修改增量,主要是内存memtable。在此期间,超过增量并保持一致的数据称为基线数据。MergerServer为每个查询结合ChunkServer上的基线数据和UpdateServer上的增量数据,将基线数据以类似于分布式文件系统的方式存储在多个服务器(称为ChunkServer)上,并将其返回给调用者。通过这种方式,写作事务集中在UpdateServer上,阅读事务分散在多个服务器上,既实现了跨行、跨表事务,又避免了复杂的分布式写作事务,具有良好的可扩展性。
首先,UpdateServer总是以内存表的形式记录变化。如果内存表达到一定的阀值,UpdateServer将当前的内存表冻结,同时打开一个新的内存表,后续的变化将被写入一个新的内存表。冻结的内存表不再被写入,而是转换成紧凑的格式,保存在SSD硬盘中。转换后,可以回收冻结内存表的内存。
OceanBase使用主键(类似于经典关系数据库的聚集索引)对表中的数据进行排序和存储。主键由几列组成,而且是唯一的。在OceanBase中,基线数据按主键排序,分为信息量大致相等的块,称为tablet。默认情况下,平板电脑的大小为256MB(可配置),存储在ChunkServer上。为防止ChunkServer故障导致内容丢失,平板电脑通常会保留2~3份副本(可配置)。
OceanBase每隔一段时间(比如一天)就会将这段时间内的修改增量合并到原来的基线数据中,生成新的基线数据(称为每日合并),然后在UpdateServer中清除过期修改增量和ChunkServer上过期基线数据。UpdateServer在合并之初将当前的内存表冻结,并打开新的内存表。之后,新的修改将被写入新的内存表。ChunkServer将当前的基线数据与冻结的内存表结合起来,生成新的基线数据。UpdateServer冻结的内存表将在所有新的平板电脑基线数据生成后被释放,其内存将被恢复。为减少每日合并对用户访问OceanBase的影响,每日合并被设定为低优先级任务。如CPU负荷和iowait等机器负荷。)如果高于某一阀值,合并速度将变慢甚至暂停。在实际应用中,海量数据库DBA通常在业务的低峰期(如午夜后)设定日常合并时间,因此日常合并对用户的影响很小。