redis切片集群:数据增多如何保存

92 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

前言

redis在使用过程中,如果遇到未预知的剧烈数据量增长,整个实例容量不够时,你会如何应对?可能大家最容易想到的方案就是扩容了。比如当前实例配置是16g内存的,那么就扩容到32g。

表面来看方案没有问题,但是在扩容后续使用中,有可能会出现响应很慢的问题。这是怎么回事呢?让我们一探究竟。

redis保存更多数据的方法

redis为保存更多数据,总的来说分为横向扩展和纵向扩展:

  • 纵向扩展:升级单个redis实例的资源配置,包括增加内存容量、磁盘容以及换更高配置的CPU。
  • 横向扩展:横向增加当前redis实例的个数,也就是搭建切片集群。

image.png

两种方法优缺点也很容易分析:

  • 纵向扩展
  1. 优点是部署方便简单,直接升级实例配置
  2. 缺点就是如果使用rdb持久化,数据量大,在主线程fork子进程时容易阻塞;而且扩展的硬件成本高。
  • 横向扩展
  1. 优点是容量扩展方便,只需要增加redis的实例个数。
  2. 缺点就是数据分布在各个切片中,数据的管理有难度。

可以看出,横向扩展的优点很明显,但是在数据管理上,我们需要明确数据的分布问题。

数据切片和实例的分布关系

在切片集群中,数据分布在不同的实例中。从redis3.0开始,Redis官方就能通过Redis cluster方法实现切片集群,它采用哈希槽来映射数据和实例。

我们在部署切片集群时,可通过clustre create命令来创建集群,Redis会平均将槽分布在各个实例上。我们也可通过cluster addslots命令手动分配哈希槽(在手动分配哈希槽时,需要把 16384 个槽都分配完,否则 Redis 集群无法正常工作)。 image.png

客户端是如何定位数据的

客户端和集群连接后,实例会将哈希槽的分配信息传到客户端。客户端收到哈希槽信息后,将信息缓存在本地,当客户端请求键值对时,首先会计算键值对所在的哈希槽,然后再将命令发送到哈希槽所在的实例上。

需要注意的是,实例和哈希槽的对应关系可能会变化的,主要有2种情况:

  • 实例在新增或者删除时,Redis需要重新分配哈希槽;
  • 为了负载均衡,Redis会在所有实例上rehash(哈希槽重新分配)。

在哈希槽变化过程中,客户端需要对数据操作时,如果实例上没有相应的哈希槽,就会给客户端返回MOVED命令结果,而结果中就有新实例的访问地址。 切片0.jpg

比如上图中的例子,如果切片2数据较多,客户端向实例2发送请求,但此时切片2有部分数据迁移到了实例3,还有部分未迁移。此时客户端会收到一条ASK报错信息。表示键值在实例3,但哈希槽正在迁移。之后客户端就可向实例3请求该数据。

Redis cluster的哈希槽分配原理

Redis cluster是通过哈希槽的方式将键值对分配到各个实例上,这个过程会对键值对的key做CRC计算,然后再和哈希槽做映射。

这样做的好处在于:

  1. key的数量不好预估,直接记录key对应的映射关系,映射表会很大,这样一来就会占用很大的内存空间;
  2. 当集群扩容、缩容、负载均衡时,节点间会进行数据迁移动作,如果修改每个key的映射关系,维护成本会很高。
  3. 当集群在扩容、缩容、数据均衡时,节点之间的操作如数据迁移,都以哈希槽为基本单位进行操作,简化了节点扩容、缩容的难度,便于集群的维护和管理。

小结

redis切片集群的方式,以横向扩展的方式对Redis进行扩容。我们需要了解数据分布的映射原理,以便更好的管理数据。