Redis 切片集群

本文将介绍 Redis 中的切片集群。

一、为什么要切片?

当 Redis 中存储的数据非常多时,会有以下两个问题:

  • 内存占用过大:当数据过多时,内存占用可能会非常大,而大内存的服务器一般成本会更高
  • RDB 持久化时间过长:
    • 如果堵塞式 RDB 持久化,则内存越大,持久化时间越长
    • 如果非堵塞式 RDB 持久化,创建子线程时需要执行 fork() 操作,该操作会堵塞父线程,且内存占用越大执行时间越长

可以通过切片集群解决这一问题,多个 Redis 实例组成一个集群,按照一定的规则将数据划分,每个实例保存一部分数据,从而避免单一实例存储过多数据。

二、Redis Cluster

1. 什么是 Redis Cluster ?

Redis Cluster 是从 Redis 3.0 开始官方提供的切片集群的解决方案。

2. 映射关系

Redis Cluster 采用哈希槽的方式来处理数据和实例之间的映射关系,具体步骤为:

  • 一个切片集群共有 16384 个哈希槽,每个哈希槽就是一个数据分区,哈希槽可以均匀分布在每个实例上,也可以手动分配
  • 根据 key,按照 CRC16 算法计算一个 16bit 的值
  • 将 16bit 的值对 16384 取模,放入对应的哈希槽中

3. 映射关系的维护 - 实例之间

  • 初始状态下:集群实例会将自己的哈希槽信息发给集群中的其它实例,当集群互相连接完成后,每个实例都将拥有所有 “哈希槽 - 实例” 的映射关系
  • 映射关系改变时:实例之间相互传递消息,更新 “哈希槽 - 实例” 的映射关系

4. 映射关系的维护 - 客户端

  • 初始状态下:客户端与集群实例建立连接之后,实例就会将 “哈希槽 - 实例” 的映射关系发送给客户端,客户端可以自行计算哈希槽,向对应的实例发送请求

  • 映射关系改变时:

    • 如果数据的迁移已完成,实例会向客户端发送 MOVED 指令,让客户端更新映射关系,以便向新的实例获取数据

      1
      2
      GET hello:key
      (error) MOVED 13320 172.16.19.5:6379
    • 如果数据的迁移未完成,实例会向客户端发送 ASK 指令,让客户端向新的实例请求是否可以获取数据

      1
      2
      GET hello:key
      (error) ASK 13320 172.16.19.5:6379

参考