Contents

Redis集群

主从|哨兵|集群

Redis集群模式概述

在单机出现故障时,即便是配置了持久化方案,但是在服务重启过程中是无法向外提供服务的,redis集群的设计就是为了解决单一服务的这种数据安全性和可靠性的问题。常见集群模式有:主从模式、哨兵、集群。

主从模式

对于单机宕机出现的问题,我们自然想到的是存储一个数据备份,但是其中一个服务宕机时能够切换到另外一个服务上。主从模式,分为主节点、从节点(主节点主要负责写读操作,从节点负责读操作,集群中的这种设计主要时考虑到大多数场景为读多写少的场景)。

集群搭建

节点相关配置文件

  1. masterauth

若是主节点配置了requirepass配置,则在从节点的配置masterauth中需要告知从节点这一密码,否则在主从复制的时候主节点会拒绝从节点的连接。

  1. repl-disable-tcp-nodelay

TCP_NODELAY属性开关,目的是权衡网络带宽和网络延时。设置TCP_NODELAY时,TCP包会立即发出,网络延时较小,但是考虑到TCP包有固定的包头,有效信息比例减低,此时的网络带宽较小。反之会使用Nagle算法,尽可能的将TCP合并后发送,使用尽可能大的数据块,提高网络带宽。默认情况下是启用TCP_NODELAY的,此时主从复制的时候科能会存在一定时间的延时(linux默认的40ms),但是在主从节点之间有很多跳的时候考虑到数据一致性,此时可以禁用这一功能。

  1. replica-priority

整数值,表示的是竞选主节点的优先级,越低则优先级越高。而0值则表示不参与主节点竞选。默认值是100。

设置主从关系

  1. SLAVEOF 命令

SLAVEOF HOST PORT:用于将当前节点设置为指定HOST:PORT的从节点. SLAVEOF NO ONE:将当前节点设置为主节点

  1. INFO replication 命令

查看当前节点的主从关系。例如从节点信息: ../../redis/slave.png#pic_center 主节点信息: ../../redis/master.png#pic_center

主从分级管理

考虑到若是一个主节点下存在很多个从节点,在主从同步的时候主节点性能会受到影响。分级管理就是说每个从节点也可以作为下级从节点的master.

哨兵模式

在上述主从关系中,当主节点宕机之后master_link_status属性值变为down,此时该怎么更换主节点。

  • 手动模型:在目标从节点上执行slaveof no one使得该节点成为主节点。
  • 哨兵模式: 由哨兵进行选举,选择一个合适的节点成为master。

概述

redis2.6之后提供了Sential哨兵机制,就是在集群中引入一个节点充当哨兵,监控master的运行状态,当master宕机后制定一个slave成为新的master。 但是哨兵若是单点的,当哨兵宕机后整个集群就危险了,所以哨兵也需要时集群式的。 哨兵定时向master发送心跳,若是其中有N个哨兵没有收到响应则认为master 宕机,然后由哨兵指定一个slave成为master。

Sentinel配置文件

  1. sentinel monitor

ip:port为master地址。

quorum:判定master宕机的最少哨兵数;该数值对master宕机后故障转移过程不起决定作用,转移需要多数sentinel判定(即,将指定slave晋升为master 仍需要多数sentinel同意)。也就是说单判定宕机来说,quorum可以完全决定,但是故障转移必须要大多数sentinel同意。

  Note that whatever is the ODOWN quorum, a Sentinel will require to
  be elected by the majority of the known Sentinels in order to
  start a failover, so no failover can be performed in minority.
  1. sentinel auth-pass

认证master和slave(可能晋升为master)的密码。

  1. slave信息

在sentinel的配置文件中不需要写slave信息,sentinel启动后会自动发掘该信息并重写配置文件。当有slave晋升为master后,该配置项也会重写。

  1. sentinel down-after-milliseconds mymaster 30000

判定master unreachable的时间,发送PING命令无响应的时间。(也是sentinel之间判断不可达的时间)

  1. sentinel parallel-syncs mymaster 1
How many replicas we can reconfigure to point to the new replica simultaneously
during the failover. Use a low number if you use the replicas to serve query
to avoid that all the replicas will be unreachable at about the same
time while performing the synchronization with the master.

在slave和master进行数据同步时(故障转移期间),同时允许建立的连接数,因为在数据同步时slave是不对外服务的,所以该值越大同步数据时集群的对外读能力越差。 但是数值越大,数据一致性相对越高。

  1. sentinel failover-timeout mymaster 180000
 Specifies the failover timeout in milliseconds. It is used in many ways:

 - The time needed to re-start a failover after a previous failover was
   already tried against the same master by a given Sentinel, is two
   times the failover timeout.

 - The time needed for a replica replicating to a wrong master according
   to a Sentinel current configuration, to be forced to replicate
   with the right master, is exactly the failover timeout (counting since
   the moment a Sentinel detected the misconfiguration).

 - The time needed to cancel a failover that is already in progress but
   did not produced any configuration change (SLAVEOF NO ONE yet not
   acknowledged by the promoted replica).

 - The maximum time a failover in progress waits for all the replicas to be
   reconfigured as replicas of the new master. However even after this time
   the replicas will be reconfigured by the Sentinels anyway, but not with
   the exact parallel-syncs progression as specified.
  • 故障转移重试时候的超时时间的2倍
  • slave从原来的master切换到新的master的超时时间
  • 对于晋升的slave,发送SLAVE NO ONE但是新master还没有产生任何的配置更新,此时取消该节点晋升的等待时间
  • 等待所有slave同步配置的时间

动态修改sentinel配置

sentinel set master-name option value [option value]

启动Sentinel

  1. 启动 redis-sentinel sentinel.conf 启动后的日志如下,可见自动探测到slave(6380)
580440:X 04 Feb 2023 17:35:02.849 * Sentinel new configuration saved on disk
580440:X 04 Feb 2023 17:35:02.850 # Sentinel ID is d8b00f1685a50dd62466728dd3e4af990bd0b820
580440:X 04 Feb 2023 17:35:02.850 # +monitor master mymaster 127.0.0.1 6379 quorum 2
580440:X 04 Feb 2023 17:35:02.850 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
580440:X 04 Feb 2023 17:35:02.856 * Sentinel new configuration saved on disk

此时的配置文件被重写为:

 1 include sentinel.conf
  2 pidfile "/var/run/sentinel_26380.pid"
  3 port 26379
  4 sentinel monitor mymaster 127.0.0.1 6379 2
  5 sentinel auth-pass mymaster ahuxiao2022
  6 
  7 # Generated by CONFIG REWRITE
  8 latency-tracking-info-percentiles 50 99 99.9
  9 dir "/tmp"
 10 protected-mode no
 11 user default on nopass ~* &* +@all
 12 sentinel myid d8b00f1685a50dd62466728dd3e4af990bd0b820
 13 sentinel config-epoch mymaster 0
 14 sentinel leader-epoch mymaster 0
 15 sentinel current-epoch 0
 16 
 17 sentinel known-replica mymaster 127.0.0.1 6380
 18 sentinel known-sentinel mymaster 127.0.0.1 26380 7362108b0863fd1e333ab4ba342b13729624ab68
  1. 观察 info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_tilt_since_seconds:-1
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=1,sentinels=2
  1. 故障转移

首先是检测到6379宕机,然后是leader选举,最后是6380master晋升。

581110:X 04 Feb 2023 17:46:59.219 # +sdown master mymaster 127.0.0.1 6379
581110:X 04 Feb 2023 17:46:59.303 # +odown master mymaster 127.0.0.1 6379 #quorum 2/2
581110:X 04 Feb 2023 17:46:59.303 # +new-epoch 1
581110:X 04 Feb 2023 17:46:59.303 # +try-failover master mymaster 127.0.0.1 6379
581110:X 04 Feb 2023 17:46:59.312 * Sentinel new configuration saved on disk
581110:X 04 Feb 2023 17:46:59.312 # +vote-for-leader 7362108b0863fd1e333ab4ba342b13729624ab68 1
581110:X 04 Feb 2023 17:46:59.339 # fdf18085b79fc686bbeeaba0cab31647ae1d41bb voted for 7362108b0863fd1e333ab4ba342b13729624ab68 1
581110:X 04 Feb 2023 17:46:59.342 # d8b00f1685a50dd62466728dd3e4af990bd0b820 voted for 7362108b0863fd1e333ab4ba342b13729624ab68 1
581110:X 04 Feb 2023 17:46:59.367 # +elected-leader master mymaster 127.0.0.1 6379
581110:X 04 Feb 2023 17:46:59.367 # +failover-state-select-slave master mymaster 127.0.0.1 6379
581110:X 04 Feb 2023 17:46:59.438 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
581110:X 04 Feb 2023 17:46:59.438 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
581110:X 04 Feb 2023 17:46:59.500 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
581110:X 04 Feb 2023 17:46:59.826 * Sentinel new configuration saved on disk
581110:X 04 Feb 2023 17:46:59.826 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
581110:X 04 Feb 2023 17:46:59.826 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6379
581110:X 04 Feb 2023 17:46:59.875 # +failover-end master mymaster 127.0.0.1 6379
581110:X 04 Feb 2023 17:46:59.875 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380

哨兵原理

定时任务

sentinel维护着三个定时任务监测redis节点和sentinel节点状态。

  1. info

每个sentinel节点每10s向redis集群中的每个节点发送info命令,获取redis集群最新的拓扑结构。

  1. 心跳任务

每个sentinel节点每1s会向redis所有节点和sentinel节点发送一条ping命令,检测这些节点的存货状态。

  1. 发布订阅

sentinel节点在启动时会向所有redis节点订阅__sentinel__:hello主题信息,当该主题信息发生改变时会通知到所有订阅者。sentinel启动后每2s会向 redis节点发布一条主题信息,包含:对redis节点的状态判断、当前sentinel的状态信息。 sentinel节点收到主题信息后,读取这些信息完成下面几项工作:

  • 若有新sentinel加入,则记录新的sentinel信息,建立连接
  • 若有sentinel leader选票信息,则执行leader选举过程
  • 汇总其他sentinel节点对redis节点的状态判断,作为redis节点客观下线的判断依据

redis节点下线判断

  1. 主观下线

sentinel向每个redis节点发送心跳,在down-after-milliseconds时间内若是没有收到响应则单方面认为待节点下线。

  1. 客观下线
  • 主观下线的节点是slave时,通过发布订阅收集其他sentinel的判断信息,超出quorum个判断下线是视为下线。
  • 主观下线的节点是master,sentinel主动发送sentinel-is-master-down-by-addr向其他sentinel询问master状态,超出quorum个sentinel 认为下线时客观判断为下线。

sentinel-leader选举

每次故障转移发生之前都会进行sentinel-leader的选举,所有sentinel节点都有当选的资格。采用的是raft算法,大致思路如下:

  1. 当sentinel完成客观下线判断后,会主动推荐自身成为leader,将自己的提案发生给其他sentinel
  2. 其他sentinel在拥有选票的情况下,会立即将同意结果反馈给提案者
  3. 提案者收到>=max(quorum, sentinel_num/2+1)同意反馈时,成为leader

简单来说,在没有网络问题的前提下:基本就是谁先做出客观下线的判断谁就会先发起leader选举,也就会得到大多数选票,成为leader.

故障转移结束,sentinel不在维护leader-follower关系

redis-master选择

故障转移时,sentinel需要从slave中选择新的master,选择原则如下:

  1. 过滤掉主观下线、replica-priority为0的redis节点
  2. 选择replica-priority 值最小的节点,若只存在一个节点则直接判断该节点为master
  3. 在优先级相同的节点列表中选择复制偏移量最大的节点
  4. 若复制便宜相同,则选择动态ID最小的节点

故障转移过程

sentinel-leader选举 -> leader 选择新的master -> 告知slave

  1. leader 选择一个slave作为新的master,向该节点发送SLAVEOF NO ONE
  2. leader 向新master发送info replication获取其动态ID
  3. leader 向其他slave 发送 SLAVEOF <IP> <PORT>
  4. leader 从slave中选择parallel-syncs个节点从新的master同步数据,逐步进行,直至所有slave节点同步完成
  5. 故障转移完成

节点上线

  1. 原redis节点上线:每个sentinel都保存有redis集群中节点信息,对于原节点上线,sentinel会定时探测,检测到恢复会从当前master同步数据。但是对于 原master节点恢复上线,由于master已经发生改变,sentinel首先会将原master设置为slave,然后才会定时查看其是否恢复。
  2. 新redis节点上线:需要手动完成,也就是说需要知道集群中的master节点是谁,启动新节点时通过slaveof命令指定master,加入集群
  3. sentinel上线:需要手动完成,启动的时候需要知道当前集群的master。sentinel monitor

redis分布式系统

Redis Cluster 可以称为redis分布式系统,解决的是数据分区存储,各个分区是个主从集群;同时能够将用户请求路由到不同redis。 redis cluster是redis3.0推出的分布式解决方案。 ../../redis/redis-cluster.png#pic_center

数据分区算法

顺序分区

  • 轮询分区
  • 时间片轮转分区
  • 数据块范围分区
  • 业务主题分区

hash分区

节点取模

设集群中的节点数为N,则val=hash(key)%N, key可以选取为数据本身或数据的一部分。该算法优点是简单,缺点是当集群节点变动时,已经存储的数据需要根据 新的节点数进行数据迁移,否则用户是无法查找到原来的数据的。

一致性hash

优点:

  • 集群节点数发生变动时,迁移的数据很少

缺点:

  • 数据倾斜:当服务节点较少时,大多数的数据存储在较少的节点上
  • 雪崩:在数据倾斜的情况下,少数节点负载或存储能力无法承担引起宕机,则下线后节点数据会继续迁移,引起连锁宕机的问题
  • 因为新增一个节点只会影响hash上距离该主机最近的节点,所以想要通过新增一台节点减轻集群压力是行不通的

解决方案

  • 引入虚拟节点,因为节点多了之后数据更加分散,映射到真实节点后也更加平均

redis数据分区算法采用的就是一致性hash+虚拟槽,虚拟槽个数为N=2^14个,计算槽点slot=CRC16(key)%N.(考虑到N是2的整数倍,CRC16(key)&N)。

../../redis/一致性hash.png#pic_center

redis-cluster搭建

相关配置

  • cluster-enabled yes: 只有开启这个选项的redis节点才能成为集群中的节点
  • cluster-config-file nodes-6379.conf: redis-cluster节点的配置文件,不需手动编写,在节点创建和更新。
  • cluster-node-timeout 15000: 节点超时毫秒数,超时判定为故障。远大于系统内其他超时大小。

在公共配置中开启cluster-enabled,在每个节点中单独配置以下内容:

include redis.conf
port 6380
pidfile "/var/run/redis_6380.pid"
appendfilename "appendonly6380.aof"
logfile "logs/redis6380.log"
cluster-config-file nodes-6380.conf

启动集群

  1. 首先依次启动集群节点
  2. 为节点配置关系.redis-cli --cluster create --cluster-replicas N ip:port [ip:port].N指定每个master对应的slave数量

例如集群中我们设置了三主三从,每个master对应一个slave. 集群创建的日志如下:虚拟槽信息、主从关系、集群节点配置生成、对每个节点发送信息邀请加入

>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 10.206.32.17:6384 to 10.206.32.17:6380
Adding replica 10.206.32.17:6385 to 10.206.32.17:6381
Adding replica 10.206.32.17:6383 to 10.206.32.17:6382
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 50a7880ce65a9690949e9c9368ee649bda08da4e 10.206.32.17:6380
   slots:[0-5460] (5461 slots) master
M: a9c7c193a5e82f4b01636cf1c6c53636ca1119a0 10.206.32.17:6381
   slots:[5461-10922] (5462 slots) master
M: 96d672b4976dbe7305f4022215884d9d195e3d1f 10.206.32.17:6382
   slots:[10923-16383] (5461 slots) master
S: 2d1d5f2030e99b29116ac20e1ff40375ef63a507 10.206.32.17:6383
   replicates 96d672b4976dbe7305f4022215884d9d195e3d1f
S: 4c749c4ae889921738a9fafe36e06747a70f230e 10.206.32.17:6384
   replicates 50a7880ce65a9690949e9c9368ee649bda08da4e
S: 07d236d9587f9a8b4c261d5252fccf4dbc89480b 10.206.32.17:6385
   replicates a9c7c193a5e82f4b01636cf1c6c53636ca1119a0
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.....
>>> Performing Cluster Check (using node 10.206.32.17:6380)
M: 50a7880ce65a9690949e9c9368ee649bda08da4e 10.206.32.17:6380
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 96d672b4976dbe7305f4022215884d9d195e3d1f 10.206.32.17:6382
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 4c749c4ae889921738a9fafe36e06747a70f230e 10.206.32.17:6384
   slots: (0 slots) slave
   replicates 50a7880ce65a9690949e9c9368ee649bda08da4e
S: 07d236d9587f9a8b4c261d5252fccf4dbc89480b 10.206.32.17:6385
   slots: (0 slots) slave
   replicates a9c7c193a5e82f4b01636cf1c6c53636ca1119a0
M: a9c7c193a5e82f4b01636cf1c6c53636ca1119a0 10.206.32.17:6381
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 2d1d5f2030e99b29116ac20e1ff40375ef63a507 10.206.32.17:6383
   slots: (0 slots) slave
   replicates 96d672b4976dbe7305f4022215884d9d195e3d1f
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
  1. 查看集群信息

    redis-cli -c -p 6380 cluster nodes

redis-cluster数据操作

连接到集群:redis-cli -c -p ${port}

写入数据

# 可见在集群中任一节点写入时,会进行数据分区;另外对于mset指定,由于所有key对应的不是同一个虚拟槽,会执行失败,解决方案是为key设置group
set port 6380
-> Redirected to slot [9479] located at 10.206.32.17:6381
 mset name ahu title us year 1928
(error) CROSSSLOT Keys in request don't hash to the same slot

# 批量写入时设置group
mset name{collage} ahu title{collage} us year{collage} 1928

查询数据

  • cluster keyslot key:计算key的slot信息
  • cluster countkeysinslot ${id}:查询slot中的key数量,只能查询当前client连接的节点对应的槽信息
  • cluster getkeysinslot ${id} ${N}:获取slot中指定数据的key信息

故障转移

当集群中的节点宕机后,从节点晋升主节点是不需要哨兵接入的。若是当某个主从集群全部宕机(hash环的部分槽未被覆盖),整个集群默认会拒绝服务直到对应的机器恢复。 可以通过配置项更改这个行为。cluster-require-full-coverage yes,这种情况下,集群会提供覆盖hash环的节点数据。

集群扩容

添加master节点

  • redis-cli -c --cluster add-node ip:port cluster_one_of_ip:port:添加新节点到集群中,第二个参数为集群中的任一节点地址。
  • redis-cli -c --cluster reshard ip:port: ip:port为集群中任一节点,充分分配hash环上的虚拟槽。之后会询问移动的槽数和新增节点ID,以及从哪些节点移动虚拟槽。

添加slave节点

将新增的节点作为master_id这个master的slave添加到集群中 redis-cli --cluster add-node new_ip:port cluster_one_of_ip:port --cluster-slave --cluster-master-id ${master_id}

集群缩容

  • redis-cli --cluster del-node ip:port id: 从集群中移除指定节点。对于master节点,由于存在关联的slot,需要先将slot移动到其他节点。

redis分布式系统限制

  • 仅支持0号数据库
  • 批量key操作需要所有key映射到同一个slot
  • 分区仅针对key
  • 主从关系不支持分级管理

主从复制

主从复制过程

../../redis/主从复制.png#pic_center

主从复制的同步请求

sync同步

redis2.8之前,首次通信成功之后,slave会发送sync数据同步请求,之后master会发送全量数据给slave。存在的问题是,对于诸如网络抖动导致的复制过程 中断,网络恢复后slave会重新发送同步请求。由于全量复制时比较耗时,容易受网络抖动影响,从而造成长时间无法完成复制的情况。

psync同步

redis2.8之后,全量复制采用了psync策略,复制过程实现“断点重传”。为了实现psync,有以下几个策略:

  • [复制偏移量offset] 对传送的数据进行字节编号(复制偏移量),主从节点维护已发送的数据偏移量。
  • [主节点复制ID master_replid] master启动后动态生成的40位16进制字符串,用于数据同步时slave识别master使用。这里没有使用ip:port的形式识别master 是考虑到,在master重启时,ip:port不变,slave会继续断点重传,此时存在数据安全问题,因为重启数据同步缓存可能已经丢失了,而此时slave是没有感知的。 但是使用动态生成的ID,在master重启后ID发生变化,slave感知到后会引起全量同步。
  • [复制积压缓冲区] 当master有连接slave时,master会创建一个backlog(默认大小1M)称为复制积压缓冲区。另外master还会为每个slave配置一个发送缓存。 当master接收到写操作时,数据会写到内存、发送缓存、复制积压缓冲区。主要是配合发送缓存用于断点重传。

psync执行过程

psync <master_replid> <repl_offset>: 标识slave要从指定的master中的repl_offset+1处开始复制。 第一次复制时,slave不知道master的master_replid,此时提交的命令为:psync ? -1表示要进行全量复制。

../../redis/psync.png#pic_center

psync2

psync的问题:

  • [问题1] slave重启时,由于master_replid是保存在内存中的,重启会丢失id,引起全量复制。
  • [问题2] psync同步过程中master宕机后,slave会发生易主,master_replid不在一致,引起全量复制。

解决方案:redis4.0之后“同源增量更新”,这里的同源指的是虽然slave发来的master_replid和自己的不一致但是和自己晋升为master之前保存的 master_replid一致,表示其之前为一个master。

  • 解决问题1:将master_replid直接持久化到文件,slave重启后加载持久化文件重新获取该ID,至于offset则通过命令向master获取。
  • 解决问题2:本质原因是新的master不知道老的master_replid。但是新master仍保存着之前自己master的master_replid,若此时slave发送来的id与 自己保存的一致,这说明易主之前两个节点是同一个master,称为同源。此时可以继续进行断点重传。而此时slave的master_replid2则表示的是易主之后的 master_replid。

无盘操作

redis6.0之后,提出了无盘全量同步、无盘加载,避免耗时的IO操作。

无盘全量同步:master fork出子进程不进行bgsave,而是直接发给slave。

无盘加载: slave收到同步数据后不再写入持久化文件,而是直接写入到内存。

共享复制积压缓冲区

redis7.0, 各个slave的发送缓冲区共享了一个新建的复制积压缓冲区(共享复制积压缓冲区)。

补充

CAP定理

  • Consistency-一致性、Availability-可用性、Partition tolerence-分区容错性
  • C:分布式系统中多个主机中间保持数据的一致性
  • A:系统一直处于可用的状态,对于用户请求能够在有限时间内对用户做出响应
  • P:节点在遇到故障时,系统仍能够对外满足一致性和可用性服务

CAP定理表达的是在一个分布式系统中,C-A-P三者不可兼得,要么CP要么AP

BASE理论

  • Basically Available-基本可用。 分布式系统出现故障时,允许损失部分可用性。
  • Soft state-软状态。允许数据存在中间状态,即允许数据同步存在一定延时。软状态(灰度状态、过滤状态)
  • Eventually consistent-最终一致性。不要求系统中各节点数据实时一致,但要求经过一段时间段的同步能够达到一个一致状态。

BASE理论是对CAP中CA、CP的折中,表达的是即使无法做到强一致性,但是系统可以根据自身业务采用适当的方式达到最终一致性。