深度原理学习–Redis集群

前面我们介绍了国人自己开发的redis集群方案——Codis,Codis友好的管理界面以及强大的自动平衡槽位的功能深受广大开发者的喜爱 。今天我们一起来聊一聊Redis作者自己提供的集群方案——Cluster 。希望读完这篇文章,你能够充分了解Codis和Cluster各自的优缺点,面对不同的应用场景可以从容的做出选择 。
Redis Cluster是去中心化的,这点与Codis有着本质的不同,Redis Cluster划分了16384个slots,每个节点负责其中的一部分数据 。slot的信息存储在每个节点中,节点会将slot信息持久化到配置文件中,因此需要保证配置文件是可写的 。当客户端连接时,会获得一份slot的信息 。这样当客户端需要访问某个key时,就可以直接根据缓存在本地的slot信息来定位节点 。这样就会存在客户端缓存的slot信息和服务器的slot信息不一致的问题,这个问题具体怎么解决呢?这里先卖个关子,后面会做解释 。
特性
首先我们来看下官方对Redis Cluster的介绍 。

  • High performance and linear scalability up to 1000 nodes. There are no proxies, asynchronous replication is used, and no merge operations are performed on values.
  • Acceptable degree of write safety: the system tries (in a best-effort way) to retain all the writes originating from clients connected with the majority of the master nodes. Usually there are small windows where acknowledged writes can be lost. Windows to lose acknowledged writes are larger when clients are in a minority partition.
  • Availability: Redis Cluster is able to survive partitions where the majority of the master nodes are reachable and there is at least one reachable slave for every master node that is no longer reachable. Moreover using replicas migration, masters no longer replicated by any slave will receive one from a master which is covered by multiple slaves.
是不是不(kan)想(bu)看(dong)?没关系,我来给你掰开了揉碎了解释一下 。
写安全
Redis Cluster使用异步的主从同步方式,只能保证最终一致性 。所以会引起一些写入数据丢失的问题,在继续阅读之前,可以先自己思考一下在什么情况下写入的数据会丢失 。
先来看一种比较常见的写丢失的情况:
client向一个master发送一个写请求,master写成功并通知client 。在同步到slave之前,这个master挂了,它的slave代替它成为了新的master 。这时前面写入的数据就丢失了 。
此外,还有一种情况 。
master节点与大多数节点无法通信,一段时间后,这个master被认为已经下线,并且被它的slave顶替,又过了一段时间,原来的master节点重写恢复了连接 。这时如果一个client存有过期的路由表,它就会把写请求发送的这个旧的master节点(已经变成slave了)上,从而导致写数据丢失 。
不过,这种情况一般不会发生,因为当一个master失去连接足够长时间而被认为已经下线时,就会开始拒绝写请求 。当它恢复之后,仍然会有一小段时间是拒绝写请求的,这段时间是为了让其他节点更新自己的路由表中的配置信息 。
为了尽可能保证写安全性,Redis Cluster在发生分区时,会尽量使客户端连接到多数节点的那一部分,因为如果连接到少数部分,当master被替换时,会因为多数master不可达而拒绝所有的写请求,这样损失的数据要增大很多 。
Redis Cluster维护了一个NODE_TIMEOUT变量,如果上述情况中,master在NODE_TIMEOUT时间内恢复连接,就不会有数据丢失 。
可用性
如果集群的大部分master可达,并且每个不可达的master至少有一个slave,在NODE_TIMEOUT时间后,就会开始进行故障转移(一般1到2秒),故障转移完成后的集群仍然可用 。
如果集群中得N个master节点都有1个slave,当有一个节点挂掉时,集群一定是可用的,如果有2个节点挂掉,那么就会有1/(N*2-1)的概率导致集群不可用 。
Redis Cluster为了提高可用性,新增了一个新的feature,叫做replicas migration(副本迁移,ps:我自己翻译的),这个feature其实就是在每次故障之后,重新布局集群的slave,给没有slave的master配备上slave,以此来更好的应对下次故障 。
性能
Redis Cluster不提供代理,而是让client直接重定向到正确的节点 。
client中会保存一份集群状态的副本,一般情况下就会直接连接到正确的节点 。
由于Redis Cluster是异步备份的,所以节点不需要等待其他节点确认写成功就可以直接返回,除非显式的使用了WAIT命令 。
对于操作多个key的命令,所操作的key必须是在同一节点上的,因为数据是不会移动的 。(除非是resharding)
Redis Cluster设计的主要目标是提高性能和扩展性,只提供弱的数据安全性和可用性(但是要合理) 。


推荐阅读