2024,Java最全的分布式面试题合集附答案,共2w字,渣本毕业两年经验

定时删除,就是在设置 key 的过期时间的同时,创建一个定时器,让定时器在过期时间来临时,立即执行对 key 的删除操作。

定时删会占用 CPU ,影响服务器的响应时间和性能。

问:Redis 的内存回收机制都有哪些?

当前已用内存超过 maxmemory 限定时,会触发主动清理策略,也就是 Redis 的内存回收策略。

LRU 、TTL。

  • noeviction :默认策略,不会删除任何数据,拒绝所有写入操作并返回客户端错误信息,此时 Redis 只响应读操作。

  • volatitle - lru :根据 LRU 算法删除设置了超时属性的键,知道腾出足够空间为止。如果没有可删除的键对象,回退到 noeviction 策略。

  • allkeys - lru :根据 LRU 算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止。

  • allkeys - random :随机删除所有键,知道腾出足够空间为止。

  • volatitle - random :随机删除过期键,知道腾出足够空间为止。

  • volatitle - ttl :根据键值对象的 ttl 属性,删除最近将要过期数据。如果没有,回退到 noeviction 策略。

问:手写一下 LRU 算法。

问:Redis 的搭建有哪些模式?

主从模式、哨兵模式、Cluster(集群)模式。最好是用集群模式。

问:你用过的 Redis 是多主多从的,还是一主多从的?集群用到了多少节点?用到了多少个哨兵?

集群模式。三主三从。

问:Redis 采用多主多从的集群模式,各个主节点的数据是否一致?

问:Redis 集群有哪些特性

master 和 slaver。主从复制。读写分离。哨兵模式。

问:Redis 是怎么进行水平扩容的?

问:Redis 集群数据分片的原理是什么?

  • Redis 数据分片原理是哈希槽(hash slot)。

  • Redis 集群有 16384 个哈希槽。每一个 Redis 集群中的节点都承担一个哈希槽的子集。

哈希槽让在集群中添加和移除节点非常容易。例如,如果我想添加一个新节点 D ,我需要从节点 A 、B、C 移动一些哈希槽到节点 D。同样地,如果我想从集群中移除节点 A ,我只需要移动 A 的哈希槽到 B 和 C。当节点 A 变成空的以后,我就可以从集群中彻底删除它。因为从一个节点向另一个节点移动哈希槽并不需要停止操作,所以添加和移除节点,或者改变节点持有的哈希槽百分比,都不需要任何停机时间(downtime)。

问:讲一下一致性 Hash 算法。

  • 一致性 Hash 算法将整个哈希值空间组织成一个虚拟的圆环, 我们对 key 进行哈希计算,使用哈希后的结果对 2 ^ 32 取模,hash 环上必定有一个点与这个整数对应。依此确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器。

  • 一致性 Hash 算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

比如,集群有四个节点 Node A 、B 、C 、D ,增加一台节点 Node X。Node X 的位置在 Node B 到 Node C 直接,那么受到影响的仅仅是 Node B 到 Node X 间的数据,它们要重新落到 Node X 上。

所以一致性哈希算法对于容错性和扩展性有非常好的支持。

问:为什么 Redis Cluster 分片不使用 Redis 一致性 Hash 算法?

一致性哈希算法也有一个严重的问题,就是数据倾斜。

如果在分片的集群中,节点太少,并且分布不均,一致性哈希算法就会出现部分节点数据太多,部分节点数据太少。也就是说无法控制节点存储数据的分配。

问:集群的拓扑结构有没有了解过?集群是怎么连接的?

无中心结构。Redis-Cluster 采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。

问:讲一下 Redis 主从复制的过程。

从机发送 SYNC(同步)命令,主机接收后会执行 BGSAVE(异步保存)命令备份数据。

主机备份后,就会向从机发送备份文件。主机之后还会发送缓冲区内的写命令给从机。

当缓冲区命令发送完成后,主机执行一条写命令,就会往从机发送同步写入命令。

问:讲一下 Redis 哨兵机制。

下面是 Redis 官方文档对于哨兵功能的描述:

  • 监控(Monitoring):哨兵会不断地检查主节点和从节点是否运作正常。

  • 自动故障转移(Automatic Failover):当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。

  • 配置提供者(Configuration Provider):客户端在初始化时,通过连接哨兵来获得当前 Redis 服务的主节点地址。

  • 通知(Notification):哨兵可以将故障转移的结果发送给客户端。

问:讲一下布隆过滤器。

布隆过滤器的主要是由一个很长的二进制向量和若干个(k 个)散列映射函数组成。因为每个元数据的存储信息值固定,而且总的二进制向量固定。所以在内存占用和查询时间上都远远超过一般的算法。当然存在一定的不准确率(可以控制)和不容易删除样本数据。

布隆过滤器的优点:大批量数据去重,特别的占用内存。但是用布隆过滤器(Bloom Filter)会非常的省内存。

布隆过滤器的特点:当布隆过滤器说某个值存在时,那可能就不存在,如果说某个值不存在时,那肯定就是不存在了。

布隆过滤器的应用场景:新闻推送(不重复推送)。解决缓存穿透的问题。

四、缓存


问:缓存雪崩是什么?

如果缓存数据设置的过期时间是相同的,并且 Redis 恰好将这部分数据全部删光了。这就会导致在这段时间内,这些缓存同时失效,全部请求到数据库中。这就是缓存雪崩。

问:怎么解决缓存雪崩?

解决方法:在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期。

问:缓存穿透是什么?

缓存穿透是指查询一个一定不存在的数据。由于缓存不命中,并且出于容错考虑,如果从数据库查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,失去了缓存的意义。

问:怎么解决缓存穿透?

问:什么是缓存与数据库双写一致问题?

问:如何保证缓存与数据库的一致性?

读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。

先删除缓存,再更新数据库。

问:为什么是先删除缓存,而不是先更新缓存?

问:先更新数据库,再删除缓存,会有什么问题?

先更新数据库,再删除缓存。可能出现以下情况:

如果更新完数据库, Java 服务提交了事务,然后挂掉了,那 Redis 还是会执行,这样也会不一致。

如果更新数据库成功,删除缓存失败了,那么会导致数据库中是新数据,缓存中是旧数据,数据就出现了不一致。

先删除缓存,再更新数据库。

如果删除缓存失败,那就不更新数据库,缓存和数据库的数据都是旧数据,数据是一致的。

如果删除缓存成功,而数据库更新失败了,那么数据库中是旧数据,缓存中是空的,数据不会不一致。因为读的时候缓存没有,所以去读了数据库中的旧数据,然后更新到缓存中。

问:先删除缓存,在写数据库成功之前,如果有读请求发生,可能导致旧数据入缓存,引发数据不一致,怎么处理?

分布式锁

问:Redis 如何实现分布式锁?

使用 set key value ex nx 命令。

当 key 不存在时,将 key 的值设为 value ,返回 1。若给定的 key 已经存在,则 setnx 不做任何动作,返回 0。

当 setnx 返回 1 时,表示获取锁,做完操作以后 del key ,表示释放锁,如果 setnx 返回 0 表示获取锁失败。

详细的命令如下:

set key value [EX seconds] [PX milliseconds] [NX|XX]

EX seconds:设置失效时长,单位秒

PX milliseconds:设置失效时长,单位毫秒

NX:key不存在时设置value,成功返回OK,失败返回(nil)

XX:key存在时设置value,成功返回OK,失败返回(nil)。

示例如下:

set name fenglin ex 100 nx

问:为什么不先 set nx ,然后再使用 expire 设置超时时间?

我们需要保证 setnx 命令和 expire 命令以原子的方式执行,否则如果客户端执行 setnx 获得锁后,这时客户端宕机了,那么这把锁没有设置过期时间,导致其他客户端永远无法获得锁了。

问:使用 Redis 分布式锁, key 和 value 分别设置成什么?

value 可以使用 json 格式的字符串,示例:

{

“count”:1,

“expireAt”:147506817232,

“jvmPid”:22224,

“mac”:“28-D2-44-0E-0D-9A”,

“threadId”:14

}

问:Redis 实现的分布式锁,如果某个系统获取锁后,宕机了怎么办?

系统模块宕机的话,可以通过设置过期时间(就是设置缓存失效时间)解决。系统宕机时锁阻塞,过期后锁释放。

问:设置缓存失效时间,那如果前一个线程把这个锁给删除了呢?

问:如果加锁和解锁之间的业务逻辑执行的时间比较长,超过了锁过期的时间,执行完了,又删除了锁,就会把别人的锁给删了。怎么办?

这两个属于锁超时的问题。

可以将锁的 value 设置为 Json 字符串,在其中加入线程的 id 或者请求的 id ,在删除之前, get 一下这个 key ,判断 key 对应的 value 是不是当前线程的。只有是当前线程获取的锁,当前线程才可以删除。

问:Redis 分布式锁,怎么保证可重入性?

可以将锁的 value 设置为 Json 字符串,在其中加入线程的 id 和 count 变量。

当 count 变量的值为 0 时,表示当前分布式锁没有被线程占用。

如果 count 变量的值大于 0 ,线程 id 不是当前线程,表示当前分布式锁已经被其他线程占用。

如果 count 变量的值大于 0 ,线程 id 是当前线程的 id ,表示当前线程已经拿到了锁,不必阻塞,可以直接重入,并将 count 变量的值加一即可。

这种思路,其实就是参考了 ReentrantLock 可重入锁的机制。

问:Redis 做分布式锁, Redis 做了主从,如果设置锁之后,主机在传输到从机的时候挂掉了,从机还没有加锁信息,如何处理?

可以使用开源框架 Redisson ,采用了 redLock。

问:讲一下 Redis 的 redLock。

问:Zookeeper 是怎么实现分布式锁的?

分布式锁:基于 Zookeeper 一致性文件系统,实现锁服务。锁服务分为保存独占及时序控制两类。

保存独占:将 Zookeeper 上的一个 znode 看作是一把锁,通过 createznode 的方式来实现。所有客户端都去创建 / distribute _ lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除自己创建的 distribute _ lock 节点就释放锁。

时序控制:基于/ distribute _ lock 锁,所有客户端在它下面创建临时顺序编号目录节点,和选 master 一样,编号最小的获得锁,用完删除,依次方便。

更详细的回答如下:

其实基于 Zookeeper ,就是使用它的临时有序节点来实现的分布式锁。

原理就是:当某客户端要进行逻辑的加锁时,就在 Zookeeper 上的某个指定节点的目录下,去生成一个唯一的临时有序节点, 然后判断自己是否是这些有序节点中序号最小的一个,如果是,则算是获取了锁。如果不是,则说明没有获取到锁,那么就需要在序列中找到比自己小的那个节点,并对其调用 exist() 方法,对其注册事件监听,当监听到这个节点被删除了,那就再去判断一次自己当初创建的节点是否变成了序列中最小的。如果是,则获取锁,如果不是,则重复上述步骤。

当释放锁的时候,只需将这个临时节点删除即可。

五、Zookeeper


问:Zookeeper 的原理是什么?

问:Zookeeper 是怎么保证一致性的?

zab 协议。

zab 协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后, zab 就进入了恢复模式,当领导者被选举出来,且大多数 server 完成了和 leader 的状态同步以后,恢复模式就结束了。状态同步保证了 leader 和 server 具有相同的系统状态。

问:Zookeeper 有哪些应用场景?

Zookeeper 可以作为服务协调的注册中心。还可以做分布式锁(如果没有用过分布式锁就不要说)。

问:Zookeeper 为什么能做注册中心?

Zookeeper 的数据模型是树型结构,由很多数据节点组成, zk 将全量数据存储在内存中,可谓是高性能,而且支持集群,可谓高可用。另外支持事件监听(watch 命令)。

Zookeeper 可以作为一个数据发布/订阅系统。

问:Zookeeper 的节点有哪些类型?有什么区别?

临时节点,永久节点。更加细分就是临时有序节点、临时无序节点、永久有序节点、永久无序节点。

临时节点:当创建临时节点的程序停掉之后,这个临时节点就会消失,存储的数据也没有了。

问:Zookeeper 做为注册中心,主要存储哪些数据?存储在哪里?

IP、端口、还有心跳机制。数据存储在 Zookeeper 的节点上面。

问:心跳机制有什么用?

问:Zookeeper 的广播模式有什么缺陷?

广播风暴。

问:讲一下 Zookeeper 的读写机制。

Leader 主机负责读和写。

Follower 负责读,并将写操作转发给 Leader。Follower 还参与 Leader 选举投票,参与事务请求 Proposal 投票。

Observer 充当观察者的角色。Observer 和 Follower 的唯一区别在于:Observer 不参与任何投票。

问:讲一下 Zookeeper 的选举机制。

Leader 不可用时,会重新选举 Leader。超过半数的 Follower 选举投票即可,Observer 不参与投票。

问:你们的 Zookeeper 集群配置了几个节点?

3 个节点。注意:Zookeeper 集群节点,最好是奇数个的。

集群中的 Zookeeper 节点需要超过半数,整个集群对外才可用。

这里所谓的整个集群对外才可用,是指整个集群还能选出一个 Leader 来, Zookeeper 默认采用 quorums 来支持 Leader 的选举。

如果有 2 个 Zookeeper,那么只要有 1 个死了 Zookeeper 就不能用了,因为 1 没有过半,所以 2 个 Zookeeper 的死亡容忍度为 0 ;同理,要是有 3 个 Zookeeper,一个死了,还剩下 2 个正常的,过半了,所以 3 个 Zookeeper 的容忍度为 1 ;同理你多列举几个:2 -> 0 ; 3 -> 1 ; 4 -> 1 ; 5 -> 2 ; 6 -> 2 会发现一个规律, 2n 和 2n - 1 的容忍度是一样的,都是 n - 1 ,所以为了更加高效,何必增加那一个不必要的 Zookeeper 呢。

问:Zookeeper 的集群节点,如果不是奇数可能会出现什么问题?

可能会出现脑裂。

假死:由于心跳超时(网络原因导致的)认为 master 死了,但其实 master 还存活着。

脑裂:由于假死会发起新的 master 选举,选举出一个新的 master ,但旧的 master 网络又通了,导致出现了两个 master ,有的客户端连接到老的 master 有的客户端链接到新的 master。

六、消息队列


问:为什么使用消息队列?消息队列有什么优点和缺点?Kafka 、ActiveMQ 、RabbitMq 、RocketMQ 都有什么优点和缺点?

消息队列解耦,削峰,限流。

问:如何保证消息队列的高可用?(多副本)

问:如何保证消息不被重复消费?(如何保证消息消费的幂等性)

问:如何保证消息的可靠性传输?(如何处理消息丢失的问题)

问:如何保证消息的顺序性?

问:如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?

问:如果让你写一个消息队列,该如何进行架构设计啊?说一下你的思路。

七、Kafka


问:讲一下 Kafka。

Kafka 的简单理解

问:Kafka 相对其他消息队列,有什么特点?

持久化:Kafka 的持久化能力比较好,通过磁盘持久化。而 RabbitMQ 是通过内存持久化的。

吞吐量:Rocket 的并发量非常高。

消息处理:RabbitMQ 的消息不支持批量处理,而 RocketMQ 和 Kafka 支持批量处理。

高可用:RabbitMQ 采用主从模式。Kafka 也是主从模式,通过 Zookeeper 管理,选举 Leader ,还有 Replication 副本。

事务:RocketMQ 支持事务,而 Kafka 和 RabbitMQ 不支持。

问:Kafka 有哪些模式?

如果一个生产者或者多个生产者产生的消息能够被多个消费者同时消费的情况,这样的消息队列称为"发布订阅模式"的消息队列。

问:Kafka 作为消息队列,有哪些优势?

分布式的消息系统。

高吞吐量。即使存储了许多 TB 的消息,它也保持稳定的性能。

数据保留在磁盘上,因此它是持久的。

问:Kafka 为什么处理速度会很快?kafka 的吞吐量为什么高?

零拷贝:Kafka 实现了"零拷贝"原理来快速移动数据,避免了内核之间的切换。

消息压缩、分批发送:Kafka 可以将数据记录分批发送,从生产者到文件系统(Kafka 主题日志)到消费者,可以端到端的查看这些批次的数据。

批处理能够进行更有效的数据压缩并减少 I / O 延迟。

顺序读写:Kafka 采取顺序写入磁盘的方式,避免了随机磁盘寻址的浪费。

问:讲一下 Kafka 中的零拷贝。

数据的拷贝从内存拷贝到 kafka 服务进程那块,又拷贝到 socket 缓存那块,整个过程耗费的时间比较高, kafka 利用了 Linux 的 sendFile 技术(NIO),省去了进程切换和一次数据拷贝,让性能变得更好。

问:Kafka 的偏移量是什么?

消费者每次消费数据的时候,消费者都会记录消费的物理偏移量(offset)的位置。等到下次消费时,他会接着上次位置继续消费

问:Kafka 的生产者,是如何发送消息的?

生产者的消息是先被写入分区中的缓冲区中,然后分批次发送给 Kafka Broker。

生产者的消息发送机制,有同步发送和异步发送。

同步发送消息都有个问题,那就是同一时间只能有一个消息在发送,这会造成许多消息。

无法直接发送,造成消息滞后,无法发挥效益最大化。

异步发送消息的同时能够对异常情况进行处理,生产者提供了 Callback 回调。

问:Kafka 生产者发送消息,有哪些分区策略?

Kafka 的分区策略指的就是将生产者发送到哪个分区的算法。有顺序轮询、随机轮询、key - ordering 策略。

key - ordering 策略:Kafka 中每条消息都会有自己的 key ,一旦消息被定义了 Key ,那么你就可以保证同一个 Key 的所有消息都进入到相同的分区里面,由于每个分区下的消息处理都是有顺序的,故这个策略被称为按消息键保序策略。

问:Kafka 为什么要分区?

实现负载均衡和水平扩展。Kafka 可以将主题(Topic)划分为多个分区(Partition),会根据分区规则选择把消息存储到哪个分区中,只要如果分区规则设置的合理,那么所有的消息将会被均匀的分布到不同的分区中,这样就实现了负载均衡和水平扩展。另外,多个订阅者可以从一个或者多个分区中同时消费数据,以支撑海量数据处理能力。

问:Kafka 是如何在 Broker 间分配分区的?

在 broker 间平均分布分区副本。

假设有 6 个 broker ,打算创建一个包含 10 个分区的 Topic ,复制系数为 3 ,那么 Kafka 就会有 30 个分区副本,它可以被分配给这 6 个 broker ,这样的话,每个 broker 可以有 5 个副本。

要确保每个分区的每个副本分布在不同的 broker 上面:

假设 Leader 分区 0 会在 broker1 上面, Leader 分区 1 会在 broker2 上面, Leder 分区 2 会在 broker3 上面。

接下来会分配跟随者副本。如果分区 0 的第一个 Follower 在 broker2 上面,第二个 Follower 在 broker3 上面。分区 1 的第一个 Follower 在 broker3 上面,第二个 Follower 在 broker4 上面。

问:Kafka 如何保证消息的顺序性?

Kafka 可以保证同一个分区里的消息是有序的。也就是说消息发送到一个 Partition 是有顺序的。

问:Kafka 的消费者群组 Consumer Group 订阅了某个 Topic ,假如这个 Topic 接收到消息并推送,那整个消费者群组能收到消息吗?

Kafka 官网中有这样一句" Consumers label themselves with a consumer group name , and each record published to a topic is delivered to one consumer instance within each subscribing consumer group . "

表示推送到 topic 上的 record ,会被传递到已订阅的消费者群组里面的一个消费者实例。

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

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

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

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

最后

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
在这里插入图片描述

record published to a topic is delivered to one consumer instance within each subscribing consumer group . "

表示推送到 topic 上的 record ,会被传递到已订阅的消费者群组里面的一个消费者实例。

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

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

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-gkPSJMoV-1711463900604)]
[外链图片转存中…(img-oLPkBXmE-1711463900605)]
[外链图片转存中…(img-URJ7EQPw-1711463900606)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-iTC5raHR-1711463900607)]

最后

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
[外链图片转存中…(img-1VRaEIzA-1711463900607)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值