Redis-集群
本文最后更新于:1 年前
[TOC]
概述
Redis有三种主要的集群模式,用于在分布式环境中实现高可用性和数据复制。这些集群模式分别是:主从复制(Master-Slave Replication)、哨兵模式(Sentinel)和Redis Cluster模式。
主从模式
主从复制是Redis最简单的集群模式。这个模式主要是为了解决单点故障的问题,所以将数据复制多个副本中,这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务。
主从模式中,包括一个主节点(Master)和一个或多个从节点(Slave)。主节点负责处理所有写操作和读操作,而从节点则复制主节点的数据,并且只能处理读操作。当主节点发生故障时,可以将一个从节点升级为主节点,实现故障转移(需要手动实现)。
缺点:无法自动故障转移
哨兵模式
为了解决主从模式的无法自动容错及恢复的问题,Redis引入了一种哨兵模式的集群架构。
哨兵模式是在主从复制的基础上加入了哨兵节点。哨兵节点是一种特殊的Redis节点,用于监控主节点和从节点的状态。当主节点发生故障时,哨兵节点可以自动进行故障转移,选择一个合适的从节点升级为主节点,并通知其他从节点和应用程序进行更新。
集群模式
Redis Cluster是Redis中推荐的分布式集群解决方案。它将数据自动分片到多个节点上,每个节点负责一部分数据。
Redis Cluster采用主从复制模式来提高可用性。每个分片都有一个主节点和多个从节点。主节点负责处理写操作,而从节点负责复制主节点的数据并处理读请求。
Redis Cluster能够自动检测节点的故障。当一个节点失去连接或不可达时,Redis Cluster会尝试将该节点标记为不可用,并从可用的从节点中提升一个新的主节点。
Redis Cluster是适用于大规模应用的解决方案,它提供了更好的横向扩展和容错能力。它自动管理数据分片和故障转移,减少了运维的负担。
Cluster模式的特点是数据分片存储在不同的节点上,每个节点都可以单独对外提供读写服务。不存在单点故障的问题。
项目:30 分片,单实例 2000MB
数据分片
Redis的数据分片(sharding)是一种将一个Redis数据集分割成多个部分,分别存储在不同的Redis节点上的技术。它可以用于将一个单独的Redis数据库扩展到多个物理机器上,从而提高Redis集群的性能和可扩展性。
Redis数据分片的实现方式通常是将数据按照某种规则(例如,key的hash值)分配到不同的节点上。当客户端想要访问某个key时,它会先计算出这个key应该存储在哪个节点上,然后直接连接到该节点进行操作。因此,对于客户端而言,Redis集群就像是一个大型的、统一的数据库,而不需要关心数据的实际分布情况。
在Redis的Cluster 集群模式中,使用哈希槽(hash slot)的方式来进行数据分片,将整个数据集划分为多个槽,每个槽分配给一个节点。客户端访问数据时,先计算出数据对应的槽,然后直接连接到该槽所在的节点进行操作。Redis Cluster还提供了自动故障转移、数据迁移和扩缩容等功能,能够比较方便地管理一个大规模的Redis集群。
Redis Cluster将整个数据集划分为16384(2 的 14 次方)个槽,每个槽都有一个编号(0~16383),集群的每个节点可以负责多个hash槽,客户端访问数据时,先根据key计算出对应的槽编号,然后根据槽编号找到负责该槽的节点,向该节点发送请求。
在 Redis 的每一个节点上,都有这么两个东西,一个是槽(slot),它的的取值范围是:0-16383。还有一个就是 cluster,可以理解为是一个集群管理的插件。当我们的存取的 Key 的时候,Redis 会根据 CRC16 算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
Redis 通信
Redis 使用自己设计的一种文本协议进行客户端与服务端之间的通信——RESP(REdis Serialization Protocol),这种协议简单、高效,易于解析,被广泛使用。
RESP 协议基于 TCP 协议,采用请求/响应模式。
redis memcached
Redis 和 Memcached 都是常见的缓存服务器,它们的主要区别包括以下几个方面:
- 数据结构不同:Redis 提供了多种数据结构,如字符串、哈希表、列表、集合、有序集合等,而 Memcached 只支持简单的键值对存储。
- 持久化方式不同:Redis 支持多种持久化方式,如 RDB 和 AOF,可以将数据持久化到磁盘上;而 Memcached 不支持持久化。
- 数据分片方式不同:Redis 使用哈希槽分片,可以实现数据的自动分片和负载均衡;而 Memcached 只能手动分片。
- 处理数据的方式不同:Redis 使用单线程处理数据请求,支持事务、Lua 脚本等高级功能;而 Memcached 使用多线程处理数据请求,只支持基本的 GET、SET 操作。
- 协议不同:Redis 使用自己的协议,支持多个数据库,可以使用密码进行认证;而 Memcached 使用文本协议,只支持一个默认数据库。
- 内存管理方式不同:Redis 的内存管理比 Memcached 更加复杂,支持更多的内存优化策略。
综上所述,Redis 和 Memcached 有着不同的设计理念和应用场景。Redis 适用于数据结构复杂、需要高级功能和数据持久化的场景;而 Memcached 则适用于简单的键值存储场景。
主从复制
主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。
slaveof 命令
部分复制:偏移量,积压缓冲区,服务器运行 id
主从复制的作用
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
- 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
- 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
- 高可用基石:主从复制还是哨兵和集群能够实施的基础,因此说主从复制是 Redis 高可用的基础。
主从复制实现原理
Redis 的复制分为全量同步和增量同步。
如果主库发现从库传来的复制 id 和自己的 replid、replid2 都不同,或者复制偏移不在复制积压缓冲中,则判定需要进行全量复制。
master 发送 fullresync 响应,附带 replid 及复制偏移。然后, master 根据需要构建 rdb,并将 rdb 及复制缓冲发送给 slave。
哨兵模式
Redis 的主从复制模式下,一旦主节点由于故障不能提供服务,需要手动将从节点晋升为主节点,同时还要通知客户端更新主节点地址,这种故障处理方式从一定程度上是无法接受的。
Redis Sentinel 是 Redis 高可用的实现方案。Sentinel 是一个管理多个 Redis 实例的工具,它可以实现对 Redis 的监控、通知、自动故障转移。
哨兵模式的原理
哨兵模式的主要作用在于它能够自动完成故障发现和故障转移,并通知客户端,从而实现高可用。哨兵模式通常由一组 Sentinel 节点和一组(或多组)主从复制节点组成。
心跳机制
(1)Sentinel 与 Redis Node
Redis Sentinel 是一个特殊的 Redis 节点。在哨兵模式创建时,需要通过配置指定 Sentinel 与 Redis Master Node 之间的关系,然后 Sentinel 会从主节点上获取所有从节点的信息,之后 Sentinel 会定时向主节点和从节点发送 info 命令获取其拓扑结构和状态信息。
(2)Sentinel 与 Sentinel
基于 Redis 的订阅发布功能, 每个 Sentinel 节点会向主节点的 sentinel:hello 频道上发送该 Sentinel 节点对于主节点的判断以及当前 Sentinel 节点的信息 ,同时每个 Sentinel 节点也会订阅该频道, 来获取其他 Sentinel 节点的信息以及它们对主节点的判断。
通过以上两步所有的 Sentinel 节点以及它们与所有的 Redis 节点之间都已经彼此感知到,之后每个 Sentinel 节点会向主节点、从节点、以及其余 Sentinel 节点定时发送 ping 命令作为心跳检测, 来确认这些节点是否可达。
故障转移
每个 Sentinel 都会定时进行心跳检查,当发现主节点出现心跳检测超时的情况时,此时认为该主节点已经不可用,这种判定称为主观下线。
之后该 Sentinel 节点会通过 sentinel ismaster-down-by-addr 命令向其他 Sentinel 节点询问对主节点的判断, 当 quorum(法定人数) 个 Sentinel 节点都认为该节点故障时,则执行客观下线,即认为该节点已经不可用。这也同时解释了为什么必须需要一组 Sentinel 节点,因为单个 Sentinel 节点很容易对故障状态做出误判。
这里 quorum 的值是我们在哨兵模式搭建时指定的,后文会有说明,通常为 Sentinel 节点总数/2+1,即半数以上节点做出主观下线判断就可以执行客观下线。
因为故障转移的工作只需要一个 Sentinel 节点来完成,所以 Sentinel 节点之间会再做一次选举工作, 基于 Raft 算法选出一个 Sentinel 领导者来进行故障转移的工作。
被选举出的 Sentinel 领导者进行故障转移的具体步骤如下
(1)在从节点列表中选出一个节点作为新的主节点
过滤不健康或者不满足要求的节点;
选择 slave-priority(优先级)最高的从节点, 如果存在则返回, 不存在则继续;
选择复制偏移量最大的从节点 (主从复制的多的), 如果存在则返回, 不存在则继续;
选择 runid 最小的从节点。
(2)Sentinel 领导者节点会对选出来的从节点执行 slaveof no one 命令让其成为主节点。
(3)Sentinel 领导者节点会向剩余的从节点发送命令,让他们从新的主节点上复制数据。
(4)Sentinel 领导者会将原来的主节点更新为从节点, 并对其进行监控, 当其恢复后命令它去复制新的主节点。
集群
哨兵模式最大的缺点就是所有的数据都放在一台服务器上,无法较好的进行水平扩展。
为了解决哨兵模式存在的问题,集群模式应运而生。在高可用上,集群基本是直接复用的哨兵模式的逻辑,并且针对水平扩展进行了优化。
集群模式具备的 4 特点如下
- 采取去中心化的集群模式,将数据按槽存储分布在多个 Redis 节点上。集群共有 16384 个槽,每个节点负
责处理部分槽。 - 使用 CRC16 算法来计算 key 所属的槽:crc16(key,keylen) & 16383。
- 所有的 Redis 节点彼此互联,通过 PING-PONG 机制来进行节点间的心跳检测。
- 分片内采用一主多从保证高可用,并提供复制和故障恢复功能。在实际使用中,通常会将主从分布在不同
机房,避免机房出现故障导致整个分片出问题。 - 客户端与 Redis 节点直连,不需要中间代理层(proxy)。客户端不需要连接集群所有节点,连接集群中任
何一个可用节点即可。
通过算法设计,计算出 key 应该保存的位置
所有的存储空间计划切割成16384份,每台主机保存一部分,每份代表的是一个存储空间,不是一个 key 的保存空间,将 key 按照计算出的结果放到对应的存储空间。
集群内部通讯设计
Key—计算槽在哪?==命中?未命中?最多两次
如何保证集群在线扩容的安全性?(Redis 集群要增加分片,槽的迁移怎么保证无损)
集群已经对外提供服务,原来有 3 分片,准备新增 2 个分片,怎么在不下线的情况下,无损的从原有的 3 个
分片指派若干个槽给这 2 个分片?
Redis 使用了 ASK 错误来保证在线扩容的安全性。
在槽的迁移过程中若有客户端访问,依旧先访问源节点,源节点会先在自己的数据库里面査找指定的键,如果找到的话,就直接执行客户端发送的命令。
如果没找到,说明该键可能已经被迁移到目标节点了,源节点将向客户端返回一个 ASK 错误,该错误会指引客户端转向正在导入槽的目标节点,并再次发送之前想要执行的命令,从而获取到结果。