美文网首页
【Hazelcast学习】数据是如何存储以及备份的

【Hazelcast学习】数据是如何存储以及备份的

作者: 伊丽莎白2015 | 来源:发表于2022-06-03 17:18 被阅读0次

    本文基于Hazelcast 5.1版本。

    本文尝试解决:

    • 数据如何存储在Hazelcast的各个节点上?
    • 如何备份?备份的方式?
    • 备分会失败吗?失败后会有别的措施保障吗?
    • CAP原则,Hazelcast是如何选择的?

    1. Hazelcast节点上的数据分区和备份

    官方文档:https://docs.hazelcast.com/hazelcast/5.1/architecture/data-partitioning
    或是博文:https://new.qq.com/omn/20200923/20200923A09K3500.html

    在介绍分区之前, 根据官网文章介绍的,并不是所有的数据结构都会进行分区存储的
    比如Map是分区存储的:

    Map: Partitioned
    而List、Set是不会进行分区存储的:
    Set, List:Non-Partitioned
    1.1 分区(Partitions)

    两个重要的概念:分区(Partitioning)备份(Replication)

    • Partitions即一些内存段。默认情况下,Hazelcast会把数据存储在271个分区上。--> 这就是分区的概念。可以通过hazelcast.partition.count配置分区数量,参考配置

    • Replication的意思也比较清楚,如果数据只有一个备份,那么某个节点down了,数据就丢失了。所以默认情况下Hazelcast会有一个备份副本(replica)。两份数据,其中一份就是主副本(primary replica),另外的就是备份副本(backup replica)相应的,存放主副本的分区叫分区的owner(partition owner)--> 当你存放数据或读数据的时候,打交道的都是partition owner

    如何理解?

    • 如果Hazelcast集群只有1个节点时,那么这271个分区都在一个节点上,即p1-p271。(如果只有一个节点那么也没必要有备份副本。)在文档中有一句话叫:A member can hold at most one replica of a partition (ownership or backup)也可推断出上述结论。
    • 如果Hazelcast集群有2个节点时,那么就可以相互backup了,即数据会有两个副本,我们可以叫Primary(p1-p271)以及Backup(b1-b271)。
      那么节点1上有:p1-p135,以及b136-b271。节点2上有:p136-p271以及b1-b135。
    • 如果Hazelcast集群有4个节点时,那么数据还是两个副本(和2个节点时一样),但分布就会不一样了:这时候的partition数量是271*2=542个,均匀分布在4个节点上,那么每个节点的partition数量是135~136个。
      4个节点上存储着两份数据
    1.2 Lite Members

    如果一个节点被配置成Lite版本,那么它就不会被分区了,而是做一些计算量比较重的任务(computationally-heavy tasks)。虽然它们本身没有分区,但是他们可以访问同一个群集里别的node的分区。

    1.3 如何分区

    数据如何被分到Hazelcast节点的分区中的?会使用哈希算法对数据进行分区(序列化,再哈希,再取模)。详见地址

    1.4 分区表(Partition Table)

    分区表存储的是分区ID以及这些分区从属的节点。这么做主要是可以让集群知道数据存放的信息。集群中第一个启动的节点(最老节点)会存放分区表,如果最老节点down了,那么次老节点会接管存储分区表的任务。
    默认情况下每隔15秒发送一次分区信息,也可通过hazelcast.partition.table.send.interval进行配置。

    1.5 重分区(Repartitioning)

    为什么会进行重分区?当一个新节点加入或旧节点down掉的时候就会进行数据的重新分区(重新分区后,在主节点上存储的分区表也会相应更新)。当一个Lite节点加入或down掉时并不会触发重新分区(主要原因是Lite节点并没有数据分区的概念)。

    2 数据如何备份

    官方文档:https://docs.hazelcast.com/hazelcast/5.1/architecture/data-partitioning#replication-algorithm-for-ap-data-structures
    Hazelcast使用的是主副本(primary-copy)和可配置的懒备份(configurable lazy replication)的策略。关于主副本和备份副本,在#1.1章节中有过介绍,平常的读写,只会跟主副本打交道(当然客户端读取或存储数据的时候是不知道主副本的存在的,即对客户端是透明的——客户端甚至不知道分区的概念)。备份副本的作用是当主备份所在的节点down了,那么它就起作用了(升级成主备份)。

    懒备份(lazy replication)当主副本收到一个key的值的更新,首先它会在本地执行更新并将其传播到备份副本上。主副本更新自己的值时会加上一个时间戳(logical timestamp),以便副本可以按正确的顺序执行更新以保持与主副本相同的状态。
    备份副本可用于扩展没有强一致性要求的读操作, 同时需要是monotonic read。(Backup replicas can be used to scale reads with no strong consistency but monotonic reads guarantee.
    关于monotonic read,可以参考:http://www.javashuo.com/article/p-ueptivvt-gu.html,即:若是一个进程开始了一次读取 r1,而后在开始另外一次读取 r2,那么 r2 不可能看到 r1 以前数据。

    如何理解?(纯属个人理解)
    想要对一个map的key=test的值从value更新到value1,再立马更新到value2:

    • 那么会先更新主副本中的值,test=value1(with logical timestamp=xx),再更新到test=value2(with logical timestamp=yy)
    • 这中间可能由于从value1--> value2更新的太快,可能已经完成更新后再传播给备份副本,那么备份副本就可以从logical timestamp中推断中value2的值是最新的,从而把自己的test中的值也更新为value2。

    懒备份(lazy replication)分为两种模式(想要用哪种都是可以在配置中配置,也可以结合使用):

    • sync:表示caller(即主副本)会阻塞,直到备份副本更新成功并发送ack确认给主副本。默认情况下,caller会等待备份副本的adk确认,最大等待时间为5ms,超过这个时长,caller则不会继续阻塞等待。也可通过配置更改hazelcast.operation.backup.timeout.millis
    • async:表示主副本发送后就算结束了,并不会等备份副本的ack确认 --> fire & forget。

    无论是sync还是async,备份都有可能会失败(比如分区表没有及时更新导致分区信息不正确,或是网络原因等),Hazelcast会周期性的去检查数据不一致的情况,如果发现有,那么就会再次把主备份的数据同步到备份副本上。除此之外,有个shutdown procedure会确保即将被关闭的主备份上数据和备份副本的数据的一致性(这个前提是节点是正常被关闭的——即没有错误)。

    当故障检测器未收到主副本成员的响应超过2分钟(为什么会收不到?比如Network splits——网络分离成独立子网的现象,或因为高负载出现长时间的停顿,GC或磁盘或网络的I/O问题),调用将失败并显示OperationTimeoutException,超时时间由系统属性定义hazelcast.operation.call.timeout.millis,当超时时间过去后,调用的结果将是不确定的。

    关于备份方面的扩展
    参考:https://docs.hazelcast.com/hazelcast/5.1/data-structures/backing-up-maps

    如果有一个map,key是ID,value是城市名,那么map中的元素就会被存放到集群的各个节点中,当只有主副本时,map的数据会均匀的分布在3个节点上: 三个节点,一份数据 当我们配置了一个副本(backup)后,这时候就会有主副本和备份副本的概念了,Hazelcast会保证主副本和备份副本不会同时落到同一台节点上。 三个节点,两份数据 如果这时候其中一个节点down掉了,那么剩下的两台机器上的备份副本会升级为主副本。然后开始生成新的备份副本。这些都会在节点down掉后立刻开始做,所以对于客户端来说,数据依旧是完整的。 挂了一个节点后的数据存储

    2. 分布式架构CAP,Hazelcast选择了AP

    2.1 CAP原则

    关于CAP,参考:https://baijiahao.baidu.com/s?id=1687697302388087668&wfr=spider&for=pc

    • C:一致性(Consistency),在数据更新或删除后,节点看到的数据都一致(从数据出发,即数据能一起变化)。
    • A:可用性(Availability): 某个节点down了,而其他节点依然能正常接收请求并返回请求(从数据出发,即有些节点挂了,数据有备份)。
    • P:分区容错性(Partition tolerance):如果出现了网络问题,分布式存储系统还需要继续运行。即不能因为出现了分区问题,整个分布式节点全部就出问题了。
    2.2 Hazelcast选择了AP

    由于分布式系统无法同时满足CAP原则,文档(https://docs.hazelcast.com/hazelcast/5.1/architecture/data-partitioning#execution-guarantees)中有一句话:Hazelcast不能保证有且仅有一次,它提供了“至少一次”的解决方案。

    Hazelcast, as an AP product, does not provide the exactly-once guarantee. In general, Hazelcast tends to be an at-least-once solution.

    AP系统意味着数据是有多副本的,即使出现网络分区问题,也不会丢失数据导致不可用,但是会存在数据一致性问题。即系统会返回一个节点的最近版本的可用数据(但并不意味着就是最新的),会花一些时间在写数据上(因为多个副本间需要通信)。

    也正因为此,在官网上Hazelcast会把Data Structure叫成AP Data Structures
    注:Hazelcast也有部分数据结构是CP原则,具体看:https://docs.hazelcast.com/hazelcast/5.1/data-structures/distributed-data-structures

    尽力而为的一致性

    • 每个Hazelcast节点都会在后台运行一个周期性任务。
    • 对于每个主副本,它会创建一个摘要信息并发送给它的备份副本。
    • 然后每个备份成员会将这个摘要信息与自己的数据进行比较,以查看它是否需要更新自己的数据。
    • 如果备份副本成员检测到丢失的更新,它会触发与主备份的同步。

    相关文章

      网友评论

          本文标题:【Hazelcast学习】数据是如何存储以及备份的

          本文链接:https://www.haomeiwen.com/subject/ubxfmrtx.html