共计 5830 个字符,预计需要花费 15 分钟才能阅读完成。
Redis的四种部署模式——单机 主从 哨兵 集群
概述
Redis 是一个开源,高级的键值存储和一个适用的解决方案,用于构建高性能,可扩展的 Web 应用程序。它有三个主要特点,使其优越于其它键值数据存储系统:
● Redis 将其数据库完全保存在内存中,仅使用磁盘进行持久化。
● 与其它键值数据存储相比,Redis 有一组相对丰富的数据类型。
● Redis 可以将数据复制到任意数量的从机中。
单机模式
单机模式就是只有一个节点提供服务,结构简单,可靠性低,处理能力弱。
优点:
- 架构简单,部署方便;
- 成本低,没有备用节点,不需要其他的开支。
- 高性能,单机不需要同步数据,数据天然一致性。
- 高性价比:缓存使用时无需使用备用节点,为了满足业务的高可用性,也可以部署一个备用节点,但同一时刻只有一个实例对外提供服务
缺点:
- 不保证数据的可靠性,可靠性保证不是很好,单节点有宕机的风险,无法保证数据的可靠性。即使有备用的节点解决高可用性,但是仍然不能解决缓存预热问题,因此不适用于对数据可靠性要求高的业务;
- 高性能受限于单核CPU的处理能力(Redis是单线程机制 6.0以后版本支持多线程),CPU为主要瓶颈,所以适合操作命令简单,排序、计算较少的场景。也可以考虑用Memcached替代。
- 缓存使用,进程重启后,数据丢失,即使有备用的节点解决高可用性,但是仍然不能解决缓存预热问题,因此不适用于数据可靠性要求高的业务;
- 内存容量有限
主从复制
主从模式是指通过执行 slaveof 命令或设置 slaveof 选项,让一个服务器去复制另一个服务器的数据。被复制的服务器称为:Master主服务;对主服务器进行复制的服务器称为:Slave从服务器。
主服务器可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从服务器。而从服务器一般是只读的,并接受主服务器同步过来的数据。
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。
前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点
主从模式工作原理
主从具体工作机制为(全量复制(初始化)+增量复制),如下图所示:
- 从服务器Slave向主服务器Master发送SYNC命令
- Master接收到SYNC命令后,通过bgsave保存快照,生成RDB文件,同时使用缓冲区记录从现在开始执行的所有的写命令
- Master将快照文件(RDB文件)发送给Slave,Slave接收到快照文件后,载入数据
- Master快照发送完后开始向Slave发送缓冲区的写命令,Slave接收命令并执行,完成复制初始化
- 此后Master每次执行一个写命令都会同步发送给Slave,保持Master与Slave之间数据的一致性
优点:
- 一旦主节点宕机,从节点作为主节点的备份可以随时顶上来
- Master能自动将数据同步到Slave,可以进行读写分离,分担Master的读压力
- Master、Slave之间的同步是以非阻塞bgsave的方式进行的,同步期间,客户端仍然可以提交查询或更新请求
- 高可用基石:除了上述作用以外,主从复制还是哨兵模式和集群模式能够实施的基础,因此说主从复制是Redis高可用的基石
缺点:
- 不具备自动容错与恢复功能,master或slave的宕机都可能导致客户端请求失败,需要等待机器重启或手动切换客户端IP才能恢复
- Master宕机,如果宕机前数据没有同步完,则切换IP后会存在数据不一致的问题
- 难以支持在线扩容,Redis的容量受限于单机配置,主节点读、写能力 受到单机的限制
主节点宕机的解决:
当主节点宕机后,此时需要让从节点顶替主节点,只要在从节点执行 slaveof no one 即可。当宕机节点恢复,可以重新执行命令把原先宕机并恢复的节点挂到新的 Master 节点之上。
哨兵模式
由于无法进行主动恢复,因此主从模式衍生出了哨兵模式。哨兵模式基于主从复制模式,只是引入了哨兵来监控与自动处理故障,在复制的基础上,哨兵实现了自动化的故障恢复:
如图,哨兵节点由两部分组成,哨兵节点和数据节点:
哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据。
数据节点:主节点和从节点都是数据节点。
哨兵模式工作机制
由一个或多个Sentinel去监听任意多个主服务以及主服务器下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线的主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已经下线的从服务器,并且Sentinel可以互相监视。
哨兵模式故障恢复
哨兵认为master客观下线后,故障恢复的操作需要由选举的领头哨兵来执行,选举采用Raft算法:
- 发现master下线的哨兵节点(我们称他为A)向每个哨兵发送命令,要求对方选自己为领头哨兵;
- 如果目标哨兵节点没有选过其他人,则会同意选举A为领头哨兵;
- 如果有超过一半的哨兵同意选举A为领头,则A当选;
- 如果有多个哨兵节点同时参选领头,此时有可能存在一轮投票无竞选者胜出,此时每个参选的节点等待一个随机时间后再次发起参选请求,进行下一轮投票竞选,直至选举出领头哨兵
选出领头哨兵后,领头者开始对系统进行故障恢复,从出现故障的master的从数据库中挑选一个来当选新的master,选择规则如下:
- 所有在线的slave中选择优先级最高的,优先级可以通过slave-priority配置。
- 如果有多个最高优先级的slave,则选取复制偏移量最大(即复制越完整)的当选
- 如果以上条件都一样,选取id最小的slave
- 挑选出需要继任的slave后,领头哨兵向该数据库发送命令使其升级为master,然后再向其他slave发送命令接受新的master,最后更新数据
- 将已经停止的旧的master更新为新的master的从数据库,使其恢复服务后以slave的身份继续运行
优点:
- 哨兵模式基于主从复制模式,所以主从复制模式有的优点,哨兵模式也有
- 主从可以自动切换,系统更健壮,可用性更高,master挂掉可以自动进行切换,系统可用性更高
- Sentinel 会不断的检查 主服务器 和 从服务器 是否正常运行。当被监控的某个 Redis 服务器出现问题,Sentinel 通过API脚本向管理员或者其他的应用程序发送通知
缺点:
- 同样也继承了主从模式难以在线扩容的缺点,Redis的容量受限于单机配置
- 需要额外的资源来启动sentinel进程,实现相对复杂一点,同时slave节点作为备份节点不提供服务
集群模式
主从不能解决故障自动恢复问题,哨兵已经可以解决故障自动恢复了,那到底为啥还要集群模式呢?
主从和哨兵都还有另外一些问题没有解决,单个节点的存储能力是有上限,访问能力是有上限的。
Redis Cluster 集群模式具有 高可用、可扩展性、分布式、容错 等特性。
一般要实现一个Redis集群,可以有三种方式:客户端实现、Proxy代理层实现、服务端实现
Cluster 集群模式的原理
服务端的实现方式是标准的集群(分区分片)模式
分布式集群首要解决的问题是如何把整个数据集按照分区规则映射到多个节点,即把数据集划分到多个节点上,每个节点负责整个数据的一个子集。
服务端的集群模式实现了Redis的分布式存储,即每台节点存储不同的内容,来解决在线扩容的问题。当遇到单机内存、并发、流量等瓶颈时,可以采用Cluster架构达到负载均衡的目的,如图:
通过数据分片的方式来进行数据共享问题,同时提供数据复制和故障转移功能。
之前的两种模式数据都是在一个节点上的,单个节点存储是存在上限的。集群模式就是把数据进行分片存储,当一个分片数据达到上限的时候,就分成多个分片。
数据分片怎么分?
集群的键空间被分割为16384个slots(即hash槽),通过hash的方式将数据分到不同的分片上的。
HASH_SLOT = CRC16(key) & 16384
CRC16是一种循环校验算法,这里用了位运算得到取模结果,位运算的速度高于取模运算。
数据分片之后怎么查,怎么写?
读请求分配给slave节点,写请求分配给master,数据同步从master到slave节点。
读写分离提高并发能力,增加高性能。
如何做到水平扩展?
master节点可以做扩充,数据迁移redis内部自动完成。
当你新增一个master节点,需要做数据迁移,redis服务不需要下线。
举个栗子:上面的有三个master节点,意味着redis的槽被分为三个段,假设三段分别是07000,700112000、12001~16383。
现在因为业务需要新增了一个master节点,四个节点共同占有16384个槽。
槽需要重新分配,数据也需要重新迁移,但是服务不需要下线。
redis集群的重新分片由redis内部的管理软件redis-trib负责执行。redis提供了进行重新分片的所有命令,redis-trib通过向节点发送命令来进行重新分片。
如何做故障转移?
假如途中红色的节点故障了,此时master3下面的从节点会通过 选举 产生一个主节点。替换原来的故障节点。
此过程和哨兵模式的故障转移是一样的。
集群模式工作机制
- 在Redis的每个节点上,都有一个插槽(slot),总共16384个哈希槽,取值范围为0-16383。跟前三种模式不同,集群模式的Redis不再是16(0-15)个库,也没有默认的0库说法,而是采用Slot的设计(一个集群有多个主从节点,一个主从节点上会分配多个Slot槽,每个槽点上存的是Key-Value数据)。
- 当我们存取key的时候,Redis会根据CRC16的算法得出一个结果,然后把结果对16384求余数,这样每个key都会对应一个编号在0-16383之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。如图所示:
- 为了保证高可用,Cluster模式也引入主从复制模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点
- 当其它主节点ping一个主节点A,如果半数以上的主节点与A通信超时,那么就认为主节点A宕机了。如果主节点A和它的从节点都宕机了,那么该集群就无法再提供服务了
Cluster模式集群节点最小配置6个节点(3主3从,因为需要半数以上),其中主节点提供读写操作,从节点作为备用节点,不提供请求,只作为故障转移使用。
优点:
- 无中心架构
- 数据按照slot存储分布在多个节点,节点间数据共享,可动态调整数据分布
- 可扩展性:可线性扩展到1000多个节点,节点可动态添加或删除
- 高可用性:部分节点不可用时,集群仍可用。通过增加Slave做standby数据副本,能够实现故障自动failover,节点之间通过gossip协议交换状态信息,用投票机制完成Slave到Master的角色提升
- 降低运维成本,提高系统的扩展性和可用性
缺点:
- Client实现复杂,驱动要求实现Smart Client,缓存slots mapping信息并及时更新,提高了开发难度,客户端的不成熟影响业务的稳定性。目前仅JedisCluster相对成熟,异常处理部分还不完善,比如常见的“max redirect exception”。
- 节点会因为某些原因发生阻塞(阻塞时间大于clutser-node-timeout),被判断下线,这种failover是没有必要的。
- 数据通过异步复制,不保证数据的强一致性。
- 多个业务使用同一套集群时,无法根据统计区分冷热数据,资源隔离性较差,容易出现相互影响的情况。
- Slave在集群中充当“冷备”,不能缓解读压力,当然可以通过SDK的合理设计来提高Slave资源的利用率。
- Key批量操作限制,如使用mset、mget目前只支持具有相同slot值的Key执行批量操作。对于映射为不同slot值的Key由于Keys不支持跨slot查询,所以执行mset、mget、sunion等操作支持不友好。
- Key事务操作支持有限,只支持多key在同一节点上的事务操作,当多个 – Key分布于不同的节点上时无法使用事务功能。
- Key作为数据分区的最小粒度,不能将一个很大的键值对象如hash、list等映射到不同的节点。
- 不支持多数据库空间,单机下的redis可以支持到16个数据库,集群模式下只能使用1个数据库空间,即db 0。
- 复制结构只支持一层,从节点只能复制主节点,不支持嵌套树状复制结构。
- 当产生hot-key时,会导致主库节点成为系统的短板。
- 当产生big-key,会导致网卡撑爆、慢查询等。
- Redis Cluster不建议使用pipeline和multi-keys操作,减少max redirect产生的场景