面试官:Redis如何实现高可扩展?如何实现分布式锁?回答上来让你过关

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

Redis Cluster如何分片?

Redis集群通过分片的方式来保存数据库中的键值对。集群的整个数据库被分为16384个槽,数据库中的每个键都属于这16384个槽的其中一个,集群中的每个节点可以负责0~16384个槽。

当数据库中的16384个槽都有节点在处理时,集群处于上线状态;如果有任何一个槽没有节点处理时,集群处于下线状态。

槽指派命令

通过向节点发送cluster addslots命令可以将一个或多个槽指派给该节点。

如何维护槽信息?

每个节点的clusterNode结构slots属性和numslot属性记录节点负责的槽信息。

clusterNode.slots是一个二进制数组,长度为16384/8=2048字节,共包含16384个二进制位。Redis对clusterNode.slots数组中的16384个二进制位进行编号,根据索引i上的二进制位值来判断节点负责哪些槽(二进制位值=1,表示节点负责处理槽i)。 clusterNode.numslot记录该节点负责的槽数量。

节点之间如何共享槽指派信息?

集群中的每个节点都知道16384个槽都分别被指派给了集群中的哪些节点。

每个节点会将自己的clusterNode.slots数组发送给集群中的其他节点,告知其他节点自己负责处理哪些槽。收到槽指派信息的节点会在自己的clusterState.nodes字典中查找该节点对应的clusterNode结构,并对该clusterNode.slots数组进行更新。

但是只是将槽指派信息保存在每个节点的clusterNode.slots数组中,想要知道某个槽是否被指派或者指派给了那个节点,都需要遍历clusterState.nodes字典中的所有clusterNode.nodes数组,时间复杂度为O(n)。

所以每个节点clusterState结构会使用一个slots数组会记录集群中16384个槽的指派信息,每个数组项指向一个clusterNode结构,表示槽i由该节点负责。想要知道某个槽的指派信息时,只需要访问clusterState.slots[i]即可,时间复杂度为O(1)。

集群中执行命令的过程

客户端向节点发送命令,接收命令的节点会计算出命令要处理的key属于哪个槽,并检查这个槽是否由自己负责,如果这个槽不是由自己负责,则向客户端返回一个MOVED错误,指引客户端请求正确的节点,并再次发送命令。

1. 如何计算键属于哪个槽 计算key的哈希值,并将哈希值对16384个槽取模,即可得到key所在的槽位。

2. 如何判断槽是否由自己负责呢? 根据槽位检查自己的clusterState.slots[i]是否等于clusterState.myself,如果是,则表示该槽位由自己负责,如果不是,根据clusterState.slots[i]指向的clusterNode记录的节点IP地址和端口号指引客户端向处理该槽的节点发送命令请求。

3. MOVED错误 MOVED错误会向客户端返回正确负责该key的槽、负责处理该key的节点IP地址、端口号,客户端通过MOVED错误返回的IP地址、端口号连接点点并重新发送命令请求。

重新分片

Redis集群的重新分片操作可以将任意数量已经指派给某个节点的槽改为指派给另一个节点,并且移动相关槽位负责的键值对。

重新分片过程

重新分片操作由Redis集群管理软件redis-trib负责执行,redis-trib通过向源节点和目标节点发送命令来进行重新分片操作。

Redis 重新分片的单位是槽,一个槽一个槽进行迁移,当一个槽正在迁移时,这个槽就处于中间过渡状态。这个槽在原节点的状态为migrating,在目标节点的状态为importing,表示数据正在从源流向目标。

  1. redis-trib 首先会在源和目标节点设置好中间过渡状态;
  2. 然后一次性获取源节点槽位的所有key列表(keysinslot指令,可以部分获取),再挨个key进行迁移,每个key的迁移过程是以原节点作为目标节点的客户端: (1) 原节点对当前的key执行dump指令得到序列化内容; (2) 源节点向目标节点发送指令restore携带序列化的内容作为参数; (3) 目标节点进行反序列化将内容恢复到目标节点的内存中,然后返回源节点OK; (4) 原节点收到后再把当前节点的key删除;

(1) ~ (4) 执行期间主线程阻塞,如果key的内容过大会导致源节点和目标节点卡顿,影响集群稳定性,所以需要尽可能避免大key产生。

ASK错误

在进行重新分片期间,可能出现被迁移槽的一部分键值对在源节点,一部分键值对在目标节点。当客户端请求的键属于被迁移的槽时:

  1. 源节点在自己的数据库中查找指定的键,如果找到,则直接执行命令;
  2. 如果源节点中找不到指定的键,则说明该键不存在或已经被迁移到了目标节点,源节点将向客户端返回一个ASK错误(槽、节点IP地址、端口号);
  3. 客户端收到回复的ASK错误,将向返回的节点IP地址、端口号发送一个不带参数的asking命令(槽迁移没完成前,目标节点还不认为该节点由自己负责,会重定向回源节点,形成重定向循环,所以需要向目标节点发送一个acking指令,告知目标节点需要处理下一条指令);
  4. 客户端请求目标节点,并再次发送命令;

Codis

Codis是一个国内开源的代理中间件,当客户端向Codis发送命令时,Codis负责将命令转发到Redis服务器来执行,并将结果再返回给客户端。

Codis上挂接的所有Redis服务器构成一个集群,当集群空间不足时,可以通过动态增加Redis服务器来实现扩容需求。

Codis是无状态的,只是一个转发代理中间件,可以启动多个Codis实例供客户端使用,每个Codis节点都是对等的。

Codis如何分片?

Codis将默认划分1024个槽,每个key都属于这1024个槽的其中一个。当客户端发送命令时,首先计算key的哈希值,再将哈希值对1024取模,即可得到key对应的槽位。

Codis会在内存维护槽位和Redis实例的映射关系,每个槽位都会唯一映射到一个Redis实例。

槽位同步

Codis会使用一个分布式配置存储数据库专门用来持久化槽位关系,如ZooKeeper。

Codis将槽位关系存储在ZooKeeper,并且提供了一个DashbBoard来观察和修改槽位关系,当槽位发生变化时,CodisProxy会监听到变化并重新同步槽位关系。

扩容

Codis增加了slotsscan命令,可以遍历某个槽下所有的key。Codis通过slotsscan命令获取待迁移槽位的所有key,然后挨个迁移每个key到新的Redis节点。

但是Codis无法判断迁移中的key存在哪个实例。当Codis接收到正在迁移槽位中的key后,会立即强制对当前的单个key进行迁移,迁移完成后再将请求转发到新的Redis节点。

比较Redis Cluster和Codis

  1. 分布式事务:
  • Codis是代理中间件,所有的key都分散在不同的Redis实例中,无法实现分布式事务;
  • Redis Cluster支持分布式事务;
  1. 槽位划分:
  • Redis Cluster划分16384个槽位;
  • Codis默认划分1024个槽位;
  1. 槽位迁移:
  • Redis Cluster每个节点都保存槽位关系,通过发送消息来通知槽位变更;
  • Codis将槽位关系维护在ZooKeeper,当Codis监听到槽位变更则重新同步;
  1. 目标节点定位:
  • Codis需要经过Proxy来定位目标节点;

Spring全套教学资料

Spring是Java程序员的《葵花宝典》,其中提供的各种大招,能简化我们的开发,大大提升开发效率!目前99%的公司使用了Spring,大家可以去各大招聘网站看一下,Spring算是必备技能,所以一定要掌握。

目录:

部分内容:

Spring源码

  • 第一部分 Spring 概述
  • 第二部分 核心思想
  • 第三部分 手写实现 IoC 和 AOP(自定义Spring框架)
  • 第四部分 Spring IOC 高级应用
    基础特性
    高级特性
  • 第五部分 Spring IOC源码深度剖析
    设计优雅
    设计模式
    注意:原则、方法和技巧
  • 第六部分 Spring AOP 应用
    声明事务控制
  • 第七部分 Spring AOP源码深度剖析
    必要的笔记、必要的图、通俗易懂的语言化解知识难点

脚手框架:SpringBoot技术

它的目标是简化Spring应用和服务的创建、开发与部署,简化了配置文件,使用嵌入式web服务器,含有诸多开箱即用的微服务功能,可以和spring cloud联合部署。

Spring Boot的核心思想是约定大于配置,应用只需要很少的配置即可,简化了应用开发模式。

  • SpringBoot入门
  • 配置文件
  • 日志
  • Web开发
  • Docker
  • SpringBoot与数据访问
  • 启动配置原理
  • 自定义starter

微服务架构:Spring Cloud Alibaba

同 Spring Cloud 一样,Spring Cloud Alibaba 也是一套微服务解决方案,包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。

  • 微服务架构介绍
  • Spring Cloud Alibaba介绍
  • 微服务环境搭建
  • 服务治理
  • 服务容错
  • 服务网关
  • 链路追踪
  • ZipKin集成及数据持久化
  • 消息驱动
  • 短信服务
  • Nacos Confifig—服务配置
  • Seata—分布式事务
  • Dubbo—rpc通信

Spring MVC

目录:

部分内容:

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-ZTLfM3n2-1713559682385)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 26
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值