技术开发 频道

淘宝海量数据库OceanBase:系统架构详解

        【IT168 技术】无论从数据量还是访问量,OceanBase不再能够是一个单机系统,即使一台单机能服务高达几个TB的数据、提供几万QPS的服务能力,因此,分布式系统不可避免,然而,内部如何实现拆表(拆库)以及如何实现数据库的事务,成为了一个很大的挑战和十分艰难的抉择:

  相关文章:

  淘宝海量数据库之一:来自业务的挑战

  淘宝海量数据库之二:一致性选择

        淘宝海量数据库之三:事务的ACID

  一种选择是当前数据库的常用的水平拆库,淘宝在这方面已经有很多实践。通常的做法是对主键进行hash或者取模(其实是一种特殊的hash),把数据分布到不同的DB服务器上,客户端通过路由或规则访问特定的数据库,将整个系统的数据和访问负载分散到多台服务器上,降低了单台机器的负载压力。但这种做法存在一些弊端:

  第一, 数据和负载增加后添加机器的操作比较复杂;

  第二, 许多跨行/跨表的修改通常涉及到多台机器,难以支持事务;

  第三, 有些范围查询需要访问几乎所有机器;

  第四, RDBMS单机数据量小(例如许多情况下MySQL单机支撑200GB左右的数据时会有较好的性能),可能消耗较大的机器资源;

  最关键的是,这种方法早在多年前就被几乎所有关系数据库厂商采用并积累了丰富的经验,而OceanBase项目团队没有任何理由做得更好。

  还有一种选择分布式B+树(类似于BigTable和HBase),按主键的范围动态拆库,即把整个表看成主键的B+树,每个叶子节点(大约两百多MB)对应一个连续的主键范围,叶子节点可能因为修改删除等变得太大或太小从而进行分裂或者合并,容错、故障恢复以及负载平衡等都以叶子节点为单位(关于BigTable的更多信息可参加另外一篇博客:云计算之分布式表格系统或者BigTable论文原文:“Bigtable: A Distributed Storage System for Structured Data”)。

  这种架构的好处是系统易于扩展:简单地增加机器就可以,并且少量突发的机器故障对使用者甚至是透明的,负载平衡也比前一种方案更好,范围查询很容易实现且高效。

  然而,这个架构最大的困难是事务的实现,因为BigTable只有单行事务,而OceanBase需要跨行跨表的事务。这个问题困扰了项目团队不短的时间才得到解决(参见“系统架构(二)”)。理论分析和代码实现都表明这个方法非常地简单、高效。

  后来有机会拜读了Google的关于分布式事务的文章(“Large-scale Incremental Processing Using Distributed Transactions and Notifications”),感受了其优秀的设计,也体会了它的复杂度,同时也发现,虽然它通过使用15000个CPU核达到了创纪录的11200 tps (TPC-E benchmark),但它的平均事务响应时间为2s-5s,并不符合淘宝业务的平均几毫秒~几十毫秒的响应时间的需求,而且开发一个类似的系统及其底层BigTable和GFS等系统所需要的时间人力物力和技术挑战也是巨大的。(关于Google的分布式事务,欢迎感兴趣的朋友访问一个友人的wiki:http://nosql-wiki.org/wiki/bin/view/Main/GoogleDistributedTransactions)

  就像上面提到的,只有分布式架构才能支撑当前和未来越来越庞大的数据量和访问量,同时OceanBase还必须支持跨行跨表事务,看起来OceanBase似乎需要实现分布式事务。

  然而,分布式事务不仅实现复杂,更重要的是它尚未在工业界得到广泛应用,其效率和性能等还有待更多生产实践的检验。

  仔细分析诸多业务发现,尽快很多数据库系统数据量十分庞大,例如几十亿、几百亿条甚至更多,但一段时间(例如一天)的修改量并不大,通常不超过几千万条到几亿条,因此OceanBase决定使用单台服务器(称为UpdateServer)来记录这段时间(例如一天)的修改增量,并以内存表(memtable)为主,SSD(固态盘)为辅。修改增量之外的、在此段时间内保持不变的数据称为基线数据。基线数据以类似于分布式文件系统的方式存储于多台服务器(称为ChunkServer)上,每次查询都由MergerServer把ChunkServer上的基线数据和UpdateServer上的增量数据融合后返回给调用者。这样写事务集中在UpdateServer进行,读事务分散在多台服务器上,既实现了跨行跨表事务、避免了复杂的分布式写事务,又有较好的扩展性。

淘宝海量数据库OceanBase:系统架构详解

  UpdateServer开始总是以内存表(memtable)方式记录修改,如果内存表(memtable)达到一定阈值,UpdateServer就冻结当前内存表并同时开启新的内存表,之后的修改写入新的内存表。冻结内存表不再接受写入并被转换成一种紧凑格式保存到SSD盘,转换完成后,冻结内存表的内存即可回收。

  OceanBase内部使用主键(类似于经典关系数据库的聚集索引)对表中数据进行排序和存储,主键由若干列组成并具有唯一性。在OceanBase内部,基线数据按主键排序并划分成数据量大致相等的块,称为tablet。Tablet的缺省大小是256MB(可配置)并存储在ChunkServer上,为了避免ChunkServer故障导致数据丢失,tablet通常保存2~3个副本(可配置)。

淘宝海量数据库OceanBase:系统架构详解

  OceanBase每隔一段时间(例如一天)会把这段时间的修改增量合并到原有基线数据并生成新的基线数据(称为每日合并),然后清除UpdateServer中过期的修改增量和ChunkServer上过期的基线数据。合并开始时,UpdateServer会冻结当前内存表并开启新的内存表,此后新的修改将写入新的内存表,ChunkServer则把当前的基线数据与冻结的内存表融合并生成新的基线数据,当所有tablet的新的基线数据都生成后,UpdateServer冻结的内存表即可释放,其所占内存也被回收。为了降低每日合并对用户访问OceanBase的影响,每日合并被设置成低优先级任务,当机器负载(例如CPU load和iowait等)高于一定阈值时,合并速度会减慢甚至暂停。在实际应用中,数据库管理员(DBA)通常把每日合并时间设定在业务的低峰期(例如后半夜),这样每日合并对用户基本没有什么影响。

0
相关文章