美文网首页redis
redis(六:分片)

redis(六:分片)

作者: supremecsp | 来源:发表于2022-11-23 18:01 被阅读0次

redis无法像mysql、mongodb那样基于同步的点位在主库发生变化后从新的主库继续同步数据。 在redis集群中一旦从库换主,redis的做法是将更换主库的从库清空然后从新主库完整同步一份数据再进行续传。
整个从库重做流程是这样的:
1,主库bgsave自身数据到磁盘
2,主库发送rdb文件到从库
3,从库开始加载
4,加载完毕开始续传,同时开始提供服务
在这个过程中redis的内存体积越大以上每一个步骤的时间都会被拉长。为什么Redis内存不宜过大

所以当redis实例过大时,我们可以尝试采取分片集群,就是指启动多个 Redis 实例组成一个集群,然后按照一定的规则,把收到的数据划分成多份,每一份用一个实例来保存。

Redis 应对数据量增多的两种方案:纵向扩展和横向扩展。
纵向扩展:升级单个 Redis 实例的资源配置,包括增加内存容量、增加磁盘容量、使用更高配置的 CPU。就像下图中,原来的实例内存是 8GB,硬盘是 50GB,纵向扩展后,内存增加到 24GB,磁盘增加到 150GB。(不要求持久化保存 Redis 数据,是个不错的选择,不持久化的话,对于宕机后数据穿透服务器的压力需重点关注下)
横向扩展:横向增加当前 Redis 实例的个数 (切片)

Redis Cluster
在切片集群中,数据需要分布在不同实例上,这个数据和实例的对应关系,官方采用Redis Cluster解决;
在 Redis Cluster 方案中,一个切片集群共有 16384 个哈希槽,这些哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中。
Redis 会自动把这些槽平均分布在集群实例上。例如,如果集群中有 N 个实例,那么,每个实例上的槽个数为 16384/N 个。
hash槽可自动分配,也可以根据实例的配置手动分配,配置较高的实例可分配更多的槽位以抵抗较大的读写压力。
redis的16个数据库数量是默认的,1个数据库的地位相当于mysql的一个表,可以理解为一个命名空间。当集群模式时,只有一个db0的概念,数据按照slot放置。
redis集群整体不可以支持事务,每个节点可以。

客户端如何定位数据?
在定位键值对数据时,它所处的哈希槽是可以通过计算得到的,这个计算可以在客户端发送请求时来执行。但是,要进一步定位到实例,还需要知道哈希槽分布在哪个实例上(即为查找的时候如果数据不在当前节点下,会先给予数据所在的实例地址)。

实例如果知道数据分布在哪个实例地址
Redis 实例会把自己的哈希槽信息发给和它相连接的其它实例,来完成哈希槽分配信息的扩散。当实例之间相互连接后,每个实例就有所有哈希槽的映射关系了。
客户端收到哈希槽信息后,会把哈希槽信息缓存在本地。当客户端请求键值对时,会先计算键所对应的哈希槽,然后就可以给相应的实例发送请求了。

但是,在集群中,实例和哈希槽的对应关系并不是一成不变的,最常见的变化有两个:
在集群中,实例有新增或删除,Redis 需要重新分配哈希槽;
为了负载均衡,Redis 需要把哈希槽在所有实例上重新分布一遍。

实例之间还可以通过相互传递消息,获得最新的哈希槽分配信息,但是,客户端是无法主动感知这些变化的怎么办?
Redis Cluster 方案提供了一种重定向机制,所谓的“重定向”,就是指,客户端给一个实例发送数据读写操作时,这个实例上并没有相应的数据,客户端要再给一个新实例发送操作命令。

GET hello:key
(error) MOVED 13320 172.16.19.5:6379

就是如果在客户端此时请求哈希槽2的数据,此时会到实例2,发现数据不在该实例下,会让你重定向实例3,并更新客户端缓存。

哈希槽数据存在两个实例怎么办?
如果 Slot 2 中的数据比较多,就可能会出现一种情况:客户端向实例 2 发送请求,但此时,Slot 2 中的数据只有一部分迁移到了实例 3,还有部分数据没有迁移。在这种迁移部分完成的情况下,客户端就会收到一条 ASK 报错信息。

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

此时,客户端需要先给 172.16.19.5 这个实例发送一个 ASKING 命令。这个命令的意思是,让这个实例允许执行客户端接下来发送的命令。然后,客户端再向这个实例发送 GET 命令,以读取数据。

和 MOVED 命令不同,ASK 命令并不会更新客户端缓存的哈希槽分配信息。所以,在上图中,如果客户端再次请求 Slot 2 中的数据,它还是会给实例 2 发送请求。这也就是说,ASK 命令的作用只是让客户端能给新实例发送一次请求,而不像 MOVED 命令那样,会更改本地缓存,让后续所有命令都发往新实例。

Redis Cluster不采用把key直接映射到实例的方式,而采用哈希槽的方式原因:
1、整个集群存储key的数量是无法预估的,key的数量非常多时,直接记录每个key对应的实例映射关系,这个映射表会非常庞大,这个映射表无论是存储在服务端还是客户端都占用了非常大的内存空间。
2、Redis Cluster采用无中心化的模式(无proxy,客户端与服务端直连),客户端在某个节点访问一个key,如果这个key不在这个节点上,这个节点需要有纠正客户端路由到正确节点的能力(MOVED响应),这就需要节点之间互相交换路由表,每个节点拥有整个集群完整的路由关系。如果存储的都是key与实例的对应关系,节点之间交换信息也会变得非常庞大,消耗过多的网络资源,而且就算交换完成,相当于每个节点都需要额外存储其他节点的路由表,内存占用过大造成资源浪费。
3、当集群在扩容、缩容、数据均衡时,节点之间会发生数据迁移,迁移时需要修改每个key的映射关系,维护成本高。
4、而在中间增加一层哈希槽,可以把数据和节点解耦,key通过Hash计算,只需要关心映射到了哪个哈希槽,然后再通过哈希槽和节点的映射表找到节点,相当于消耗了很少的CPU资源,不但让数据分布更均匀,还可以让这个映射表变得很小,利于客户端和服务端保存,节点之间交换信息时也变得轻量。
5、当集群在扩容、缩容、数据均衡时,节点之间的操作例如数据迁移,都以哈希槽为基本单位进行操作,简化了节点扩容、缩容的难度,便于集群的维护和管理。

Redis Cluster不采用一致性哈希算法的原因
一致性哈希算法:多增加一层虚拟映射层,数据与虚拟节点映射、虚拟节点与真实节点再映射。听起来和哈希槽很像。
但一致性哈希的ketama算法实现在扩容或down的情况下,需要重新计算节点,这对之前的分配可能会有一些影响。所以可以引入hash slot的方式,即某些hash slot区间对应一台机器,对于扩容或down机情况下,就改变某个hash slot区间就可以了,改动比较小,对之前分配的影响也较小。
虚拟桶是取模和一致性哈希二者的折中办法。
采用固定节点数量,来避免取模的不灵活性。
采用可配置映射节点,来避免一致性哈希的部分影响。
一致性哈希算法原理详解

摘抄:《Redis 核心技术与实战》-第9节

相关文章

  • redis(六:分片)

    redis无法像mysql、mongodb那样基于同步的点位在主库发生变化后从新的主库继续同步数据。 在redis...

  • 动手实践Redis主从复制、Sentinel主从切换、Clust

    背景简介 Redis 提供的如下技术「Redis Sentinel『主从切换』、Redis Cluster『分片』...

  • k3s operator 方式 安装 redis 无中心集群

    redis有单机,复制,分片这几种方式 复制就是把一个redis的数据,复制到另外一个redis, 分片就是把ke...

  • Jedis路由key的算法剥离

    在Redis集群中,会有很多个分片,如果此时利用Jedis来操作此Redis集群,那么他会把数据路由到不到的分片上...

  • 优酷土豆的Redis服务平台化之路

    优酷土豆的Redis服务平台化之路 1 Redis架构的方案经历阶段 1.1.客户端分片 客户端分片: 优点 不依...

  • Redis分片

    分片(partitioning)就是将你的数据拆分到多个 Redis 实例的过程,这样每个实例将只包含所有键的子集...

  • redis 分片

    为什么要分片 问题:公司用户量3千万,用户基本信息缓存到redis中,需要内存10G,如何设计Redis的缓存架构...

  • redis 集群搭建

    Redis集群 使用redis做缓存工具 实现系统高可用,redis需要做主备。使用redis做分片集群。 向业务...

  • Redis集群实现方案

    http://redis.io/topics/partitioning 分片 我经历的项目中把redis仅仅当做内...

  • jedis分片原理剖析

    Redis2.0+版本不支持服务器分片,只能通过jedis分片,3.0+以上支持hash槽的服务端分片。jedis...

网友评论

    本文标题:redis(六:分片)

    本文链接:https://www.haomeiwen.com/subject/zgrdxdtx.html