0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Redis教程:两种方法教你如何保存更多数据

如意 来源:码农架构微信公众号 作者:码农架构微信公众 2020-09-04 10:21 次阅读

我曾遇到过这么一个需求:要用 Redis 保存 5000 万个键值对,每个键值对大约是 512B,为了能快速部署并对外提供服务,我们采用云主机来运行 Redis 实例,那么,该如何选择云主机的内存容量呢?

我粗略地计算了一下,这些键值对所占的内存空间大约是 25GB(5000 万 *512B)。所以,当时,我想到的第一个方案就是:选择一台 32GB 内存的云主机来部署 Redis。因为 32GB 的内存能保存所有数据,而且还留有 7GB,可以保证系统的正常运行。同时,我还采用 RDB 对数据做持久化,以确保 Redis 实例故障后,还能从 RDB 恢复数据。

但是,在使用的过程中,我发现,Redis 的响应有时会非常慢。后来,我们使用 INFO 命令查看 Redis 的 latest_fork_usec 指标值(表示最近一次 fork 的耗时),结果显示这个指标值特别高,快到秒级别了。

这跟 Redis 的持久化机制有关系。在使用 RDB 进行持久化时,Redis 会 fork 子进程来完成,fork 操作的用时和 Redis 的数据量是正相关的,而 fork 在执行时会阻塞主线程。数据量越大,fork 操作造成的主线程阻塞的时间越长。所以,在使用 RDB 对 25GB 的数据进行持久化时,数据量较大,后台运行的子进程在 fork 创建时阻塞了主线程,于是就导致 Redis 响应变慢了。

看来,第一个方案显然是不可行的,我们必须要寻找其他的方案。这个时候,我们注意到了 Redis 的切片集群。虽然组建切片集群比较麻烦,但是它可以保存大量数据,而且对 Redis 主线程的阻塞影响较小。

切片集群,也叫分片集群,就是指启动多个 Redis 实例组成一个集群,然后按照一定的规则,把收到的数据划分成多份,每一份用一个实例来保存。回到我们刚刚的场景中,如果把 25GB 的数据平均分成 5 份(当然,也可以不做均分),使用 5 个实例来保存,每个实例只需要保存 5GB 数据。如下图所示:

Redis教程:两种发教你如何保存更多数据

那么,在切片集群中,实例在为 5GB 数据生成 RDB 时,数据量就小了很多,fork 子进程一般不会给主线程带来较长时间的阻塞。采用多个实例保存数据切片后,我们既能保存 25GB 数据,又避免了 fork 子进程阻塞主线程而导致的响应突然变慢。

在实际应用 Redis 时,随着用户或业务规模的扩展,保存大量数据的情况通常是无法避免的。而切片集群,就是一个非常好的解决方案。这节课,我们就来学习一下。

如何保存更多数据?

在刚刚的案例里,为了保存大量数据,我们使用了大内存云主机和切片集群两种方法。实际上,这两种方法分别对应着 Redis 应对数据量增多的两种方案:纵向扩展(scale up)和横向扩展(scale out)。

纵向扩展:升级单个 Redis 实例的资源配置,包括增加内存容量、增加磁盘容量、使用更高配置的 CPU。就像下图中,原来的实例内存是 8GB,硬盘是 50GB,纵向扩展后,内存增加到 24GB,磁盘增加到 150GB。

横向扩展:横向增加当前 Redis 实例的个数,就像下图中,原来使用 1 个 8GB 内存、50GB 磁盘的实例,现在使用三个相同配置的实例。

Redis教程:两种发教你如何保存更多数据

那么,这两种方式的优缺点分别是什么呢?

首先,纵向扩展的好处是,实施起来简单、直接。不过,这个方案也面临两个潜在的问题。

第一个问题是,当使用 RDB 对数据进行持久化时,如果数据量增加,需要的内存也会增加,主线程 fork 子进程时就可能会阻塞(比如刚刚的例子中的情况)。不过,如果你不要求持久化保存 Redis 数据,那么,纵向扩展会是一个不错的选择。

不过,这时,你还要面对第二个问题:纵向扩展会受到硬件和成本的限制。这很容易理解,毕竟,把内存从 32GB 扩展到 64GB 还算容易,但是,要想扩充到 1TB,就会面临硬件容量和成本上的限制了。

与纵向扩展相比,横向扩展是一个扩展性更好的方案。这是因为,要想保存更多的数据,采用这种方案的话,只用增加 Redis 的实例个数就行了,不用担心单个实例的硬件和成本限制。在面向百万、千万级别的用户规模时,横向扩展的 Redis 切片集群会是一个非常好的选择。

不过,在只使用单个实例的时候,数据存在哪儿,客户端访问哪儿,都是非常明确的,但是,切片集群不可避免地涉及到多个实例的分布式管理问题。要想把切片集群用起来,我们就需要解决两大问题:

数据切片后,在多个实例之间如何分布?

客户端怎么确定想要访问的数据在哪个实例上?

接下来,我们就一个个地解决。

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

在切片集群中,数据需要分布在不同实例上,那么,数据和实例之间如何对应呢?这就和接下来我要讲的 Redis Cluster 方案有关了。不过,我们要先弄明白切片集群和 Redis Cluster 的联系与区别。

实际上,切片集群是一种保存大量数据的通用机制,这个机制可以有不同的实现方案。在 Redis 3.0 之前,官方并没有针对切片集群提供具体的方案。从 3.0 开始,官方提供了一个名为 Redis Cluster 的方案,用于实现切片集群。Redis Cluster 方案中就规定了数据和实例的对应规则。

具体来说,Redis Cluster 方案采用哈希槽(Hash Slot,接下来我会直接称之为 Slot),来处理数据和实例之间的映射关系。在 Redis Cluster 方案中,一个切片集群共有 16384 个哈希槽,这些哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中。

具体的映射过程分为两大步:

首先根据键值对的 key,按照CRC16 算法计算一个 16 bit 的值;

然后,再用这个 16bit 值对 16384 取模,得到 0~16383 范围内的模数,每个模数代表一个相应编号的哈希槽。

关于CRC16 算法,如果感兴趣!可以自行Googel查询

那么,这些哈希槽又是如何被映射到具体的 Redis 实例上的呢?

我们在部署 Redis Cluster 方案时,可以使用 cluster create 命令创建集群,此时,Redis 会自动把这些槽平均分布在集群实例上。例如,如果集群中有 N 个实例,那么,每个实例上的槽个数为 16384/N 个。

当然, 我们也可以使用 cluster meet 命令手动建立实例间的连接,形成集群,再使用 cluster addslots 命令,指定每个实例上的哈希槽个数。

客户端如何定位数据?

在定位键值对数据时,它所处的哈希槽是可以通过计算得到的,这个计算可以在客户端发送请求时来执行。但是,要进一步定位到实例,还需要知道哈希槽分布在哪个实例上。

一般来说,客户端和集群实例建立连接后,实例就会把哈希槽的分配信息发给客户端。但是,在集群刚刚创建的时候,每个实例只知道自己被分配了哪些哈希槽,是不知道其他实例拥有的哈希槽信息的。

那么,客户端为什么可以在访问任何一个实例时,都能获得所有的哈希槽信息呢?这是因为,Redis 实例会把自己的哈希槽信息发给和它相连接的其它实例,来完成哈希槽分配信息的扩散。当实例之间相互连接后,每个实例就有所有哈希槽的映射关系了。

客户端收到哈希槽信息后,会把哈希槽信息缓存在本地。当客户端请求键值对时,会先计算键所对应的哈希槽,然后就可以给相应的实例发送请求了。

总结

上述讲述切片集群在保存大量数据方面的优势,以及基于哈希槽的数据分布机制和客户端定位键值对的方法

在应对数据量扩容时,虽然增加内存这种纵向扩展的方法简单直接,但是会造成数据库的内存过大,导致性能变慢。Redis 切片集群提供了横向扩展的模式,也就是使用多个实例,并给每个实例配置一定数量的哈希槽,数据可以通过键的哈希值映射到哈希槽,再通过哈希槽分散保存到不同的实例上。这样做的好处是扩展性好,不管有多少数据,切片集群都能应对。
责编AJX

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    6986

    浏览量

    88931
  • 磁盘
    +关注

    关注

    1

    文章

    372

    浏览量

    25200
  • Redis
    +关注

    关注

    0

    文章

    374

    浏览量

    10870
收藏 人收藏

    评论

    相关推荐

    Linux端口的开启的两种方法需要掌握

    Linux端口的开启的两种方法需要掌握
    发表于 11-28 10:05 1234次阅读

    启动Redis的三种方法

    Redis笔记(1)——安装、卸载、三种方法启动RedisRedis命令使用(干货十足),Redis
    发表于 06-08 16:09

    STM32操作矩阵键盘的两种方法

    目录STM32操作矩阵键盘的两种方法——扫描和中断一、矩阵键盘的结构和原理二、扫描式矩阵键盘的原理和实现三、中断式矩阵键盘的原理和实现四、两种方案优劣STM32操作矩阵键盘的两种方法——扫描和中断
    发表于 08-12 06:33

    关断检流放大器的两种方法

    摘要:本应用笔记介绍了两种关断高边电流检测器的方法两种方法都可以在下一代便携式多媒体设备中用于电源管理。从而使系统在保证用户功能需求的前提下有效延长电池的使
    发表于 05-06 11:04 13次下载

    关断检流放大器的两种方法

    摘要:本应用笔记介绍了两种关断高边电流检测器的方法两种方法都可以在下一代便携式多媒体设备中用于电源管理。从而使系统在保证用户功能需求的前提下有效延长电池的使
    发表于 05-07 08:48 23次下载

    AODV协议中解决断链问题的两种方法

    AODV协议中解决断链问题的两种方法 2.1 备用路由方法由于常规路由协议维护完整的路由表,能得知网络中的拓扑情况,很容易
    发表于 03-01 17:31 1124次阅读
    AODV协议中解决断链问题的<b class='flag-5'>两种方法</b>

    使用jdbc连接上oracle的两种方法

    本文主要介绍了使用jdbc连接上oracle的两种方法:1、 使用thin连接,2、 使用oci连接(Oracle Call Interface)
    发表于 02-06 10:43 1711次阅读

    提升家里网速的两种方法

    总是嫌家里的网速慢,看视频“转圈圈”,玩游戏“时延高”,如何提升家里的网速呢?这里介绍两种方法
    的头像 发表于 02-19 21:10 1.4w次阅读
    提升家里网速的<b class='flag-5'>两种方法</b>

    STM32操作矩阵键盘的两种方法——扫描和中断

    目录STM32操作矩阵键盘的两种方法——扫描和中断一、矩阵键盘的结构和原理二、扫描式矩阵键盘的原理和实现三、中断式矩阵键盘的原理和实现四、两种方案优劣STM32操作矩阵键盘的两种方法——扫描和中断
    发表于 11-26 13:36 36次下载
    STM32操作矩阵键盘的<b class='flag-5'>两种方法</b>——扫描和中断

    LDO在IoT中省电的两种方法

    LDO在IoT中省电的两种方法
    发表于 11-04 09:50 0次下载
    LDO在IoT中省电的<b class='flag-5'>两种方法</b>

    关断检流放大器的两种方法

    本应用笔记介绍了两种关断高边电流检测器的方法两种方法都可以在下一代便携式多媒体设备中用于电源管理。从而使系统在保证用户功能需求的前提下有效延长电池的使用寿命。
    的头像 发表于 02-10 15:21 739次阅读
    关断检流放大器的<b class='flag-5'>两种方法</b>

    简述安装打印机驱动的两种方法

    安装打印机驱动通常有两种方法,一种是直接使用驱动文件自带的安装程序自动安装,而另一种方法就是我们自己手动进行安装。两种方法各有利弊,日常工作中可以根据实际情况来选择使用哪种方法进行安装
    的头像 发表于 04-04 09:46 4747次阅读
    简述安装打印机驱动的<b class='flag-5'>两种方法</b>

    图腾柱TCM之相变频错相的两种方法

    目前而言,TCM的错相方法两种:开环180deg固定错相,以及闭环实时调节错相;在我们的代码中,我们同时采用了这两种方法
    的头像 发表于 08-20 10:03 1093次阅读
    图腾柱TCM之<b class='flag-5'>两</b>相变频错相的<b class='flag-5'>两种方法</b>

    PoE以太网供电的两种方法

    电力,简化了设备的安装和布线。在本文中,我们将详细介绍PoE以太网供电的两种方法。 第一种方法是标准PoE供电(IEEE 802.3af)。这种方法需要一个双绞线以太网电缆来传输电力和数据
    的头像 发表于 11-28 15:51 904次阅读

    redis两种持久化方式的区别

    的完整性和一致性。 Redis提供了两种持久化方式:RDB(Redis Database)和AOF(Append Only File)。这两种方式各有优劣,下面我们将详细介绍它们的区别
    的头像 发表于 12-04 11:12 514次阅读