Redis集群方案
Redis简介
Redis特点
Redis是一个开源的高性能的key-value存储系统。具有以下特点:
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
- 丰富的数据类型 – Redis支持二进制案例的 String, List, Hash, Set 及 Sorted Set 数据类型操作。
- 原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性
- Redis支持数据的备份,即master-slave模式的数据备份。
- Redis支持数据的持久化,能够在一定层度上保证数据不丢失。
Redis常见误区
- Redis代理传统数据库。
- Redis是多线程的。
- 一台服务器部署一个Redis实例。
Redis高性能的原因
- 存储:数据存储在内存中。
- 通信:通过多路复用进行IO优化。
- 单线程:通过单线程运行,避免了多线程下上下文切换导致的时间耗费。
Redis集群高可用方案
Redis集群高可用方案可以分为如下几类
- 传统的Replication方案,即Master-Slave-Sentinel。
- 客户端分片,客户端自己通过Key分片,服务端通过多组Redis高可用进行组合。
- 代理分片,服务端通过多组Redis高可用进行组合。
- Redis3.0官方带来的Redis Cluster集群方案。
下面将分别介绍这些方案。
Replication方案:Master-Slave-Sentinel
通过一主多从
的方案实现Redis的高可用,其核心架构为1个Master多个Slave再加多个Sentinel。
示意图如下所示:
- Master负责Redis集群对外的的写和读操作。
- Slave为Master的副本,其数据来源于Master的同步,客户端可以从此处进行信息读取,减轻Master服务器压力。
- Sentinel是哨兵,主要作用是监控Master和Slave的存活情况,当Master宕机后将Slave提升为Master,并发布事件通知。
该方案的优点是:
- 历史最悠久的Redis高可用方案,大部分的Redis集群都是建立在该方案的基础上的。
- 经过最大量的实践,可靠性得到了充足的验证。
- 运维方式比较简单,不需要引入第三方中间件。
该方案有什么缺点了?
- Redis的容量上限受制于Master所在服务器的内存上限。
- Redis的计算能力受限于Master所在服务器的CPU资源上限。
为了弥补上述缺点,在Redis Cluster
方案出来之前,开源者们提出了数据分片
的概念来解决此问题。
Redis数据分片
数据分片是指将数据的主键通过Hash算法将其路由到不同的Redis Group
中。其中每一个Redis Group
的容量只有传统Replication
的一部分,将压力分摊到每个Redis Group中,其服务端部署图如下所示:
该方案简述如下:
- 每一个
Redis Group
只负责一部分缓存,分配了传统方式Master的内存压力和CPU压力。
- 每一个
Redis Group
可以由Master+Slave+Sentinel
组成,保证高可用。
该方案的优点:
- 内存压力由之前的单台服务器转嫁到了多台服务器,多台服务器可以承担更大的存储要求。
- 将Redis的计算压力进行了分摊,充分利用了多台主机的CPU资源。
那么如何实现该方案了?
客户端分片
客户端分片是客户端在进行Redis操作的时候,在本地就对Key进行hash处理来获取具体对哪台服务器进行操作。
该方法比较简单,只需要在进行操作前,对Key进行Hash处理,然后直接操作对应的Redis服务端即可。
该方式的缺点也是比较明显:
- 如果后端Redis的实例发生变换的时候,就有可能找不到缓存,需要重新从数据库读取并缓存。
- 无法支持涉及多键的操作:例如对Set 1和Set 2 求交集的时候,如果其不在一个Redis中,那么就无法直接操作。
代理分片
代理分片技术有2款重要的开源产品,一款是Twitter的Twemproxy,一款是Codis。
- Twemproxy已经停止维护了,但是因为其功能很简单,所以目前仍然能够满足基本使用。
- Codis可以看做是Twemproxy的一个超集,不仅实现了Twemproxy的所有功能,再引入Codis其他组件的情况下,还能实现Redis服务器动态增减、监控等其他附加功能。
设计架构图如下所示:
- 每一个
redis group
都应该是一个高可用的Redis集群,其架构设计同Replication
,如下所示
- 代理节点因为不应该是单点,所以通过Keepalived来实现高可用。
- 客户端只需要连接Keepavlied暴露的虚拟IP即可。
该架构的优点是:
- 客户端无侵入,因为Proxy实现了Redis的协议,所以之前怎么操作Redis,现在也如何操作,无需客户端代码变更。
- 通过代理的方式引入了数据分片的技术,提高了服务器的资源利用。
其缺点也很明显:
- 因为走了一层代理,多了一层请求转发和响应转发,随意性能会有一定损耗,其该损耗随着数据增大而近乎几何倍增大。
- 服务端Redis服务器增加受到限制。其中TwemProxy完全不支持Redis服务器增加后的自动重新分配,Codis需要使用其维护的Codis Redis Server才能够实现该功能,这样也限制了自身Redis Server的升级,同时因为非官方维护,也存在一定风险。
- 引入了其他中间件,增加了运维难度:单个代理存在单点问题,所以需要类似
Keepalived
的方式来实现高可用。
- 同客户端分片一样,不支持多键操作,比如交集和并集。
服务端分片:Redis 3.0 Cluster
Redis 3.0发布后,官方终于发布了自己的服务端分片技术Redis Cluster
,这是一种去中心化的设计。
其核心原理是在多个Redis实例上平均分配0-16384个槽(slot),每一个Redis实例有部分Slot。然后通过主键进行Hash处理,将结果缓存到对应的slot所在的服务器中,其算法为:hash_slot = crc16(key) mod 16383
下面通过一个简单的例子进行说明:假如有3个Redis的实例,第一个Redis实例有0-5461个slot,第二个实例有5462-10922,第三个实例有10923-16383。有一个Key经过hash取模后得到的slot为3456,那么便会将对应的数据存放在第一个服务器中。
其架构图如下所示:
- 节点之间通过Ping-Pong机制进行存活判定,当半数以上的实例来判定某一个Redis实例宕机,那么该实例宕机
- 因为需要半数确认,所以在做高可用,需要部署3个Master实例,并且每一个Master实例都加一个Slave。该方案最起码需要
3主3从
共6个Redis实例。
- 在Master宕机后,Slave会被自动提升为Master,不需要额外通过Sentinel,客户端只要有1个Master节点可以通信就可以保证服务正常运行。
该架构优点为:
- 客户端使用简单。
- 动态增减Redis实例的时候,服务端可以很方便的进行重新分片,客户端无感知。
- 每一个节点都可以对外提供服务,可以通过ASK 转向/MOVED 转向机制进行请求的转发。
- 相比Codis运维简单,不需要引入第三方中间件。
总结
从部署和运维方式来看,由易到难是如下顺序:
Replication ≈ 客户端分片< 简单代理 ≈ 服务端分片(Cluster)< 中间代理并支持Redis的重新分配
从客户端代码实现复杂度来讲:
Replication ≈ 服务端分片(Cluster) ≈ 简单代理 < 客户端分片 ≈ 中间代理并支持Redis的重新分配
综上所述
- 如果仅仅只需要进行缓存,且该缓存的预期量级单机都能支持的,那么通过Replication进行高可用即可。
- 其他的选型可以根据上述罗列的分类进行选型。
骐骥一跃,不能十步。驽马十驾,功在不舍。