前言
Redis 缓存作为使用最多的缓存工具被各大厂商争相使用。通常我们会使用单体的 Redis 应用作为缓存服务,然而我们日常在对于redis的使用中,经常会遇到一些问题:
- 高可用问题,如何保证redis的持续高可用性。
- 容量问题,单实例redis内存无法无限扩充,达到32G后就进入了64位世界,性能下降。
- 并发性能问题,redis号称单实例10万并发,但也是有尽头的。
如果只使用一个redis实例时,其中保存了服务器中全部的缓存数据,这样会有很大风险,如果单台redis服务宕机了将会影响到整个服务。解决的方法就是我们可以采用分片/分区的技术,将原来一台服务器维护的整个缓存,现在换为由多台服务器共同维护内存空间。下面对高可用和高并发处理方案进行介绍。
redis分片原理
redis分片概念:按照某种规则去划分数据,分散存储在多个节点上。通过将数据分到多个 Redis 服务器上,来减轻单个 Redis 服务器的压力。
分片思路:采用在一台主机上实现分片的方式,所以只需要在该主机上配置启动三台redis的实例即可。因为redis默认使用的端口号为6379,所以这里我们分别使用6379、6380以及6381三个端口来实现。
分片算法:分片方式虽然解决了高可用的问题,但是分片后数据如何均匀的分步到每个机器上呢?
【重点】实现数据均匀分布在多个节点方式:
①普通的HASH算法
通常的做法就是获取节点的 Hash 值,然后根据节点数求模。 hash(key) % length
但是当缓存服务器变化时(宕机或新增节点),length字段变化,导致所有缓存的数据需要重新进行HASH运算,这样就导致原来的哪些数据访问不到了。而这段时间如果访问量上升了,容易引起服务器雪崩。因此,引入了一致性哈希算法。
②一致性 Hash 算法
该算法对 2^32 取模,将 Hash 值空间组成虚拟的圆环,整个圆环按顺时针方向组织,每个节点依次为 0、1、2…2^32-1。
- 将每个服务器进行 Hash 运算,对 2^32 取模,确定服务器在这个 Hash 环上的地址,确定了服务器地址后,对数据使用同样的 Hash 算法,将数据定位到特定的 Redis 服务器上。
- 如果定位到的地方没有 Redis 服务器实例,则继续顺时针寻找,找到的第一台服务器即该数据最终的服务器位置。
Hash 环的数据倾斜问题:
Hash 环在服务器节点很少的时候,容易遇到服务器节点不均匀的问题,这会造成数据倾斜,数据倾斜指的是被缓存的对象大部分集中在 Redis 集群的其中一台或几台服务器上。
如上图,一致性 Hash 算法运算后的数据大部分被存放在 A 节点上,而 B 节点只存放了少量的数据,久而久之 A 节点将被撑爆。我们可以通过虚拟节点的方式解决Hash环的偏移。
如果想要均衡的将缓存分布到这三台服务器上,最好能让这三台服务器尽量多的,均匀的出现在Hash环上,但是,真实的服务器资源只有3台,那么如何凭空的让他们多起来呢?
做法就是既然没有多余的真正的物理服务器节点,我们就可能将现有的物理节点通过虚拟的方法复制出来,而被复制出来的节点被称为“虚拟节点”
简单地说,就是为每一个服务器节点计算多个 Hash,每个计算结果位置都放置一个此服务器节点,称为虚拟节点,可以在服务器 IP 或者主机名后放置一个编号实现。例如上图:将 NodeA 和 NodeB 两个节点分为 Node A#1-A#3,NodeB#1-B#3。
一致性Hash能解决容灾问题吗?
我们假设有5台服务器,有a,f,c对象映射在A服务器上,r,t,v对象映射在E服务器上。如下图:
假如此时E服务器宕机了,其他服务器的对象仍然能被命中,因为对象的映射到服务器的位置已经固定了,不会出现因为宕机而让对象找不到。而宕机E上的对象会在下次容灾分配的时候,会把r,t,v这些对象重新分配到就近的服务器上,如下图:
分区的不足:
- 分区是多台redis共同作用的,如果其中一台出现了宕机现象,则整个分片都将不能使用,虽然是在一定程度上缓减了内存的压力,但是没有实现高可用。
- 涉及多个key的操作通常是不被支持的。举例来说,当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作。
- 涉及多个key的redis事务不能使用。
- 当使用分区时,数据处理较为复杂,比如你需要处理多个rdb/aof文件,并且从多个实例和主机备份持久化文件。
高可用的解决方案:可以采用哨兵机制实现主从复制从而实现高可用。
redis-cluster 常用方案
所谓集群,就是通过添加服务器的数量,提供相同的服务,从而使服务器达到一个稳定、高效的状态。为什么要使用Redis集群?
- 因为单台的Redis服务器一旦宕机,就无法正常的提供服务了;
- 单台Redis服务器的读写性能有限,利用集群可以提高读写能力
总结起来使用集群的原因可以归为提高服务器的稳定性和提高读写能力。
(1)主从模式
【主从同步,读写分离】
像MySQL一样,redis是支持主从同步的,而且也支持一主多从以及多级从结构。特点:
- 主从结构,一是为了纯粹的冗余备份,二是为了提升读性能,主服务器负责写,从服务器负责读。
- redis的主从同步是异步进行的,这意味着主从同步不会影响主逻辑,也不会降低redis的处理性能。
- 主从架构中,可以考虑关闭主服务器的数据持久化功能,只让从服务器进行持久化,这样可以提高主服务器的处理性能。
因此,主从模型可以很大的提高数据库读的能力,也能间接的提高写的能力,由于在Slave中分担Master读的压力,使Master中有更多的资源可以分配到写资源中。
【主从同步原理】
①全量复制<