此信息以前在 Cluster Replication 中提供。

HBase 提供了一种群集复制机制,允许您使用源群集的预写日志(WAL)来传播更改,从而使一个群集的状态与另一个群集的状态保持同步。集群复制的一些用例包括:

  • 备份和灾难恢复

  • 数据聚合

  • 地理数据分布

  • 在线数据提取与离线数据分析相结合

以列族的粒度启用复制。在为列族启用复制之前,请在目标群集上创建要复制的表和所有列族。

复制是异步的,因为我们将 WAL 发送到后台的另一个集群,这意味着当您想通过复制进行恢复时,可能会丢失一些数据。为解决此问题,我们引入了一项称为同步复制的新功能。由于机制有点不同所以我们使用一个单独的部分来描述它。请参见同步复制

155.1。复制概述

群集复制使用源推送方法。 HBase 集群可以是源(也称为主服务器或主服务器,意味着它是新数据的发起者),目标服务器(也称为从服务器或被动服务器,意味着它通过复制接收数据),或者可以同时满足这两个角色。复制是异步的,复制的目标是最终的一致性。当源接收对启用了复制的列族的编辑时,该编辑将使用 WAL 传播到所有目标群集,以用于管理相关区域的 RegionServer 上的该列族。

当数据从一个集群复制到另一个集群时,将通过集群 ID 跟踪数据的原始源,集群 ID 是元数据的一部分。在 HBase 0.96 和更新的( HBASE-7709 )中,还跟踪已经消耗了数据的所有簇。这可以防止复制循环。

只要需要将数据复制到任何从属群集,每个区域服务器的 WAL 必须保留在 HDFS 中。每个区域服务器都从需要复制的最旧日志中读取,并跟踪其在 ZooKeeper 中处理 WAL 的进度,以简化故障恢复。指示从属群集的进度的位置标记以及要处理的 WAL 的队列对于每个从属群集可以是不同的。

参与复制的集群可以具有不同的大小。主群集依赖于随机化来尝试平衡从属群集上的复制流。预期从属群集具有存储容量来保存复制数据,以及它负责摄取的任何数据。如果从属群集的空间不足或由于其他原因而无法访问,则会抛出错误并且主服务器会保留 WAL 并每隔一段时间重试一次复制。

复制群集的一致性

在复制过程中,您的应用程序如何构建在 HBase API 之上。 HBase 的复制系统至少为已启用的列系列向每个已配置的目标群集提供客户端编辑。如果未能到达给定目标,复制系统将以可能重复给定消息的方式重试发送编辑。 HBase 提供了两种复制方式,一种是原始复制,另一种是串行复制。在以前的复制方式中,客户端编辑没有保证的交付顺序。如果 RegionServer 发生故障,复制队列的恢复将独立于服务器先前处理的各个区域的恢复而发生。这意味着尚未复制的编辑可能由 RegionServer 提供服务,该 RegionServer 目前比在失败后处理编辑的更复杂。

这两个属性的组合(至少一次传递和缺少消息排序)意味着如果您的应用程序使用非幂等的操作,某些目标群集可能最终处于不同的状态,例如,增量。

为了解决这个问题,HBase 现在支持串行复制,它将编辑作为客户端请求的顺序发送到目标集群。请参见串行复制

术语变化

以前, master-mastermaster-slavecyclical 等术语用于描述 HBase 中的复制关系。这些术语增加了混淆,并且已经放弃了有利于讨论适用于不同场景的集群拓扑。

群集拓扑

  • 中央源群集可能会将更改传播到多个目标群集,以进行故障转移或由于地理分布。

  • 源群集可能会将更改推送到目标群集,这可能还会将其自身的更改推送回原始群集。

  • 许多不同的低延迟群集可能会将更改推送到一个集中式群集,以进行备份或资源密集型数据分析作业。然后,处理后的数据可能会被复制回低延迟群集。

可以将多个级别的复制链接在一起以满足组织的需要。下图显示了一个假设的场景。使用箭头跟随数据路径。

hbase replication diagram图 16.复杂群集复制配置示例

HBase 复制借鉴了 MySQL 使用的基于 _ 语句的复制 _ 设计中的许多概念。而不是 SQL 语句,将复制整个 WALEdits(包括来自客户端上的 Put 和 Delete 操作的多个单元格插入),以保持原子性。

155.2。管理和配置群集复制

群集配置概述

  1. 配置并启动源和目标群集。在源群集和目标群集上创建具有相同名称和列系列的表,以便目标群集知道将在何处存储将接收的数据。

  2. 源和目标群集中的所有主机都应该可以相互访问。

  3. 如果两个群集都使用相同的 ZooKeeper 群集,则必须使用不同的zookeeper.znode.parent,因为它们无法在同一文件夹中写入。

  4. 在源群集上,在 HBase Shell 中,使用add_peer命令将目标群集添加为对等方。

  5. 在源群集上,在 HBase Shell 中,使用enable_table_replication命令启用表复制。

  6. 检查日志以查看是否正在进行复制。如果是这样,您将看到来自 ReplicationSource 的以下消息。

LOG.info("Replicating "+clusterId + " -> " + peerClusterId); 

串行复制配置

参见串行复制

群集管理命令

add_peer

在两个群集之间添加复制关系。

  • ID - 唯一字符串,不得包含连字符。

  • CLUSTER_KEY:使用以下模板和适当的占位符组成:hbase.zookeeper.quorum:hbase.zookeeper.property.clientPort:zookeeper.znode.parent。可以在主 UI 信息页面上找到此值。

  • STATE(可选):ENABLED 或 DISABLED,默认值为 ENABLED

list_peers

列出此群集已知的所有复制关系

enable_peer

启用先前禁用的复制关系

disable_peer

禁用复制关系。 HBase 将不再向该对等集群发送编辑,但它仍会跟踪在重新启用时需要复制的所有新 WAL。只要存在对等体,在启用或禁用复制时将保留 WAL。

remove_peer

禁用并删除复制关系。 HBase 将不再向该对等集群发送编辑或跟踪 WAL。

enable_table_replication<table_name></table_name>

为其所有列系列启用表复制开关。如果在目标集群中找不到该表,则它将创建一个具有相同名称和列族的表。

disable_table_replication<table_name></table_name>

禁用其所有列系列的表复制开关。

155.3。串行复制

注意:此功能在 HBase 2.1 中引入

串行复制的功能

串行复制支持以与日志到达源群集相同的顺序将日志推送到目标群集。

为什么需要串行复制?

在 HBase 的复制中,我们通过在每个区域服务器中读取 WAL 来将突变推送到目标集群。我们有一个 WAL 文件的队列,所以我们可以按照创建时间的顺序读取它们。但是,当源群集中发生区域移动或 RS 故障时,在区域移动或 RS 失败之前未被推送的 hlog 条目将被原始 RS(用于区域移动)或另一个接管剩余 hlog 的 RS 推送。死 RS(用于 RS 失败),同一区域的新条目将由现在服务于区域的 RS 推送,但它们同时推送同一区域的 hlog 条目而不进行协调。

这种处理可能导致源和目标集群之间的数据不一致:

  1. 有 put 然后删除写入源集群。

  2. 由于区域移动/ RS 失败,它们被不同的复制源线程推送到对等集群。

  3. 如果在放入之前将删除推送到对等集群,并且在将 put 推送到对等集群之前在对等集群中发生 flush 和 major-compact,则收集删除并且放置在对等集群中,但是在源集群中,放置被掩盖了删除,因此源和目标集群之间的数据不一致。

串行复制配置

将复制节点的串行标志设置为 true。默认的串行标志为 false。

  • 添加一个串行标志为 true 的新复制对等体
hbase> add_peer '1', CLUSTER_KEY => "server1.cie.com:2181:/hbase", SERIAL => true 
  • 将复制对等方的串行标志设置为 false
hbase> set_peer_serial '1', false 
  • 将复制对等方的串行标志设置为 true
hbase> set_peer_serial '1', true 

首先在 HBASE-9465 中进行了系列复制,然后在 HBASE-20046 中进行了回复和重做。您可以在这些问题中找到更多详细信息。

155.4。验证复制数据

VerifyReplication MapReduce 作业(包含在 HBase 中)对两个不同集群之间的复制数据进行系统比较。在主群集上运行 VerifyReplication 作业,为其提供用于验证的对等 ID 和表名。您可以通过指定时间范围或特定系列来进一步限制验证。这份工作的简称是verifyrep。要运行作业,请使用如下命令:

$ HADOOP_CLASSPATH=`${HBASE_HOME}/bin/hbase classpath` "${HADOOP_HOME}/bin/hadoop" jar "${HBASE_HOME}/hbase-mapreduce-VERSION.jar" verifyrep --starttime=<timestamp> --endtime=<timestamp> --families=<myFam> <ID> <tableName> 
  • VerifyReplication命令打印出GOODROWSBADROWS计数器,以指示正确复制和未复制的行。

155.5。有关群集复制的详细信息

replication overview图 17.复制架构概述

155.5.1。 WAL 编辑的生活

单个 WAL 编辑将经历几个步骤,以便复制到从属群集。

  1. HBase 客户端使用 Put 或 Delete 操作来操作 HBase 中的数据。

  2. 区域服务器以某种方式将请求写入 WAL,如果未成功写入则允许重放。

  3. 如果更改的单元格对应于作为复制作用域的列族,则会将编辑添加到队列以进行复制。

  4. 在单独的线程中,作为批处理的一部分,从日志中读取编辑。仅保留符合复制条件的 KeyValues。可复制的 KeyValues 是列族的一部分,其列的范围为 GLOBAL,不是hbase:meta等目录的一部分,不是源自目标从属群集,并且尚未被目标从群集使用。

  5. 编辑用主 UUID 标记并添加到缓冲区。填充缓冲区或读取器到达文件末尾时,缓冲区将发送到从属群集上的随机区域服务器。

  6. 区域服务器按顺序读取编辑并将它们分成缓冲区,每个表一个缓冲区。读取所有编辑后,使用 HBase 的普通客户端刷新每个缓冲区。主服务器的 UUID 和已经使用数据的从服务器的 UUID 将保留在应用的编辑中,以防止复制循环。

  7. 在主服务器中,当前正在复制的 WALL 的偏移量在 ZooKeeper 中注册。

  8. 插入编辑的前三个步骤是相同的​​。

  9. 同样在单独的线程中,区域服务器以与上面相同的方式读取,过滤和编辑日志编辑。从属区域服务器不响应 RPC 调用。

  10. 主人睡眠并再次尝试可配置的次数。

  11. 如果从属区域服务器仍然不可用,则主服务器选择要复制到的区域服务器的新子集,并再次尝试发送编辑缓冲区。

  12. 同时,WALs 被滚动并存储在 ZooKeeper 的队列中。由区域服务器将 _ 归档 _ 的日志从区域服务器的日志目录移动到中央日志目录,将更新其在复制线程的内存中队列中的路径。

  13. 当从属群集最终可用时,缓冲区的应用方式与正常处理时相同。然后,主区域服务器将复制在中断期间累积的积压日志。

传播队列故障转移负载

复制处于活动状态时,源群集中的一部分区域服务器负责将编辑内容传送到接收器。与进程或节点崩溃时的所有其他区域服务器功能一样,此责任必须进行故障转移。建议使用以下配置设置来维护源群集中其余活动服务器上的复制活动的均匀分布:

  • replication.source.maxretriesmultiplier设置为300

  • replication.source.sleepforretries设置为1(1 秒)。该值与replication.source.maxretriesmultiplier的值相结合,导致重试周期持续约 5 分钟。

  • 在源群集站点配置中将replication.sleep.before.failover设置为30000(30 秒)。

在复制期间保留标记

默认情况下,用于群集之间复制的编解码器会从单元格中剥离标记,例如单元级 ACL。要防止标记被剥离,您可以使用不剥离标记的其他编解码器。在复制中涉及的源和接收区域服务器上配置hbase.replication.rpc.codec以使用org.apache.hadoop.hbase.codec.KeyValueCodecWithTags。该选项在 HBASE-10322 中引入。

155.5.2。复制内部

ZooKeeper 中的复制状态

HBase 复制在 ZooKeeper 中维护其状态。默认情况下,状态包含在基节点 / hbase / replication 中。该节点包含两个子节点,Peers znode 和RS znode。

Peers Znode

peers znode 默认存储在 / hbase / replication / peers 中。它由所有对等复制集群的列表以及每个集群的状态组成。每个对等方的值是其群集密钥,它在 HBase Shell 中提供。群集密钥包含群集仲裁中的 ZooKeeper 节点列表,ZooKeeper 仲裁的客户端端口以及该群集上 HDFS 中 HBase 的基本 znode。

RS Znode

rs znode 包含需要复制的 WAL 日志列表。此列表分为由区域服务器组织的一组队列和区域服务器将日志传送到的对等群集。 rs znode 为集群中的每个区域服务器都有一个子 znode。子 znode 名称是区域服务器的主机名,客户端端口和起始代码。此列表包括实时和死区服务器。

155.5.3。选择要复制到的区域服务器

当主群集区域服务器向从群集启动复制源时,它首先使用提供的群集密钥连接到从属的 ZooKeeper 集合。然后扫描 rs / 目录以发现所有可用的接收器(接受要复制的输入流的区域服务器),并使用配置的比率随机选择它们的子集,其默认值为 10 %。例如,如果从属群集有 150 台计算机,则将选择 15 个作为此主群集区域服务器发送的编辑的潜在接收者。由于此选择由每个主区域服务器执行,因此使用所有从属区域服务器的概率非常高,并且此方法适用于任何大小的群集。例如,10 台机器的主集群复制到 5 台机器的从机集群,比率为 10%,这使得主集群区域服务器可以随机选择一台机器。

ZooKeeper 观察器由每个主集群的区域服务器放置在从集群的 $ {zookeeper.znode.parent} / rs 节点上。此表用于监视从属群集组成的变化。从节点集群中删除节点后,或节点关闭或重新启动时,主集群的区域服务器将通过选择要复制到的新的从属区域服务器池进行响应。

155.5.4。跟踪日志

每个主群集区域服务器在复制 znodes 层次结构中都有自己的 znode。它包含每个对等群集一个 znode(如果创建了 5 个从属群集,创建了 5 个 znode),并且每个群集都包含要处理的 WAL 队列。这些队列中的每一个都将跟踪该区域服务器创建的 WAL,但它们的大小可能不同。例如,如果一个从属群集在一段时间内不可用,则不应删除 WAL,因此在处理其他群集时,它们需要保留在队列中。有关示例,请参见 rs.failover.details

实例化源时,它包含区域服务器正在写入的当前 WAL。在日志滚动期间,新文件将在可用之前添加到每个从属群集的 znode 的队列中。这可确保所有源都知道在区域服务器能够向其中添加编辑之前存在新日志,但此操作现在更加昂贵。当复制线程无法从文件中读取更多条目(因为它到达最后一个块的末尾)并且队列中有其他文件时,将丢弃队列项。这意味着如果源是最新的并且从区域服务器写入的日志中复制,则读取当前文件的“结尾”将不会删除队列中的项目。

如果日志不再使用或日志数超过hbase.regionserver.maxlogs,则可以归档日志,因为插入速率比刷新区域的速度快。归档日志时,会通知源线程该日志的路径发生更改。如果特定源已经完成了归档日志,它将忽略该消息。如果日志在队列中,则路径将在内存中更新。如果当前正在复制日志,则更改将以原子方式完成,以便读取器在已移动时不会尝试打开该文件。因为移动文件是 NameNode 操作,如果读者当前正在读取日志,则不会生成任何异常。

155.5.5。阅读,过滤和发送编辑

默认情况下,源会尝试从 WAL 读取并尽快将日志条目发送到接收器。速度受到日志条目过滤的限制只保留作用域为 GLOBAL 且不属于目录表的 KeyValues。速度也受到每个从站复制的编辑列表总大小的限制,默认情况下限制为 64 MB。使用此配置,具有三个从属服务器的主群集区域服务器将使用最多 192 MB 来存储要复制的数据。这不会考虑已过滤但未收集垃圾的数据。

一旦编辑的最大编辑大小被缓冲或读者到达 WAL 的末尾,源线程就会停止读取并随机选择一个接收器复制到(从通过仅保留从属区域服务器的子集生成的列表) 。它直接向选定的区域服务器发出 RPC 并等待方法返回。如果 RPC 成功,源将确定当前文件是否已清空,或者是否包含需要读取的更多数据。如果文件已清空,则源将删除队列中的 znode。否则,它会在日志的 znode 中注册新的偏移量。如果 RPC 引发异常,源将在尝试查找不同的接收器之前重试 10 次。

155.5.6。清理日志

如果未启用复制,则主服务器的日志清理线程将使用配置的 TTL 删除旧日志。这种基于 TTL 的方法不适用于复制,因为已超过其 TTL 的存档日志可能仍在队列中。默认行为是增强的,因此如果日志超过其 TTL,则清理线程会查找每个队列,直到找到日志,同时缓存已找到的队列。如果未在任何队列中找到日志,则将删除该日志。下次清理过程需要查找日志时,它首先使用其缓存列表。

只要存在对等体,就会在启用或禁用复制时保存 WAL。

155.5.7。区域服务器故障转移

当没有区域服务器发生故障时,跟踪 ZooKeeper 中的日志不会增加任何值。遗憾的是,区域服务器确实失败,并且由于 ZooKeeper 具有高可用性,因此在发生故障时管理队列的传输非常有用。

每个主集群区域服务器在每个其他区域服务器上保持观察者,以便在一个人死亡时得到通知(就像主人一样)。当发生故障时,他们都会竞争在死区服务器的 znode 中创建一个名为lock的 znode,该 znode 包含其队列。成功创建它的区域服务器然后将所有队列传输到它自己的 znode,一次一个,因为 ZooKeeper 不支持重命名队列。队列全部转移后,将从旧位置删除它们。使用附加了死服务器名称的从属群集的 ID 重命名已恢复的 znode。

接下来,主集群区域服务器为每个复制的队列创建一个新的源线程,并且每个源线程遵循读取/过滤器/发布模式。主要区别在于这些队列永远不会收到新数据,因为它们不属于新的区域服务器。当阅读器到达最后一个日志的末尾时,队列的 znode 将被删除,主群集区域服务器将关闭该复制源。

给定具有 3 个区域服务器的主集群复制到具有 id 2的单个从属服务器,以下层次结构表示 znodes 布局在某个时间点可能是什么。区域服务器的 znode 都包含一个包含单个队列的peers znode。队列中的 znode 名称以address,port.timestamp的形式表示 HDFS 上的实际文件名。

/hbase/replication/rs/
  1.1.1.1,60020,123456780/
    2/
      1.1.1.1,60020.1234  (Contains a position)
      1.1.1.1,60020.1265
  1.1.1.2,60020,123456790/
    2/
      1.1.1.2,60020.1214  (Contains a position)
      1.1.1.2,60020.1248
      1.1.1.2,60020.1312
  1.1.1.3,60020,    123456630/
    2/
      1.1.1.3,60020.1280  (Contains a position) 

假设 1.1.1.2 丢失了 ZooKeeper 会话。幸存者将竞争创造一个锁,并且,任意地,1.1.1.3 获胜。然后,它将通过附加死服务器的名称开始将所有队列传输到其本地对等方 znode。在 1.1.1.3 之前能够清理旧的 znode,布局将如下所示:

/hbase/replication/rs/
  1.1.1.1,60020,123456780/
    2/
      1.1.1.1,60020.1234  (Contains a position)
      1.1.1.1,60020.1265
  1.1.1.2,60020,123456790/
    lock
    2/
      1.1.1.2,60020.1214  (Contains a position)
      1.1.1.2,60020.1248
      1.1.1.2,60020.1312
  1.1.1.3,60020,123456630/
    2/
      1.1.1.3,60020.1280  (Contains a position)

    2-1.1.1.2,60020,123456790/
      1.1.1.2,60020.1214  (Contains a position)
      1.1.1.2,60020.1248
      1.1.1.2,60020.1312 

一段时间之后,但在 1.1.1.3 之前能够完成从 1.1.1.2 复制最后一个 WAL,它也会死掉。在正常队列中也创建了一些新日志。然后,最后一个区域服务器将尝试锁定 1.1.1.3 的 znode 并开始传输所有队列。新的布局将是:

/hbase/replication/rs/
  1.1.1.1,60020,123456780/
    2/
      1.1.1.1,60020.1378  (Contains a position)

    2-1.1.1.3,60020,123456630/
      1.1.1.3,60020.1325  (Contains a position)
      1.1.1.3,60020.1401

    2-1.1.1.2,60020,123456790-1.1.1.3,60020,123456630/
      1.1.1.2,60020.1312  (Contains a position)
  1.1.1.3,60020,123456630/
    lock
    2/
      1.1.1.3,60020.1325  (Contains a position)
      1.1.1.3,60020.1401

    2-1.1.1.2,60020,123456790/
      1.1.1.2,60020.1312  (Contains a position) 

155.6。复制指标

以下度量标准在全局区域服务器级别和对等级别公开:

source.sizeOfLogQueue

复制源处理的 WAL 数(不包括正在处理的 WAL)

source.shippedOps

发送的突变数量

source.logEditsRead

从复制源处的 WAL 读取的突变数

source.ageOfLastShippedOp

复制源发送的最后一批的时间

source.completedLogs

已完成其已确认发送到与此源关联的对等方的预写日志文件的数量。此度量标准的增量是 HBase 复制的正常操作的一部分。

source.completedRecoverQueues

此源已完成发送到关联对等方的恢复队列数。在失败的区域服务器面前,此度量标准的增量是 HBase 复制的正常恢复的一部分。

source.uncleanlyClosedLogs

复制系统在面对不正确关闭的文件到达可读条目末尾后认为已完成的预写日志文件数。

source.ignoredUncleanlyClosedLogContentsInBytes

如果未完全关闭预写日志文件,则可能会有一些已部分序列化的条目。此度量标准包含 HBase 复制系统认为在面对不正确关闭的文件时跳过的文件末尾的此类条目的字节数。这些字节应该在不同的文件中,或者表示未被确认的客户端写入。

source.restartedLogReading

HBase 复制系统检测到无法正确解析完全关闭的预写日志文件的次数。在这种情况下,系统从一开始就重放整个日志,确保相关对等体不能确认编辑。此度量标准的增量表示 HBase 复制系统难以正确处理底层分布式存储系统中的故障。不应出现数据删除,但您应检查 Region Server 日志文件以获取故障的详细信息。

source.repeatedLogFileBytes

当 HBase 复制系统确定它需要重放给定的预写日志文件时,此度量标准将增加复制系统认为在重新开始之前已由关联对等方确认的字节数。

source.closedLogsWithUnknownFileLength

当 HBase 复制系统认为它位于预写日志文件的末尾但是无法确定底层分布式存储系统中该文件的长度时,会增加。可以指示 dataloss,因为复制系统无法确定可读条目的末尾是否与文件的预期结束对齐。您应该检查 Region Server 日志文件以获取故障的详细信息。

155.7。复制配置选项

选项 描述 默认
zookeeper.znode.parent 用于 HBase 的基本 ZooKeeper znode 的名称 / HBase 的
zookeeper.znode.replication 用于复制的基本 znode 的名称 复制
zookeeper.znode.replication.peers 对等 znode 的名称 同行
zookeeper.znode.replication.peers.state 对等状态 znode 的名称 对等状态
zookeeper.znode.replication.rs rs znode 的名称 RS
replication.sleep.before.failover 在尝试复制死区服务器 WAL 队列之前,工作者应该睡多少毫秒。
replication.executor.workers 给定区域服务器应尝试同时进行故障转移的区域服务器数。 1

155.8。监控复制状态

您可以使用 HBase Shell 命令status 'replication'来监视群集上的复制状态。该命令有三个变体: status 'replication' - 打印每个源及其接收器的状态,按主机名排序。 status 'replication', 'source' - 打印每个复制源的状态,按主机名排序。 * status 'replication', 'sink' - 打印每个复制接收器的状态,按主机名排序。