在上周的作业中,我们了解到redis哨兵(sentinel)机制可以实现一定程度的高可用,当master节点出现故障时,通过选举,某一个slave节点会成为新的master节点,从而保证redis服务的持续运行。但是sentinel机制也有弊端,它无法解决单机redis写入的瓶颈问题,单机redis的写入性能受限于单机的内存大小、并发数量和网卡速率等影响。为了解决写入瓶颈问题,提高redis性能,可以采用分布式集群的解决方案。
- 早期redis分布集群部署方案
早期redis分布集群部署方案主要有两种:
①客户端分区:由客户端决定key写分配和写入的redis node,这就需要客户端自身来实现写分配、高可用管理和故障转移等。例如有100000条key,如果觉得都放在同一台redis主机中会造成太大压力,可以增加一台redis主机,将1-50000的key放在node1中,剩余的50000条放在node2中。
②代理方案:基于第三方软件来实现redis proxy(例如早期比较著名的Codis和Twemproxy),客户端先连接到代理层,再由代理层来实现key的写入分配。改方案对客户端来说是会比较简单,但从集群管节点的增减角度来看相对会比较麻烦,而且代理本身也是单点的,具有性能瓶颈。
(Codis解决方案)
(Twemproxy解决方案)
在redis3.0版本之后推出了无中心架构的redis cluster机制,在无中心的redis集群中,每个节点保存当前节点数据和整个集群的状态,每个节点和集群中的其他节点是互相连接的。
- redis cluster特点
redis cluster的特点也就是其工作原理,主要可以归纳为以下几点:
①所有redis node使用ping机制进行互联。
②判定集群中的某个node是否失效,与sentinel机制类似,是由整个集群中超过半数的node监测认定为失效,才能真正被算成是失效的。
③客户端无需经过proxy即可连接到redis,应用程序中需要配置所有的redis服务器ip。由于中间少了一层proxy,不要中间人就直接建立连接,能减少redis性能损失(例如Twemproxy测试损失约为20%),效率也会有所提高。
④redis cluster把所有的redis nodes平均映射到0-16383个槽位(slot)上,读写需要到指定的redis node上进行操作,因此有多少个redis node就相当于redis并发扩展了多少倍,每个redis node承担16384/N个槽位。
⑤redis cluster预先分配16384个槽位,当需要在redis中写入一个k-v键值对时,会使用CRC16(key)mod16384之后的值来决定将k-v键值对写入到哪一个槽位中,由于该槽位是预先分配好的,也就决定了写入的k-v键值对是保存在哪一个redis node上,从而有效解决了单机瓶颈问题。
- redis cluster架构
3.1 redis cluster基本架构
在redis cluster特点的第四点和第五点中,我们了解到要将所有的redis nodes平均映射到所有的槽位上的,假设现在有3个redis node,那么这些node按次序分配到的槽位分别是0-5460、5461-10922和10922-16383,用户在写入一个key时,首先采用CRC16这种方式的哈希算法来得到一个哈希值,再用这个哈希值对槽位总数16384进行取模,取模后得到的值对应的是哪一个槽位,就写入到哪一个node中。
3.2 redis cluster主从架构
上面的基本架构虽然解决了并发问题,但每个node,也就是单个redis master的高可用问题并未解决,因此可以对每个node都是用主从复制架构,从而解决高可用问题。
3.3 redis cluster部署架构说明
由于redis cluster要使用主从架构来解决高可用问题,并且master节点的数量需要设置为奇数以避免脑裂现象的出现,因此总的redis node数量会比较多,如果是实验环境,可以考虑使用单台redis采用多虚拟机的形式。要注意的是,为了避免出现单点失败问题,采用该种方式时不能直接在同一台redis主机上进行主从节点的绑定,而要将本机的主节点与其他主机的从节点错开绑定。
单台主机多实例并不能提高服务器性能,也不能解决容错性问题,如果是生产环境,需要单独选择服务器来作为从节点。