本文讲述了HBase Region Read Replicas功能详解
往期文章回顾:Talos 读写一致性
背景
CAP原理指出,对于一个分布式系统来说,不可能同时满足一致性 (Consistency)、可用性(Availability)、分区容错性(Partition tolerance),而HBase则被设计成一个CP系统,在保证强一致性的同时,选择牺牲了一定的可用性。在对HBase的压测中很容易发现,虽然HBase的平均读写延迟很低,但却存在很高的毛刺,P99、P999延迟很高,主要的一个影响因素则是单点的GC,另外Region的MTTR(平均修复时间)也较高,一旦某个RegionServer宕机或某个Region出现问题,甚至是一次Full GC,都有可能出现较长时间的不可用,影响可用性[4]。为了实现高可用度, HBase提供了Region Read Replicas功能,在这种模型下,表的每个region都会有多个副本,分布在不同的RegionServer上。在region恢复期间或请求时间过长时,支持最终一致性的读服务。在一些不要求强一致性的应用中,可以通过此功能来提高可用性或降低读请求延迟。
一个region的所有副本都有一个唯一的replica_id。replica_id=0的是primary region(和之前模型中唯一的region一样),其他的副本region被都叫做secondary region。默认region副本数为1,此时与之前的region模型并无不同。当region副本数被设置为2或更多时,Load Balancer会保证同一个region的多个副本会被分散在不同的RegionServer上。其中primary region支持读写请求;而secondary region则只支持读请求。如此设计保证primary region依旧具有强一致性,同时提高读可用性。但也因为写请求只有primary region可以处理,所以写请求依然会因为primary region不可用而被阻塞,HBase的写可用性依然没有得到改善。
>>>>
Client侧实现
1.Timeline Consistency
在该功能的实现中,HBase提供了一种支持单次读请求的一致性定义。
public enum Consistency {
STRONG,
TIMELINE
}
HBase默认的就是Consistency.STRONG
强一致性模型,与之前的模型一样,所有读写操作都通primary region完成。而当client使用Consistency.TIMELINE
的一致性发起读请求时,会首先向primary region发起请求,一定时间内没有返回响应,则同时并发向所有的secondary region发起请求,最终采用率先返回的请求。为了区分最终的响应是否来自secondary region,在Result
中增加了stale
的boolean属性,true
则表示来自secondary region。
从语义上讲,HBase的TIMELINE一致性并不同于常见的最终一致性解决方案。存在多个读副本,但不需要考虑副本之间数据冲突的问题。因为只有primary region可以写入,而secondary region只接收primary region同步的数据,并按同样顺序处理数据,所以secondary region可以看做是primary region在之前某个时刻的快照。从这一点上看,更像是RDBMS(关系型数据库管理系统)的复制、或是HBase多集群之间的复制[1]。
(图1: Timeline Consistency)
根据图1我们来更好的理解TIMELINE的语义。首先client1按顺序写了x=1,x=2,x=3,primary region也按写入顺序处理,并将WAL同步给其他secondary region(一种数据同步方式,后面会再讲)。在图中注意到,replica_1只接收到两次更新,所以最终数据是x=2,replica_2只接收到1次更新,数据是x=1。
client可能会读到乱序的数据,比如多次请求发往了不同的region。比如图1中的client2如果使用TIMELINE一致性读取数据,有可能和所有副本做交互,最终获得的数据1、2、3都有可能。如果client请求下面将展示下TIMELINE Get/Scan多次,甚至可能出现数据回退,即第1次请求获得x=2,第2次请求则获得了x=1。
这里实际上是不满足单调读一致性。单调读一致性是比强一致性弱,但比最终一致性强的保证:当读取数据时,单调读保证,如果某个用户依次进行多次读取,则他绝不会看到回滚现象,即在读取较新值之后又发生读旧值的情况。实现单调读的一种方式是,确保每个用户总是从固定的同一副本执行读取(而不同的用户可以从不同的副本读取)[2]。显然,这里不满足单调读一致性的原因是无法保证结果总是来自同一个副本。
2. Region Read Replica Location
(图2