kudu master design

The Catalog Manager and System Tables

Catalog Manager 监听用户创建的kudu表和tablet。

所有table和tablet的元数据信息以写入时复制(copy-on-write)的objects形式存储在内存和磁盘里,kudu系统的sys.catalog信息只存储在master节点上,它在master启动时被加载进内存。在写这篇设计文档时,为了保证元数据的强一致性,sys.catalog仅仅存在一个tablet中(当前版本,一个tablet有自己独立的catalog)。

增加或者修改table/tablet时,master先写入磁盘,完成后才会提交到内存。这保证了client访问内存table/tablet状态的一致性。我的理解是,创建或者修改表时,内存先提交,如果底层磁盘还有没有flush,client访问时却能拿到table/tablet的信息,就会出现不一致问题,因为此时table/tablet还未能提供正确的服务。所以必须保证磁盘先正常提交,完成后再刷新到内存中。

这种设计避免了tablet寻址服务更耗性能的全局扫描的问题,并且保证了每个table/tablet具备平稳的状态。

Catalog Manager在sys table中为查询元数据信息维护了三个hash-map:

  • [Table Id] -> TableInfo
  • [Table Name] -> TableInfo
  • [Tablet Id] -> TableInfo

TableInfo里也维护了一个map,存储了[table-start-key] -> TableInfo信息,为用户提供了根据key-range查找tablets地址服务。

Table Creation

如下步骤与CatalogManager::CreateTable()方法是一致的:

  1. Client向Master提交请求,请求信息有:创建表table x,N个tablets,表结构
  2. Master的CatalogManager::CreateTable()方法:
    • 验证请求准确性,例如验证表结构是否准确
    • 确定表名是否已经被占用
    • 在内存中创建TableInfo,并标注preparing状态
    • 在内存中,根据用户提供的表结构信息,创建TableInfo的pre-split-keys域信息,此时TableInfo同样也是preparing状态
    • 写入tablets信息进入sys.catalog(如果写入失败,这个Master线程会被killed)
      • master开始写入disk
      • 如果此时正好master crashes或者restarts,当master再次恢复时,表不会存在
      • 表信息写入sys.catalog,并标注running状态
      • master写入disk完成
      • 此后,master即使crashes或者重启,表依然存在。接着会提交running状态到内存,然后client才能访问到这个表。
  3. Master返回给client信息:已经创建,或者创建失败信息

经过如上步骤后,表就创建好了,集群shutdown,重启后表会依然存在。不过表的tablets还没有创建,见下边的Table Assignment章节。

Table Deletion

当用户提交一个DetleTable T的请求,表T在sys.catalog信息表中会被标注为deleted,从master的内存 table names列表中移除,同时,master内存的TableInfo/TableInfo该表的状态也被标注为deleted。

此时,外部通过master rpc对这个表不可见,但表T的tablet configs依然运行着。新的client open 表T,会报找不到表的异常,然而之前缓存了tablet地址信息的client,依然可以读写table configs,只要tablet servers运行正常,且tablets没被delete。在某种情况下,类似于文件系统的软连接。

Master将会异步的发送一个DeleteTablet RPC请求给每个tablet(config的中每个tablet server中的tablet一个RPC请求,config的概念参见下文)。然后tablets会被detele掉,互不干涉的且没有先后顺序的。如果master或者tablet server在一个成功执行的DeleteTablet操作之前下线了,master下次接收到这个需要被delete的tablet的心跳后,master会发送一个新的DeleteTablet的请求。

A config in Kudu is a fault-tolerant, consistent unit that serves requests for a single tablet. As long as there are 2f+1 participants available in a config, where f is the number of possibly faulty participants, the config will keep serving requests for its tablet and it is guaranteed that clients perceive a fully consistent, linearizable view of both data and operations on that data. The f parameter, defined table wide through configuration implicitly defines the size of the config, f=0 indicates a single node config, f=1 indicates a 3 node config, f=2 indicates a 5 node config, etc.. Quorums may overlap in the sense that each physical machine may be participating in multiple configs, usually one per each tablet that it serves.

以后(TODO),一个独立的cleaner线程会负责删除table/tablet的on-disk和in-memory数据。

Table Assignment(Tablet Creation)

当表创建后,需要在一组副本上创建tablets。为了实现它,master需要选择副本,并与tablet结合,即将副本指定给某一个tablet。

我们发送创建tablet请求,选择了一组副本,且选择了leader,并不代表着这个tablet已经创建好了。接下来,tablet server如果接收到leader的tablet created心跳,我们就可认为这个tablet是running状态。如果超出了timeout时间(ASSIGNMENT-TIMEOUT-MSEC)没有接收到tablet created报告,master会替换掉这个tablet,步骤与上诉的一样。

这个分配任务是被CatalogManagerBgTasks线程执行的。这个线程主要负责两个事:

  • 创建表(分配新的tablet)
  • 超时时再次分配(部分tablet超时了,需要替换)

具体的步骤如下:
CatalogManagerBgTasks thread:

  1. 处理Pending Assignments:
    循环每个即将要分配tablet任务:
      如果已经提交了创建tablet的请求:
        如果没有接收到响应,且配置的超时时间已经超过了,就标记这个tablet为replaced:
          a.删除这个tablet
          b.创建一个新的tablet替代如上tablet,把创建tablet加入到create tablet的list中
      如果tablet是新的,即刚刚被CreateTable创建且是preparing状态
        将这个tablet加入到create tablet的list中
    循环create tablet list里的每个tablet:
      选择一组tablet server,在tablet config里
      选择一个tablet server成为初始化config的leader,此时[BEGIN-WRITE-TO-DISK]
      sys.cagalog中标注creating,如果这里失败了,Pending Assignments会重新创建这个tablet。[END-WRITE-TO-DISK]
      循环第一步中选择的那一组tablet server:
        发送一个异步的CreateTablet RPC请求,给tablet server。由于tablertserver的心跳,master会接收到tablet createion的通知
    提交tablet的状态变化到内存,此时client可以看到tablet是”running”状态

  2. 清理删除掉的table和tablet(应该还没实现)
    从sys.catalog中移除已经标注为deleted的tables/tablets
    从内存的map中移除已经标注为deleted的tables/tablets

如上都是Catalog Manger的工作,而当TS(tablet server简称TS,下文雷同)接收到一个CreateTablet RPC请求时,TS会本地创建一个tablet副本。一旦成功创建了,会被加入到下一个tablet的report中。接着,调用master端的ProcessTabletReport方法。

如果此时master找到tablet状态是creating,并且TS report此tablet在分配过程中被选举为leader(CatalogManagerBgTasks过程后),这个tablet会被标记为running,并且提交到disk,结束这个tablet分配任务。

Heatbeats and TSManager

TS会发送Heartbeats给master,心跳包含如下信息:

  1. 节点实例信息:TS永久的uuid,节点顺序number
  2. (可选的)注册。TS启动或者先前master响应TS需要needs register
  3. (可选的)tablet report。当tablet的信息被改变了,或者先前master要求TS返回一个完整的tablet信息。

Hadling heartbeats

master接收到一个TS的heartbeat后:

  1. 判断是否是registration的心跳。如果是,TSManager登记这个TS实例
  2. 从TSManager中获取TSDescriptor,如果TSDescriptor找不到,则告知这个TS需要重新注册
  3. 更新心跳时间,在registration对象里
  4. 如果心跳含有tablet report信息,catalog manger会处理这个report并且更新mem cache,以及系统表(sys.catalog)。如果没有tablet report信息,master会向TS索取一个tablet report
  5. 发送一个成功响应给TS

TSManager

TSManagert在内存中存储着TS发送给master的信息(所有的TS信息,心跳信息和tablet reports等等),信息存储在map中,key是TS的永久UUID,而value指向的是这个TS的TSDescriptor。

参考

源文档:kudu master design

你可能感兴趣的:(kudu)