Redis的集群解决方案

192 阅读10分钟

Redis相关文章

Redis主从模式

主从模式原理

顾名思义,将集群区分成一个主节点多个从节点,读写分离架构,主节点负责写入数据也可以读数据,从节点同步主节点的数据写入做备份,同时支持读操作。

从节点如何处理key的过期

  • 根本原因

    • 从节点不会让 key 过期,而是等待主节点让 key 过期。当主节点让一个key到期时,会下发del命令并传输到所有的从节点。
  • Redis的两种删除策略

    • 惰性删除:当数据过期后,并不会马上删除。而是等到有请求访问时,对数据检查,如果数据过期,则删除数据。
    • 定期删除:每隔一段时间,默认100ms,Redis会随机挑选一定数量的Key,检查是否过期,并将过期的数据删除
  • 当读数据请求打到主节点访问删除数据时,主节点会触发惰性删除。但当请求达到从节点则可能读到旧数据,一般有两种原因。

    • Redis3.2之前版本,读从库并不会判断数据是否过期。
      • 解决方案: 可以将版本升级到3.2版本后。
    • 跟过期时间的设置方式有关系,我们一般采用 EXPIRE key ttl命令,表示从执行命令那个时刻开始,往后延长ttl 时间。主从复制是异步行为,必然会出现延迟情况,所以ttl时间的开始时间会出现不一致情况。
      • 解决方案: 采用Redis的另外两个命令,EXPIREAT key timestam 和 PEXPIREAT key timestamp避免由主从同步命令导致的开始时间延迟问题。

Redis replication

Redis复制过程

  1. 重要概念:

    1. 服务器的唯一id:每个 Redis 服务器在运行期间都有自己的run ID,run ID在服务器启动的时候自动生成。
    2. 复制偏移量 offset:主服务器和从服务器都会维护一个复制偏移量
  2. Redis从2.8以后使用PSYNC命令代替SYNC命令来执行复制时的同步操作

  3. slave刚上线的复制过程

  4. 设置主服务器的ip+端口

    1. 建立套接字链接
    2. 发送ping命令
    3. 验证身份
    4. 向主服务器发送Slave的端口
    5. 同步PSYNC命令具有完整同步增量同步
  5. 全量同步

    1. 用于初次复制或其他无法进行部分复制的情况,将主节点中的所有数据都发送给从节点
    2. SlaveMaster发送PSYNC请求
    3. 主服务器开启后台保护进程创建RDB快照并发送给从服务器,同时将产生快照阶段产生的新的操作命令存储到缓存区
    4. Master向Slave同步存储缓存区的操作命令
  6. 增量同步

    1. 用于网络中断等情况后的复制,只将中断期间主节点执行的写命令发送给从节点,与全量复制相比更加高效。需要注意的是,如果网络中断时间过长,导致主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制。
    2. Redis 主库接收到写操作的命令,首先会写入replication buffer(主要用于主从数据传输的数据缓冲),同时也会把这些操作命令也写入repl_backlog_buffer这个缓冲区。
    3. 如何主从断开了,当然对应的replication buffer也就没有了。这时候就依赖repl_backlog_buffer进行数据的增量同步了。repl_backlog_buffer是一个环形缓冲区,主库会记录自己写到的位置,从库则会记录自己已经读到的位置。
    4. 使用PSYNC {offset} {replication id}实现
    5. Master每执行一个写命令就会向Slave发送相同的写命令。然后Slave接收并执行

新增从库的过程

  1. 从库使用PSYNC请求同步,首次链接不会指定replcationid和offset
  2. master节点收到命令判断为全量同步后就会将自己的replcationid和offset告知slave,回复命令full resync {runId} {offset}。同时,master会执行bgsave命令来生成rdb文件,期间的所有写命令将被写入缓冲区。
  3. master bgsave执行完毕,向slave发送rdb文件。rdb文件发送完毕后,开始向slave发送缓冲区中的写命令。
  4. slave收到rdb文件,丢弃所有旧数据,开始载入rdb文件。
  5. rdb文件同步结束之后,slave执行从master缓冲区发送过来的所有写命令。
  6. 此后 master 每执行一个写命令,就向slave发送相同的写命令。

主从模式数据丢失问题

  1. 无法严格避免数据丢失问题,只能尽可能减轻
  2. redis配置文件中有两个配置
min-slaves-to-write 1
min-slaves-max-lag 10
  • min-slaves-to-write默认情况下是0,min-slaves-max-lag默认情况下是10。

  • 上述参数表示至少有1个salve的与master的同步复制延迟不能超过10s,一旦所有的slave复制和同步的延迟达到了10s,那么此时master就不会接受任何请求,系统故障。

  • 通过降低min-slaves-max-lag参数的值,可以避免在发生故障时大量的数据丢失,一旦发现延迟超过了该值就不会往master中写入数据发生故障。

  • 应对方案

    1. 一定场景下用主写主读策略
    2. 保证主从网络相同机房顺畅,监控从节点如果与主节点差距过大将该剔出集群,不在接受读请求。

Redis哨兵模式

哨兵模式原理

  1. Redis 哨兵模式(Sentinel)就是一个自动地监控处理 redis 间故障节点转移工作的一个程序,准确来说,Sentinel 其实是一个 redis 服务端程序,只不过运行在特殊的模式下,不提供数据存储服务,只进行普通 redis 节点监控管理。
  2. 通过不断发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
  3. 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。配置也会修改
  4. 一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式
  5. 故障切换:假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行故障转移过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行故障切换操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的。
  6. 在哨兵sentinel机制中,可以解决redis高可用问题,即当master故障后可以自动将slave提升为master,从而可以保证redis服务的正常使用,但是无法解决redis单机写入的瓶颈问题,即单机redis写入性能受限于单机的内存大小、并发数量、网卡速率等因素。

哨兵工作模式

  1. 每个Sentinel以每秒钟一次的频率向mster、slave、其他sentinel发送ping命令
  2. 如果一个实例(instance)距离最后一次有效回复PING命令的时间超过 own-after-milliseconds 选项所指定的值,则这个实例会被Sentinel标记为主观下线。
  3. 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。
  4. 当有足够数量的Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态,则Master会被标记为客观下线。
  5. 在一般情况下,每个Sentinel 会以每10秒一次的频率向它已知的所有Master,Slave发送 INFO 命令。
  6. 当Master被Sentinel标记为客观下线时,Sentinel 向下线的 Master 的所有Slave发送 INFO命令的频率会从10秒一次改为每秒一次。
  7. 若没有足够数量的Sentinel同意Master已经下线,Master的客观下线状态就会被移除。 若 Master重新向Sentinel 的PING命令返回有效回复,Master的主观下线状态就会被移除。

主备切换过程

  1. 假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线
  2. 当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行故障切换操作。
  3. 切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的。

Redis集群模式

Redis cluster集群原理

  1. 哨兵模式只解决了redis高可用问题,及时将挂掉了master换掉,但无法解决redis单机写入的瓶颈问题
  2. 由多个Redis服务器组成的分布式网络服务集群;至少6台redis服务器3主3从
  3. 集群之中有多个Master主节点,每一个主节点都可读可写;
  4. 节点之间会互相通信,两两相连;
  5. Redis集群无中心节点。可以理解成多个哨兵模式,基于Raft算法管理集群

数据分片机制

  1. Redis的分布式解决方案,分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集
  2. 采用hash槽分区
  3. 所有的键根据hash函数映射到0-16384整数槽内,根据公式:slot = CRC16(ey) & 16384,每个节点负责维护一部分槽一级槽所映射的键值数据
  4. Redis虚拟槽分区的特点
    1. 解耦数据和节点之间的关系,简化了节点扩容和收缩难度。
    2. 节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据
    3. 支持节点、槽和键之间的映射查询,用于数据路由,在线集群伸缩等场景。
  1. 如果集群中新增节点需要从已有节点删除一些hash slot给新节点,同理删除节点也应该将删除节点上的hash slot移动到现有的节点