redis的三大模式:
master/slave—>sentinel模式—>cluster模式
redis的三大模式是一点点演化而来的,当前模式不能满足特定的要求,就会滋生新模式的产生。
主从模式(master/slave)
主从模式的简介和配置,此处不再说,参照下面的博客:Redis 主从模式详解。
首先谈谈我对主从模式的必要性:
- 主从模式的一个作用是备份数据,这样当一个节点损坏(指不可恢复的硬件损坏)时,数据因为有备份,可以方便恢复。
- 另一个作用是负载均衡,所有客户端都访问一个节点肯定会影响Redis工作效率,有了主从以后,查询操作就可以通过查询从节点来完成。
对主从模式必须的理解(结论已经验证过,可以自行验证):
- 一个Master可以有多个Slaves
- 默认配置下,master节点可以进行读和写,slave节点只能进行读操作,写操作被禁止。不要修改配置让slave节点支持写操作,没有意义,原因一,写入的数据不会被同步到其他节点;原因二,当master节点修改同一条数据后,slave节点的数据会被覆盖掉
- slave节点挂了不影响其他slave节点的读和master节点的读和写,重新启动后会将数据从master节点同步过来
- master节点挂了以后,不影响slave节点的读,Redis将不再提供写服务,master节点启动后Redis将重新对外提供写服务。
- master节点挂了以后,slave节点不会重新选一个master
对有密码的情况说明一下,当master节点设置密码时:
- 客户端访问master需要密码
- 启动slave需要密码,在配置中进行配置即可
- 客户端访问slave不需要密码
主从节点的缺点
主从模式的缺点其实从上面的描述中可以得出:
master节点挂了以后,redis就不能对外提供写服务了,因为剩下的slave不能成为master
这个缺点影响是很大的,尤其是对生产环境来说,是一刻都不能停止服务的,所以一般的生产坏境是不会单单只有主从模式的。所以有了下面的sentinel模式。
sentinel模式
sentinel模式的简介和配置,此处不再说,参照下面的博客:Redis Sentinel模式详解。
sentinel的中文含义是哨兵、守卫。也就是说既然主从模式中,当master节点挂了以后,slave节点不能主动选举一个master节点出来,那么我就安排一个或多个sentinel来做这件事,当sentinel发现master节点挂了以后,sentinel就会从slave中重新选举一个master。
对sentinel模式的理解:
- sentinel模式是建立在主从模式的基础上,如果只有一个Redis节点,sentinel就没有任何意义
- 当master节点挂了以后,sentinel会在slave中选择一个做为master,并修改它们的配置文件,其他slave的配置文件也会被修改,比如slaveof属性会指向新的master
- 当master节点重新启动后,它将不再是master而是做为slave接收新的master节点的同步数据
- sentinel因为也是一个进程有挂掉的可能,所以sentinel也会启动多个形成一个sentinel集群
- 当主从模式配置密码时,sentinel也会同步将配置信息修改到配置文件中,不许要担心。
- 一个sentinel或sentinel集群可以管理多个主从Redis。
- sentinel最好不要和Redis部署在同一台机器,不然Redis的服务器挂了以后,sentinel也挂了
- sentinel监控的Redis集群都会定义一个master名字,这个名字代表Redis集群的master Redis。
当使用sentinel模式的时候,客户端就不要直接连接Redis,而是连接sentinel的ip和port,由sentinel来提供具体的可提供服务的Redis实现,这样当master节点挂掉以后,sentinel就会感知并将新的master节点提供给使用者。
sentinel模式基本可以满足一般生产的需求,具备高可用性。但是当数据量过大到一台服务器存放不下的情况时,主从模式或sentinel模式就不能满足需求了,这个时候需要对存储的数据进行分片,将数据存储到多个Redis实例中,就是下面要讲的。
cluster模式
sentinel模式的简介和配置,此处不再说,参照下面的博客:Redis cluster模式详解。
cluster的出现是为了解决单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器。对cluster的一些理解:
cluster可以说是sentinel和主从模式的结合体,通过cluster可以实现主从和master重选功能,所以如果配置两个副本三个分片的话,就需要六个Redis实例。
因为Redis的数据是根据一定规则分配到cluster的不同机器的,当数据量过大时,可以新增机器进行扩容
这种模式适合数据量巨大的缓存要求,当数据量不是很大使用sentinel即可。
- Redis Cluster是一个实现了分布式且允许单点故障的Redis高级版本,它没有中心节点,各个节点地位一致,具有线性可伸缩的功能。
- 上图给出Redis Cluster的分布式存储架构,其中节点与节点之间通过二进制协议进行通信(属于轻量协议通信,减少带宽占用,性能很高),节点与客户端之间通过ascii协议进行通信。
- 数据分片:Redis集群不同一致性哈希,它用一种不同的分片形式,在这种形式中,每个key都是一个概念性(hash slot)的一部分。Redis集群中有16384个hash slots,用这个key的CRC16值来对16384取模。(即:key的CRC16 % 16384),Redis集群中的每个节点负责一部分hash slots。
- 采用主从模式和哨兵模式保证数据一致性。
Redis cluster tutorial
Redis集群提供一种方式自动将数据分布在多个Redis节点上。
Redis Cluster provides a way to run a Redis installation where data is automatically sharded across multiple Redis nodes.
Redis Cluster是一个实现了分布式且允许单点故障的Redis高级版本,它没有中心节点,各个节点地位一致,具有线性可伸缩的功能。如图给出Redis Cluster的分布式存储架构,其中节点与节点之间通过二进制协议进行通信,节点与客户端之间通过ascii协议进行通信。在数据的放置策略上,Redis Cluster将整个 key的数值域分成16384个哈希槽,每个节点上可以存储一个或多个哈希槽,也就是说当前Redis Cluster支持的最大节点数就是16384。
1. Redis集群TCP端口(Redis Cluster TCP ports)
每个Redis集群中的节点都需要打开两个TCP连接。一个连接用于正常的给Client提供服务,比如6379,还有一个额外的端口(通过在这个端口号上加10000)作为数据端口,比如16379。第二个端口(本例中就是16379)用于集群总线,这是一个用二进制协议的点对点通信信道,使用轻量协议通信,减少带宽占用,性能很高。这个集群总线(Cluster bus)用于节点的失败侦测、配置更新、故障转移授权,等等。客户端从来都不应该尝试和这些集群总线端口通信,它们只应该和正常的Redis命令端口进行通信。注意,确保在你的防火墙中开放着两个端口,否则,Redis集群节点之间将无法通信。
命令端口和集群总线端口的偏移量总是10000。
注意,如果想要集群按照你想的那样工作,那么集群中的每个节点应该:
- 正常的客户端通信端口(通常是6379)用于和所有可到达集群的所有客户端通信
- 集群总线端口(the client port + 10000)必须对所有的其它节点是可到达的
也就是,要想集群正常工作,集群中的每个节点需要做到以下两点:
- 正常的客户端通信端口(通常是6379)必须对所有的客户端都开放,换言之,所有的客户端都可以访问
- 集群总线端口(客户端通信端口 + 10000)必须对集群中的其它节点开放,换言之,其它任意节点都可以访问
如果你没有开放TCP端口,你的集群可能不会像你期望的那样工作。集群总线用一个不同的二进制协议通信,用于节点之间的数据交换。
2. Redis集群数据分片(Redis Cluster data sharding)
Redis集群不同一致性哈希,它用一种不同的分片形式,在这种形式中,每个key都是一个概念性(hash slot)的一部分。
There are 16384 hash slots in Redis Cluster, and to compute what is the hash slot of a given key, we simply take the CRC16 of the key modulo 16384.
Redis集群中有16384个hash slots,为了计算给定的key应该在哪个hash slot上,我们简单地用这个key的CRC16值来对16384取模。(即:key的CRC16 % 16384)
Every node in a Redis Cluster is responsible for a subset of the hash slots
Redis集群中的每个节点负责一部分hash slots,假设你的集群有3个节点,那么:
Node A contains hash slots from 0 to 5500
Node B contains hash slots from 5501 to 11000
Node C contains hash slots from 11001 to 16383
允许添加和删除集群节点。比如,如果你想增加一个新的节点D,那么久需要从A、B、C节点上删除一些hash slot给到D。同样地,如果你想从集群中删除节点A,那么会将A上面的hash slots移动到B和C,当节点A上是空的时候就可以将其从集群中完全删除。
因为将hash slots从一个节点移动到另一个节点并不需要停止其它的操作,添加、删除节点以及更改节点所维护的hash slots的百分比都不需要任何停机时间。也就是说,移动hash slots是并行的,移动hash slots不会影响其它操作。
Redis支持多个key操作,只要这些key在一个单个命令中执行(或者一个事务,或者Lua脚本执行),那么它们就属于相同的hash slot。你也可以用hash tags俩强制多个key都在相同的hash slot中。
3. Redis集群主从模式
(Redis Cluster master-slave model)
In order to remain available when a subset of master nodes are failing or are not able to communicate with the majority of nodes, Redis Cluster uses a master-slave model where every hash slot has from 1 (the master itself) to N replicas (N-1 additional slaves nodes).
当部分master节点失败了,或者不能够和大多数节点通信的时候,为了保持可用,Redis集群用一个master-slave模式,这样的话每个hash slot就有1到N个副本。
在我们的例子中,集群有A、B、C三个节点,如果节点B失败了,那么5501-11000之间的hash slot将无法提供服务。然而,当我们给每个master节点添加一个slave节点以后,我们的集群最终会变成由A、B、C三个master节点和A1、B1、C1三个slave节点组成,这个时候如果B失败了,系统仍然可用。节点B1是B的副本,如果B失败了,集群会将B1提升为新的master,从而继续提供服务。然而,如果B和B1同时失败了,那么整个集群将不可用。
4. Redis集群一致性保证(Redis Cluster consistency guarantees)
Redis Cluster is not able to guarantee strong consistency. In practical terms this means that under certain conditions it is possible that Redis Cluster will lose writes that were acknowledged by the system to the client.
Redis集群不能保证强一致性。换句话说,Redis集群可能会丢失一些写操作。The first reason why Redis Cluster can lose writes is because it uses asynchronous replication.
Redis集群可能丢失写的第一个原因是因为它用异步复制。
写可能是这样发生的:
客户端写到master B
master B回复客户端OK
master B将这个写操作广播给它的slaves B1、B2、B3
正如你看到的那样,B没有等到B1、B2、B3确认就回复客户端了,也就是说,B在回复客户端之前没有等待B1、B2、B3的确认,这对应Redis来说是一个潜在的风险。所以,如果客户端写了一些东西,B也确认了这个写操作,但是在它将这个写操作发给它的slaves之前它宕机了,随后其中一个slave(没有收到这个写命令)可能被提升为新的master,于是这个写操作就永远丢失了。
这和大多数配置为每秒刷新一次数据到磁盘的情况是一样的。你可以通过强制数据库在回复客户端以前刷新数据,但是这样做的结果会导致性能很低,这就相当于同步复制了。
基本上,需要在性能和一致性之间做一个权衡。
如果绝对需要的话,Redis集群也是支持同步写的,这是通过WAIT命令实现的,这使得丢失写的可能性大大降低。然而,需要注意的是,Redis集群没有实现强一致性,即使用同步复制,因为总是有更复杂的失败场景使得一个没有接受到这个写操作的slave当选为新的master。(however note that Redis Cluster does not implement strong consistency even when synchronous replication is used: it is always possible under more complex failure scenarios that a slave that was not able to receive the write is elected as master.)
另一个值得注意的场景,即Redis集群将会丢失写操作,这发生在一个网络分区中,在这个分区中,客户端与少数实例(包括至少一个主机)隔离。
假设这样一个例子,有一个集群有6个节点,分别由A、B、C、A1、B1、C1组成,三个masters三个slaves,有一个客户端我们叫Z1。在分区发生以后,可能分区的一边是A、C、A1、B1、C1,另一边有B和Z1。此时,Z1仍然可用写数据到B,如果网络分区的时间很短,那么集群可能继续正常工作,而如果分区的时间足够长以至于B1在多的那一边被提升为master,那么这个时候Z1写到B上的数据就会丢失。
什么意思呢?简单的来说就是,本来三主三从在一个网络分区中,突然网络分区发生,于是一边是A、C、A1、B1、C1,另一边是B和Z1,这时候Z1往B中写数据,于此同时另一边(即A、C、A1、B1、C1)认为B已经挂了,于是将B1提升为master,当分区回复的时候,由于B1变成了master,所以B就成了slave,于是B就要丢弃它自己原有的数据而从B1那里同步数据,于是乎先去Z1写到B的数据就丢失了。
注意,有一个最大窗口,这是Z1能够向B写的最大数量:如果时间足够的话,分区的多数的那一边已经选举完成,选择一个slave成为master,此时,所有在少数的那一边的master节点将停止接受写。
也就说说,有一个最大窗口的设置项,它决定了Z1在那种情况下能够向B发送多数写操作:如果分隔的时间足够长,多数的那边已经选举slave成为新的master,此后少数那边的所有master节点将不再接受写操作。
在Redis集群中,这个时间数量是一个非常重要的配置指令,它被称为node timeout。在超过node timeout以后,一个master节点被认为已经失败了,并且选择它的一个副本接替master。类似地,如果在过了node timeout时间以后,没有一个master能够和其它大多数的master通信,那么整个集群都将停止接受写操作。
After node timeout has elapsed, a master node is considered to be failing, and can be replaced by one of its replicas. Similarly after node timeout has elapsed without a master node to be able to sense the majority of the other master nodes, it enters an error state and stops accepting writes.
5. Redis集群配置参数(Redis Cluster configuration parameters)
- cluster-enabled <yes/no>: 如果是yes,表示启用集群,否则以单例模式启动
- cluster-config-file : 可选,这不是一个用户可编辑的配置文件,这个文件是Redis集群节点自动持久化每次配置的改变,为了在启动的时候重新读取它。
- cluster-node-timeout : 超时时间,集群节点不可用的最大时间。如果一个master节点不可到达超过了指定时间,则认为它失败了。注意,每一个在指定时间内不能到达大多数master节点的节点将停止接受查询请求。
- cluster-slave-validity-factor : 如果设置为0,则一个slave将总是尝试故障转移一个master。如果设置为一个正数,那么最大失去连接的时间是node timeout乘以这个factor。
- cluster-migration-barrier : 一个master和slave保持连接的最小数量(即:最少与多少个slave保持连接),也就是说至少与其它多少slave保持连接的slave才有资格成为master。
- cluster-require-full-coverage <yes/no>: 如果设置为yes,这也是默认值,如果key space没有达到百分之多少时停止接受写请求。如果设置为no,将仍然接受查询请求,即使它只是请求部分key。
参考文章:
https://www.cnblogs.com/cjsblog/p/9048545.html
https://www.cnblogs.com/yiwangzhibujian/p/7047458.html
https://blog.csdn.net/angjunqiang/article/details/81190562