时间轴一致性(Timeline Consistency)
HBase引入了一致性定义,可以根据读取操作(获取或扫描)提供一致性定义。
public enum Consistency {
STRONG,
TIMELINE
}
Consistency.STRONG是HBase提供的默认一致性模型。如果表的区域复制为1,或者在具有区域副本的表中,但是读取是以此一致性完成的,则读取总是由主区域执行,以便与先前的行为不会发生任何变化,并且客户端总是观察最新的数据。
如果执行读取操作Consistency.TIMELINE,则读取的RPC将首先发送到主要区域服务器。在很短的时间间隔(hbase.client.primaryCallTimeout.get默认为10ms)之后,如果主服务器没有响应,则也会发送用于辅助区域副本的并行RPC。在此之后,结果将从首先完成的RPC中返回。如果响应从主区域副本返回,则我们始终可以知道数据是最新的。为此,Result.isStale()API已被添加到检查失效。如果结果来自辅助区域,则Result.isStale()将被设置为true。然后用户可以检查该字段,以便了解有关数据的可能原因。
就语义而言,HBase实现的TIMELINE一致性与这些方面的纯粹最终一致性不同:
- 单宿主和有序更新:区域复制与否,在写入端,仍然只有1个定义的副本(主)可以接受写入。此副本负责命令编辑并防止冲突。这保证了两个不同的写入不会被不同的副本同时提交,并且数据发散。有了这个,就不需要进行read-repair或last-timestamp-wins两种中的冲突解决。
- 辅助还按照主要承诺的顺序应用编辑。通过这种方式,辅助数据将在任何时间点包含初选数据的快照。这与RDBMS复制相似,甚至与HBase自己的多数据中心复制类似,但在单个集群中也是如此。
- 在读取端,客户端可以检测读取是来自最新数据还是旧数据。另外,客户端可以在每个操作的基础上发布具有不同一致性要求的读取,以确保其自身的语义保证。
- 客户端仍然可以观察到无序编辑,并且如果它观察到首先从一个辅助副本读取,然后观察到另一个辅助副本的读取,则可以及时返回。对区域副本或基于交易ID的担保没有粘性。如果需要,这可以稍后实施。
为了更好地理解TIMELINE语义,让我们看看上面的图。假设有两个客户端,第一个客户端首先写入x=1,然后x=2和x=3。如上所述,所有写入都由主区域副本处理。写入保存在预写日志(WAL)中,并异步复制到其他副本。在上图中,请注意replica_id=1收到2次更新,其数据显示x=2,而replica_id=2只收到一次更新,其数据显示x=1。
如果client1以STRONG一致性读取,它只会与replica_id=0进行通信,因此保证观察x=3的最新值。如果客户端发出TIMELINE一致性读取,则RPC将转到所有副本(在主超时之后),并且第一个响应的结果将返回。因此,客户端可以将1,2或3看作x的值。假设主区域发生故障并且日志复制无法持续一段时间。如果客户端使用TIMELINE一致性进行多次读取,则它可以先观察x=2,然后观察x=1,依此类推。