Java-中间件-3

1.19 请介绍Redis集群的实现方案

参考答案

Redis集群的分区方案:

Redis集群采用虚拟槽分区来实现数据分片,它把所有的键根据哈希函数映射到0-16383整数槽内,计算公式为slot=CRC16(key)&16383,每一个节点负责维护一部分槽以及槽所映射的键值数据。虚拟槽分区具有如下特点:

  1. 解耦数据和节点之间的关系,简化了节点扩容和收缩的难度;

  2. 节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据;

  3. 支持节点、槽、键之间的映射查询,用于数据路由,在线伸缩等场景。

Redis集群中数据的分片逻辑如下图:

Redis集群的功能限制:

Redis集群方案在扩展了Redis处理能力的同时,也带来了一些使用上的限制:

  1. key批量操作支持有限。如mset、mget,目前只支持具有相同slot值的key执行批量操作。对于映射为不同slot值的key由于执行mset、mget等操作可能存在于多个节点上所以不被支持。

  2. key事务操作支持有限。同理只支持多key在同一节点上的事务操作,当多个key分布在不同的节点上时无法使用事务功能。

  3. key作为数据分区的最小粒度,因此不能将一个大的键值对象(如hash、list等)映射到不同的节点。

  4. 不支持多数据库空间。单机下的Redis可以支持16个数据库,集群模式下只能使用一个数据库空间,即DB0。

  5. 复制结构只支持一层,从节点只能复制主节点,不支持嵌套树状复制结构。

Redis集群的通信方案:

在分布式存储中需要提供维护节点元数据信息的机制,所谓元数据是指:节点负责哪些数据,是否出现故障等状态信息。常见的元数据维护方式分为:集中式和P2P方式。

Redis集群采用P2P的Gossip(流言)协议,Gossip协议的工作原理就是节点彼此不断通信交换信息,一段时间后所有的节点都会知道集群完整的信息,这种方式类似流言传播。通信的大致过程如下:

  1. 集群中每个节点都会单独开辟一个TCP通道,用于节点之间彼此通信,通信端口号在基础端口号上加10000;

  2. 每个节点再固定周期内通过特定规则选择几个节点发送ping消息;

  3. 接收ping消息的节点用pong消息作为响应。

其中,Gossip协议的主要职责就是信息交换,而信息交换的载体就是节点彼此发送的Gossip消息,Gossip消息分为:meet消息、ping消息、pong消息、fail消息等。

  • meet消息:用于通知新节点加入,消息发送者通知接受者加入到当前集群。meet消息通信正常完成后,接收节点会加入到集群中并进行周期性的ping、pong消息交换。

  • ping消息:集群内交换最频繁的消息,集群内每个节点每秒向多个其他节点发送ping消息,用于检测节点是否在线和交换彼此状态信息。ping消息封装了自身节点和一部分其他节点的状态数据。

  • pong消息:当接收到meet、ping消息时,作为响应消息回复给发送方确认消息正常通信。pong消息内封装了自身状态数据,节点也可以向集群内广播自身的pong消息来通知整个集群对自身状态进行更新。

  • fail消息:当节点判定集群内另一个节点下线时,会向集群内广播一个fail消息,其他节点接收到fail消息之后把对应节点更新为下线状态。

虽然Gossip协议的信息交换机制具有天然的分布式特性,但它是有成本的。因为Redis集群内部需要频繁地进行节点信息交换,而ping/pong消息会携带当前节点和部分其他节点的状态数据,势必会加重带宽和计算的负担。所以,Redis集群的Gossip协议需要兼顾信息交换的实时性和成本的开销。

  • 集群里的每个节点默认每隔一秒钟就会从已知节点列表中随机选出五个节点,然后对这五个节点中最长时间没有发送过PING消息的节点发送PING消息,以此来检测被选中的节点是否在线。

  • 如果节点A最后一次收到节点B发送的PONG消息的时间,距离当前时间已经超过了节点A的超时选项设置时长的一半(cluster-node-timeout/2),那么节点A也会向节点B发送PING消息,这可以防止节点A因为长时间没有随机选中节点B作为PING消息的发送对象而导致对节点B的信息更新滞后。

  • 每个消息主要的数据占用:slots槽数组(2KB)和整个集群1/10的状态数据(10个节点状态数据约1KB)。

1.20 说一说Redis集群的分片机制

参考答案

Redis集群采用虚拟槽分区来实现数据分片,它把所有的键根据哈希函数映射到0-16383整数槽内,计算公式为slot=CRC16(key)&16383,每一个节点负责维护一部分槽以及槽所映射的键值数据。虚拟槽分区具有如下特点:

  1. 解耦数据和节点之间的关系,简化了节点扩容和收缩的难度;

  2. 节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据;

  3. 支持节点、槽、键

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java岗位面试真题宝典 文章被收录于专栏

本面试宝典均来自校招面试题目大数据进行的整理

全部评论
笔记: redis的Hash数据结构结构:底层数据结构为字典(dict),每个dict记录一下数据的必要信息外,包含2个字典哈希表(dict hash table),一个默认存放数据,一个用于扩容时的中间表(类似于 GC中标记-复制法中的空闲内存作用),dictht中保存了数据的必要信息+dictEntry数组,这里的dictEntry数组个人认为近似于java中的hashmap结构,以数组+链表的形式存储了k-v对; 渐进式扩容:数据默认存放在ht[0]中,一旦触发了扩容或收缩,则将dictht[1]作为操作的中间表,具体如下: 1、为ht[1]分配空间,扩容时,大小为第一个>=(h[0]中被使用空间大小x的2倍)的偶数值(难道2x本身不就是最接近的嘛...在线疑惑)。收缩时,大小为第一个>=(h[0]中被使用空间大小x)的偶数值; 2、对ht[0]中每个kv对重新rehashcode并迁移到ht[1](渐进式rehash模式下,并不是一次性完成,而是将每个kv对的转移捆绑到客户端的增删改查指令中); 3、迁移完成,清空ht[0],设置ht[1]为默认数据存储表; 4、上述渐进式rehash过程中,如果有新插入的数据,则统一进入ht[1](即提前将ht[1]设置为默认数据存储表),增删改差等操作会在两个表上进行,先查旧表(0)再查新表(1)
点赞 回复 分享
发布于 2021-09-09 16:52

相关推荐

昨天 22:49
门头沟学院 Java
点赞 评论 收藏
分享
11-23 15:33
已编辑
门头沟学院 Java
CUTMR:换账号试试重启推荐算法,我换账号之后回复率还不错,约莫有个20%左右的消息回复率,前几页、主动招呼的HR也开始符合我期望薪资,此前的大号从招呼、回复、前几页的岗位薪资在涨幅30%+以上 用着用着聊着聊着就变成-20%,而且我开通会员之后直接0面试
点赞 评论 收藏
分享
不知道怎么取名字_:玩游戏都写到简历上了啊
投递BOSS直聘等公司6个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务