Redis核心技术-高可靠-集群(cluster)

前言

  如果我们的业务需要32GRedis实例,我们创建一个32GRedis实例还是有其他的解决方案呢?

  Redis Cluster 从Redis 3.0开始支持使用,用于实现切片集群
  Redis Cluster 保证CAP中的可用性和一致性。

切片集群

  为了支持大容量Redis提出的方案,多个Redis实例存储不同的key和value。Redis 官方提供的解决方案是Redis Cluster,哈希槽便是用来处理数据和实例之间的关系。

  为什么不使用更大的内存的Redis?
  内存更大,持久化和恢复时间越长;需要更大内存和更强CPU支持。

Redis Cluster

哈希槽

  Redis Cluster 不使用一致性散列,而是一种不同形式的分片,其中每个key在概念上都是我们所谓的散列槽的一部分。

  Redis 集群中有 16384 个哈希槽(2的14次方),要计算key的哈希槽是多少,我们只需计算CRC16(key) % 16384

Redis实例和哈希槽关联

  分配方式:
1.cluster create命令创建集群时,Redis把哈希槽平均分配给Redis实例,每个Redis实例分配哈希槽数量=16384/N(N为Redis实例数量);

2.cluster meet命令手动建立Redis实例间的连接,形成集群,再通过cluster addslots命令指定每个Redis实例哈希槽个数(如果Redis实例内存、硬件配置不同比较适用);

Client和cluster交互

client如何指定key对应那个Redis实例?

  client与cluster连接后,Redis实例会把哈希槽信息发送给client。

  cluster建立后Redis实例间相互连接,可以指定彼此分配到的哈希槽信息,所有client与一个Redis实例连接时可以知道所有Redis实例的哈希槽信息。

cluster重新分配哈希槽后,client如何更新Redis实例和哈希槽的映射关系呢?

  client请求key时,先在本地计算key对应的哈希槽,再给对应的Redis实例发送key请求。

  添加Redis实例、移除Redis实例、手动修改Redis实例与哈希槽的映射都会重新分配哈希槽,Redis实例可以相互连接通信指定彼此的哈希槽信息,但是client不知道Redis与哈希槽信息发送变更。

  cluster 提供重定向机制,client发送key操作到Redis实例,并且key对应的哈希槽不属于当前Redis实例,那么便会返回MOVED命令响应client。

GET testKey1
(error) MOVED 13320 172.16.19.5:6379

  client 重新向172.16.19.5:6379 发送key操作,并且重新更新Redis实例与哈希槽映射关系。

cluster添加Redis实例情况

  cluster添加新Redis实例时,cluster重新分配哈希槽、属于新Redis实例的key从原来的Redis实例迁移过去。

  迁移过程中,client需要操作key,会出现什么情况呢?

GET testKey1
(error) ASK 13320 172.16.19.5:6379

  ASK命令表示key对应的哈希槽为13320,172.16.19.5:6379 Redis实例上,但是当前正在迁移。

  client需要向172.16.19.5:6379实例发送ASKING命令,让实例允许client接下来的key操作,client再向172.16.19.5:6379实例发送GET testKey1 操作。

  ASK命令和MOVED命令不同,ASK命令client不会更新本地Redis实例与哈希槽的映射缓存,ASK命令让client把key操作重新请求一次返回去的Redis实例。

Redis cluster多key操作支持

  MULTI/EXEC事务命令、mget、mset等多key操作时,Redis是否支持?如支持同一个Redis节点处理还是离散到其他Redis节点处理?

  Redis Cluster 支持多key操作,只要涉及到单个命令执行(或整个事务,或 Lua 脚本执行)的所有key都属于同一个哈希槽。用户可以使用称为散列标签的概念强制多个key成为同一个散列槽的一部分。

Redis cluster配置

添加节点
删除节点

Redis cluster问题

数据倾斜

  如果发生了数据倾斜,那么保存了大量数据,或者是保存了热点数据的Redis实例的处理压力就会增大,速度变慢,甚至还可能会引起这个实例的内存资源耗尽,从而崩溃。在应用切片集群时要避免的。

数据量倾斜

  Redis实例上的数据分布不均衡,某个实例上的数据特别多。

  数据量倾斜是怎么产生的呢?

  主要有三个原因:
1.分别是某个Redis实例上保存了 bigkey;

  解决方案:生成缓存数据时,要尽量避免把过多的数据保存在同一个键值对中。例如一个对象,可以拆分为对个key保存,后者使用hash保存,每次取需要的属性;如果bigKey为hash,可以拆分成多个hash key。

2.集群Slot 分配不均衡;

  如果管理员没有均衡地分配集群的Slot,可能出现大量的数据被分配到同一个 Slot 中,而同一个 Slot 只会在一个Redis实例上分布,这就会导致,大量数据被集中到一个实例上,造成数据倾斜。

  执行CLUSTER SLOTS 命令查看 Slot 分配情况。

  解决方案:管理员使用内存大小一致的Redis实例,slot平均发布。

  1. Hash Tag。

  Hash Tag 是指加在key-value对 key 中的一对花括号{}。这对括号会把 key 的一部分括起来,client在计算 key 的 CRC16 值时,只对 Hash Tag 花括号中的 key 内容进行计算。如果没用 Hash Tag 的话,client计算整个 key 的 CRC16 的值。

  假如key为:user:info:{713},713就是Hash Tag,client取713计算CRC16值。

数据访问倾斜

  集群中的Redis实例上的数据量相差不大,但是某个实例上的数据是热点数据,被访问得非常频繁。例如app首页配置、秒杀商品信息、公共配置。

  解决方案1:缓存数据多副本,缓存key增加后缀(1-3数字),访问时,随机生成1-3拼接在key上。
  弊端是多副本,需要额外保证多副本数据一致。适用于固定配置、热点新闻等。

  解决方案2:JVM本地短时间缓存,例如缓存1-30秒。

Redis实例上限

  Redis 官方给出了 Redis Cluster 的规模上限,就是一个集群运行 1000 个实例。

  前面说的集群中Redis实例相互通信,Redis实例间的通信开销会随着Redis实例规模增加而增大。在集群超过一定规模时(比如 800 节点),集群吞吐量反而会下降。所以,集群的实际规模会受到限制。

   Gossip 协议是Redis实例间通信规则。

   Gossip 协议的工作原理可以概括成两点:

   1.每个Redis实例之间会按照一定的频率,从集群中随机挑选一些实例,把 PING 消息发送给挑选出来的实例,用来检测这些实例是否在线,并交换彼此的状态信息。PING 消息中封装了发送消息的实例自身的状态信息、部分其它实例的状态信息,以及 Slot 映射表。

   2.一个Redis实例在接收到 PING 消息后,会给发送 PING 消息的实例,发送一个 PONG 消息。PONG 消息包含的内容和 PING 消息一样。

  Gossip 消息大小
  Redis 实例发送的 PING 消息的消息体是由 clusterMsgDataGossip 结构体组成的,这个结构体的定义如下所示:

typedef struct {
    //节点的名字
    char nodename[REDIS_CLUSTER_NAMELEN];
    //最后一次向该节点发送PING消息的时间戳
    uint32_t ping_sent;
    //最后一次从该 节点接收到PONG消息的时间戳
    uint32_t pong_received;
    //节点的IP地址
    char ip[16];
    //节点的端口号
    uint16_t port;
    //节点的标识值
    uint16_t flags;
} clusterMsgDataGossip;

参考:
https://redis.io/topics/cluster-tutorial

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冲上云霄的Jayden

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值