当前位置: 首页 > 科技观察

比较通俗易懂的HBase架构完整讲解,10分钟内学会,推荐给

时间:2023-03-19 20:22:38 科技观察

加入书签。依旧是Hadoop组件的讲解。今天说到HBase的架构,都是一个字一个字打出来的。希望大家转发关注。我会一直给大家写优质的内容。从物理上讲,Hbase是一种主从架构,由三类服务器组成:RegionServer负责处理数据读写请求,客户端在请求数据时直接与RegionServer交互。HBaseMaster负责Region分配、DDL(创建、删除表)等操作。Zookeeper作为HDFS的一部分,负责维护集群状态。当然底层存储是基于HadoopHDFS的:HadoopDataNode负责存储RegionServer管理的数据。所有HBase数据都存储在HDFS文件中。RegionServer和HDFSDataNode往往分布在一起,这样RegionServer就可以实现数据本地化(datalocality,即将数据尽可能靠近需要的地方)。HBase的数据写入的时候是本地的,但是当region迁移的时候,数据可能不再满足locality,需要compaction完成才能恢复到本地。HadoopNameNode维护着所有HDFS物理数据块的元信息。RegionsHBase表(Table)根据rowkey的范围水平拆分成若干region。每个区域包含区域的开始键和结束键之间的所有行。Region被分配给集群中的一些节点进行管理,即RegionServers,负责处理数据的读写请求。每个RegionServer可以管理大约1000个区域。HBaseMaster,也叫HMaster,负责Region的分配、DDL(创建、删除表)等操作:统筹所有RegionServer:启动时的Region分配、故障恢复时的Region重分配和负载均衡监控集群中所有RegionServer实例的(从Zookeeper获取通知信息)Administrator功能:提供创建、删除和更新HBase表的接口ZookeeperHBase使用Zookeeper作为分布式管理服务维护集群中所有服务的状态。Zookeeper维护哪些服务器健康且可用,并在服务器出现故障时发出通知。Zookeeper使用共识协议来保证分布式状态的一致性。注意这需要三五台机器来做共识协议。这些组件如何协同工作Zookeeper用于协调分布式系统中集群状态信息的共享。RegionServers维护与在线HMaster(活动的HMaster)和Zookeeper的会话。Zookeeper通过心跳检测来维护所有的临时节点。每个区域服务器创建一个临时节点。HMaster将监视这些节点以发现可用的RegionServer,它还将监视这些节点的故障。HMasters将竞争创建临时节点,Zookeeper决定谁是第一个在线的HMaster,确保只有一个HMaster在线。在线的HMaster(activeHMaster)会向Zookeeper发送心跳,离线的standbyHMaster(inactiveHMaster)会监控activeHMaster可能出现的故障,随时准备接管。如果某个RegionServer或HMaster由于各种原因失败或无法发送心跳,它们与Zookeeper的会话将过期,ephemeral节点将被删除并下线,监听者将收到此消息。ActiveHMaster监听regionserver掉线的消息,然后恢复故障的regionserver及其负责的region数据。InactiveHMaster关心activeHMaster下线的消息,然后竞争成为activeHMaster。点评:这段很重要,涉及到分布式系统设计中的一些核心概念,包括集群状态、一致性等,可见Zookeeper是沟通万物的桥梁。所有参与者与Zookeeper保持心跳会话,并从Zookeeper获取他们需要的集群状态信息,以管理其他节点和切换角色。这在分布式系统设计中也是非常重要的。这个想法是通过专门的服务来维护分布式集群状态信息。第一个读写操作有一个特殊的HBaseCatalog表,叫做Meta表(其实就是一个特殊的HBase表),里面包含了集群中所有region的位置信息。Zookeeper保存了这个Meta表的位置。当第一个HBase读写操作到来时:客户端从Zookeeper获取由哪个RegionServer负责管理Meta表。客户端会去查询管理Meta表的RegionServer,然后得知是哪个RegionServer负责管理这个数据请求所需要的rowkey。客户端缓存此信息,以及元表位置信息本身。然后client再回去访问那个RegionServer获取数据。对于以后的读请求,客户端可以直接从缓存中获取Meta表的位置信息(在哪个RegionServer上)和之前访问过的rowkey的位置信息(在哪个RegionServer上),除非因为Region被迁移,缓存无效。此时,客户端会重复上述步骤,重新获取相关位置信息,并更新缓存。点评:客户端读写数据,其实分两步:第一步从Meta表中定位,rowkey属于哪个RegionServer管理;第二步,去对应的RegionServer读写数据。这里涉及到两个RegionServer,各自的作用功能一定要搞清楚。关于Metatable下面会详细介绍。HBaseMetaTableMeta表是一张特殊的HBase表,存储了系统中所有的region列表。这张表类似于b树,其结构大致如下:Key:表,region起始键,regionidValue:regionserverRegionServer由RegionServer组成。它运行在HDFSDataNode上,由以下组件组成:WAL:WriteAheadLog分布式文件系统上的一个文件,用于存储尚未持久化的新数据。它用于故障恢复。BlockCache:这是一种读取缓存,将最常访问的数据存储在内存中,是一种LRU(最近最少使用)缓存。MemStore:这是写缓存,将新的数据存储在内存中,还没有持久化到硬盘。写入磁盘时,首先对数据进行排序。请注意,每个Region中的每个ColumnFamily都会有一个MemStore。HFile将HBase数据以有序的KeyValue形式存储在硬盘(HDFS)上。点评:这段是最重要的。理解RegionServer的组成对于理解HBase的架构至关重要。需要充分了解RegionServer的功能和各个组件的作用。这些组件的行为和功能在后面的段落中都会一一展开。HBase写数据步骤当客户端发起写数据请求(Put操作)时,第一步是将数据写入WAL:新数据会追加到WAL文件的末尾。WAL用于恢复故障转移期间未持久化的数据。数据写入WAL后,会添加到MemStore写缓存中。然后服务端可以向客户端返回ack,表示写入数据完成。点评:写入数据时注意WAL和MemStore的更新顺序,不能互换,WAL必须在MemStore之后。反之,如果先更新MemStore,此时RegionServercrash,内存中的更新丢失。此时数据还没有持久化到WAL中,所以无法恢复。理论上,WAL是MemStore中数据的镜像,应该是一致的,除非发生系统崩溃。另请注意,更新WAL附加在文件末尾。这种磁盘操作性能高,不会过多影响请求的整体响应时间。HBaseMemStoreMemStore将HBase数据更新以有序KeyValues的形式缓存在内存中,与HFile中的存储形式相同。每个ColumnFamily都有一个MemStore,所有的更新都按照ColumnFamily排序。在HBaseRegionFlushMemStore中积累了足够的数据后,整个有序数据集将被写入HDFS上的一个新的HFile文件中。HBase为每一个ColumnFamily创建一个HFile,里面存放着具体的Cell,也就是KeyValue数据。随着时间的推移,HFile会不断生成,因为KeyValue会不断从MemStore刷到硬盘。注意,这也是HBase限制ColumnFamily数量的原因之一。每个ColumnFamily都有一个MemStore;如果一个MemStore已满,则所有MemStore将被刷新到硬盘。同时,它还会记录最后一次写入数据的最大序号(sequencenumber),以便系统知道哪些数据被持久化到现在。最大序列号是一条元信息,存储在每个HFile中,表示哪条数据已经被持久化,应该从哪里继续。区域启动时,会读取这些序号,取其中最大的作为基序号。后续新的数据更新会在这个值的基础上递增,生成新的序列号。点评:这里有个序号的概念。HBase数据每次更新,都会绑定一个新的自增序号。并且每个HFile都会存储它保存的数据的最大序号。这个元信息非常重要。相当于一个commitpoint,告诉我们这个序号之前的数据已经持久化到硬盘了。它不仅在region启动时使用,还告诉我们故障恢复时在WAL中的什么位置开始回放数据的历史更新记录。HBaseHFile数据以Key/Value的形式存储在HFile中。当MemStore积累了足够多的数据后,整个有序的数据集就会被写入到HDFS上一个新的HFile文件中。整个过程是顺序写操作,速度非常快,因为不需要移动磁头。(注意HDFS不支持随机文件修改操作,但支持追加操作。)HBaseHFile文件结构HFile使用多层索引查询数据,无需读取整个文件。这种多层索引类似于B+树:KeyValues有序存储。rowkey指向索引,索引指向具体的数据块,以64KB为单位。每个块都有其叶索引。每个块的最后一个键存储在中间索引中。索引根节点指向中间层索引。Trailer指向原始信息数据块,当数据持久化为HFile时写入到HFile的末尾。预告片还包含布隆过滤器和时间范围等信息。布隆过滤器用于跳过不包含指定rowkey的文件,根据时间过滤时间范围信息,跳过不在请求时间范围内的文件。HFile索引刚才讨论的索引会在HFile打开时加载到内存中,这样数据查询只需要一次硬盘查询。HBaseReadMerge我们发现每一行(row)的KeyValuecells可能位于不同的地方。这些cell可能已经写入HFile,可能最近更新过,还在MemStore中,也可能最近刚刚被读取,缓存在BlockCache中。那么,当你读取一行时,系统如何返回对应的单元格呢?读取操作将合并BlockCache、MemStore和HFile中的单元格:首先,扫描器从BlockCache中读取单元格。最近读到的KeyValue缓存在这里,这是一个LRU缓存。然后扫描器读取MemStore,写入缓存,其中包含最近更新的数据。如果scanner在BlockCache和MemStore中都没有找到对应的cell,HBase会使用BlockCache中的index和Bloomfilter将对应的HFile加载到内存中,找到请求的行cell。如前所述,每个MemStore可能有多个HFile,因此一个读请求可能需要读取更多的文件,这可能会影响性能。这称为读取放大。点评:从时间轴上看,各个HFile也是有顺序的。本质上,它们保存了每个区域中每个列族的数据历史更新。所以对于同一个rowkey的同一个cell,也可能有多个版本的数据分布在不同的HFile中,所以可能需要读取多个HFile,这样性能开销会比较大,尤其是数据局部性不满足的时候.这种读放大会比较严重。这也是后面说到的compaction是必须的原因。HBaseMinorCompactionHBase会自动合并一些小的HFiles,重写成少量的大的HFiles。这个过程称为次要压缩。它使用合并排序算法将小文件合并为大文件,有效减少了HFiles的数量。HBaseMajorCompactionMajorCompaction将每个ColumnFamily下的所有HFile合并并重写,成为一个单一的大型HFile。在这个过程中,删除和过期的cell会被物理删除,可以提高读性能。.但是因为majorcompaction会重写所有的HFile,会产生大量的硬盘I/O和网络开销。这称为写入放大(WriteAmplification)。Majorcompaction可以设置为自动调度。由于写放大的问题,majorcompaction一般安排在周末和午夜。MapR数据库对此进行了改进,不需要压缩。Majorcompaction也可以将服务器崩溃或负载均衡导致的数据迁移移回远离RegionServer的地方,从而恢复数据局部性。HDFS数据备份的所有读写都发生在HDFS的主DataNode节点上。HDFS自动备份WAL和HFile文件块。HBase依靠HDFS来保证数据的完整性和安全性。数据写入HDFS时,一份写入本地节点,两份写入其他节点。WAL和HFiles都持久化到磁盘并备份。那么HBase是如何将MemStore中还没有持久化到HFile中的数据恢复的呢?以下章节将讨论这个问题。HBase故障恢复当RegionServer发生crash时,其管理的region无法访问,直到检测到crash,然后故障恢复完成,这些region才能恢复访问。Zookeeper依靠心跳检测来检测节点故障,然后HMaster会收到regionserver故障的通知。当HMaster发现某个regionserver出现故障时,HMaster会将该regionserver管理的region分配给其他健康的regionserver。为了将故障regionserver的MemStore中还没有持久化到HFile中的数据恢复,HMaster会将WAL拆分成几个文件保存到新的regionserver上。然后每个区域服务器重播它获得的WAL片段中的数据,为它分配到的新区域创建MemStore。WAL包含了一系列的修改操作,每一个修改代表一个put或者delete操作。这些修改是按照时间顺序依次写入的,持久化的时候会依次写入到WAL文件的末尾。如果数据还在MemStore中,没有持久化到HFile中怎么办?WAL文件将被回放。操作方法是读取WAL文件,排序并添加所有修改记录到MemStore中,最后MemStore会被flush到HFile中。点评:故障恢复是HBase可靠性保障的一个重要特性。WAL在这里起着关键作用。在拆分WAL的时候,数据会根据region分配给对应的新的regionserver,然后regionserver负责将这部分数据replay到MemStore。