当前位置: 首页 > article >正文

Java八股文详细文档.2(基于黑马、ChatGPT、DeepSeek)

        通过B站黑马程序员的八股文教学,自己也二刷了,结合ChatGpt、deepSeek总结了一下,Java八股文详细文档.2(Redis篇和消息中间件篇,还没有写完,这只是一部分)

        Java八股文详细文档.1(包含JVM篇、数据库篇和常见集合篇):

https://blog.csdn.net/weixin_73144915/article/details/145535602?spm=1001.2014.3001.5502

         Java八股文详细文档.3(包含框架篇和并发编程篇):

https://blog.csdn.net/weixin_73144915/article/details/145535602?spm=1001.2014.3001.5502

        Java八股文面试重点完整版:

https://blog.csdn.net/weixin_73144915/article/details/145657974?spm=1001.2014.3001.5501

 四、Reids篇

1.什么是缓存穿透,怎么处理?

       缓存穿透是指请求数据时,缓存中没有该数据,并且数据库中也没有改数据,导致每次请求都绕过了缓存直接访问数据库,造成缓存失效,数据库压力增大;

(1)使用布隆过滤器:一种概率性数据结构,能够高效判断一个元素是否在一个集合中,但也存在误判(跟内存成反比)

  1. 在访问缓存之前使用布隆过滤器判断某个请求的数据是否存在,如果不存在则直接返回空或错误信息,避免查询数据库;
  2. 如果布隆过滤器认为数据存在,才查询缓存,如果缓存也没有再查询数据库并将结果放入缓存中;

(2)缓存空对象:对于缓存和数据库都查询不到的对象,我们可以将该对象设置为空缓存起来,需要设置合适的过期时间,防止空对象长时间存在缓存中。

2.什么是缓存击穿,怎么处理?

缓存击穿是指某个热点数据过期,导致在同一时间内大量请求直接访问数据库,导致数据库压力过大甚至崩溃;

(1)使用互斥锁,强一致性但性能差;

(2)使用逻辑过期,高可用性和性能好,但不能保证数据强一致性;

3.什么是缓存雪崩,怎么处理?

       缓存雪崩是指在同一时间内有大量的缓存key同时失效或者Redis服务宕机,导致大量请求访问数据库,给数据库带来巨大压力。

(1)随机设置过期时间,避免同一时间内大量key过期;

(2)使用分布式锁来实现互斥锁,确保同一时刻只有一个请求可以访问;

(3)缓存预热,通过定时任务或根据访问频率加载热点数据,减少缓存未命中的概率

(4)降级处理,缓存未命中返回默认值或备用缓存;

4.reids作为缓存,怎么确保数据库和redis的数据进行同步?(结合黑马点评)(重点)

(1)项目中把文章的热点数据先存入到缓存中,虽然是热点数据但实时要求没有这么高,所以采用了异步通知的方案,就是使用MQ中间件,更新数据之后,通知缓存删除数据。也可以使用canal中间件,不需要修改业务代码,伪装成MySQL的一个从节点,canal通过读取binlog数据更新缓存;

(2)项目中将抢卷存入缓存中,这个需要实时的进行数据同步,为了确保数据的强一致性,采用的是redission提供的读写锁来保证数据的同步。一旦加锁后,就会阻塞其他线程进行读写操作。

5.Redis作为缓存,数据的持久化是怎么实现的?(重点)

       Redis中提供了两种数据持久化的方式,一种是RDB,另一种是AOF。RDB是一个快照文件,将redis存储的数据写到磁盘中,当redis实例宕机恢复数据时,可以从RDB的快照文件中恢复数据;而AOF是追加文件,当redis操作写命令时,都会存储到这个文件中,当redis实例宕机恢复数据时,就可以从这个文件再次执行一遍命令来恢复数据;

6.Redis的数据过期策略有哪些?

(1)定期删除:Redis会定期扫描数据库中的键,检查这些键的过期时间,如果键的过期时间到了,就会立即删除,通常是每100毫秒扫描一次;

(2)惰性删除:当你访问一个键时,Reids会检查这个键首付过期,如果过期立即删除,也就是说过去数据只有被访问时才会被删除;

(3)内存不足时删除:当Reids的内存使用达到限制时,会根据淘汰策略删除一些过期或不常用的键。

       因此,Redis的过期删除策略时定期删除和惰性删除配合使用。

7.Redis的数据淘汰策略有哪些?(重点)

(1)不淘汰任何的key,当内存满时写入新数据就会报错(默认)

(2)对于设置了TTL的数据,比较key的TTL剩余值,越小越优先淘汰

(3)对全体/设置了TTL的key,随即进行淘汰

(4)对全体/设置了TTL的key,基于LRU(最近最少使用)算法进行淘汰

(5)对全体/设置了TTL的key,基于LFU(最少频率使用)算法进行淘汰

       综上,建议根据业务需求设置数据淘汰策略如下:

(1)如果业务中有明显的冷热数据区分,使用allkeys-lru 策略,将最近最常访问的数据留在缓存中;

(2)如果业务中数据访问频率差别不大,建议使用allkeys-random,随机淘汰

(3)如果业务有置顶的需求,可以使用volatile-lru策略,确保没有设置过期时间的数据不被删除

(4)如果业务中有短时高频访问的数据,可以使用allkeys-lfu或volatile-lfu策略

8.redis分布式锁是怎么实现的?(重点)

       项目中我是使用redission实现的分布式锁,底层是setnx和lua脚本(保证原子性),在redission的分布式锁中,提供了一个看门狗机制,一个线程获取锁成功之后,看门狗会次序给持有锁的线程续期(默认是每隔10秒续期一次);另外,redission是可以重入的,根据线程ID判断持有锁的是否当前线程,利用hash结构存储线程信息和重入的次数,当重入的次数为0时就释放锁;但这个不能解决redis主从数据一致的问题,可以使用redission提供的红锁来解决(因性能低不推荐使用),如果非要保证数据的强一致性,建议使用zookeepr实现分布式锁;

9.能介绍一下redis主从数据同步吗

       因为单节点Redis的并发能力是有上限的,如果想要进一步提高reids的并发能力,可以搭建主从集群,实现读写分离。一般默认是一主多从,主节点负责写操作,从节点负责读操作。主节点写入数据之后,需要把数据同步到从节点中。

主节点会先判断是否第一次请求,如果是第一次请求就会跟从节点同步版本信息;主节点执行bssave命令,生成RDB文件后发送给从节点去执行,在RDB生成执行期间,主节点会以命令的方式记录到缓冲区(日志文件),把生成的命令日志文件发送到从节点进行同步。

10.redis是单线程的,为啥还这么快?(重点)

(1)Redis 是基于内存的数据库,访问速度远远高于磁盘存储系统;

(2)正因为采用的是单线程,确保了每个操作的执行顺序和一致性,避免了复杂的并发控制和锁机制;

(3)使用IO多路复用模型,并非阻塞IO;

(4)redis的存储形式是简单的键值对和一些字符串、哈希等数据结构,并且每个命令也不复杂;

五、消息中间件篇

1.RabbitMQ 如何保证消息不丢失?

(1)开启生产者确认机制,确保生产者的消息能达到队列;

(2)开启持久化功能,确保消息未消费前在队列中不会丢失;

(3)开启消费者确认机制为auto,由spring确认消息处理成功后完成ack;

(4)开启消费者失败重试机制,多次重试失败后将消息投递到异常交换机,交由人工处理;

2.RabbitMQ消息的重复消费问题怎么解决?

(1)启用消息确认(ack),确保每次消费者成功处理完消息后,发送一个信号给RabbitMQ, 如果消费者处理失败,重新排队未确认的消息;

(2)幂等性:无论消息是否被重复消费,最终结果应该是一样的,如果使用数据库,可以检查消息是否已经被处理过(或者使用rediss分布式锁)

(3)给每个消息设置唯一ID(UUID或雪花算法),判断该消息是否被消费过

3.延迟队列了解过吗?(重点)

       延迟队列是通过死信交换机+TTL实现的。我们可以先把消息的TTL设置为需要的延迟时间,消息在TTL过期之后会被转发到死信队列,接着消费者到死信队列中消费消息,从而达到延迟消费的作用。一般需要延迟队列的场景有超时订单、限时优惠、定时发布等。

4.消息队列有很多消息累积怎么解决?

       这个问题就是消费速度比不上生产速度,重点是怎么提高消费速度。第一,可以增加更多的消费者,提高消费速度。第二、在消费者内开启线程池可以加快消息处理速度。

另外,可以扩大队列容积,提高堆积上线,比如采用惰性队列,它是基于磁盘存储的,性能比较稳定,但是受限于磁盘IO,时效性会降低。

重平衡(Rebalance) 是 Kafka 中消费者组(Consumer Group)在消费过程中经常遇到的一个情况,尤其是在消费者的数量发生变化(加入或离开)或消费者与 Kafka 集群之间的负载不均衡时。简单来说,重平衡是指 Kafka 会重新分配消费者组中各个消费者负责的分区。

5.RabbitMQ的高可用机制有了解过吗?

       在生产环境下,可以采用镜像集群模式来搭建集群,共有三个节点;镜像集群结构是一主多从(从节点就是镜像),所有的操作都在主节完成,接着同步给镜像节点;如果主节点宕机,镜像节点会替代成为新的主节点(如果主从同步完成前,刚好主节点宕机,可能会导致数据丢失)

       如果数据丢失,我们可以采用仲裁队列(声明队列时候指定为仲裁队列即可),跟镜像队列一样都是主从模式,支持主从数据同步,它们的主从同步是基于Raft协议的,具有强一致性

6.Kafka是如何保证消息不丢失的?

       Kafka的大致流程可以概括为:生产者向Kafka集群发送消息,消息被存储到某个主题的某个分区,消费者从对应的分区中消费消息,需要从三个层面解决这个问题:

(1)生产者发送消息到Brocker丢失:可以设置异步回调发送,如果发送失败,我们可以通过回调获取失败后的消息信息,考虑重试或记录日志;还可以设置消息重试机制,避免因网络抖动导致发送不成功的问题

(2)消息在Broker中存储丢失:可以设置发送确认acks(默认为1),acks=1 表示只需要等待 Leader 分区确认,acks=all 表示等待所有follwer分区确认。可以选择acks=all,让所用副本都确认保存数据。

(3)消费者从Broker接收消息丢失:Kafka消费信息都是按照offset进行标记消费的,可以关闭默认的自动提交偏移量(每5秒提交一次),改为手动提交,当消费成功后在报告给broker,这样可以避免消息丢失和重复消费。

7.Kafka中的消息重复消费怎么解决?

(1)Kafka消费消息都是按照偏移量来进行标记消费的,消费者默认是自动提交已经消费的偏移量(默认每隔5秒发送一次),如果出现重平衡的情况,可能会重复消费或丢失数据。我们可以设置为手动提交偏移量,当消费成功后在报告给broker消费的位置。

(2)幂等方案(设置分布式锁,数据库的乐观锁和悲观锁)

8.KafKa是如何保证消费的顺序性?

       一个主题的数据可能会存储到不同的分区中,每个分区都是按照消息写入来存储的,如果消费者关联了多个分区就不能保证顺序性。解决方案如下:

(1)发送消息时指定分区号;

(2)发送消息时按照相同的业务设置相同的key;

9. RabbitMQ的高可用机制有了解过吗?

       这主要是两个方面,一个是集群,另一个是复制机制:

(1)Kafka集群指的是它有多个broker实例组成,即使某一台实例宕机了,也不耽误其他broker继续对外提供服务;

(2)一个主题有多个分区,每个分区有多个fllower和一个leader,如果leader发生故障,会自动将其中一个follower提升为leader,保证了系统的高可用性;

10.Kafka中是怎么实现高性能的设计?

(1)消息分区:不受单台服务器的限制,不受限地处理更多的数据;

(2)顺序读写:磁盘顺序读写,提升读写效率;

(3)页缓存:把磁盘中的数据缓存到内存中,把对磁盘的访问改为对内存的访问;

(4)零拷贝:减少上下文切换以及数据拷贝;

(5)消息压缩:较少磁盘IO和网络IO;

(6)分批发送:将消息打包批量发送,减少网络开销;


http://www.kler.cn/a/547353.html

相关文章:

  • Linux软件编程——标准IO(2025.2.14)
  • 微信小程序 - 组件
  • DELL 服务器 OpenManage监控指标释义
  • 2024年认证杯SPSSPRO杯数学建模A题(第二阶段)保暖纤维的保暖能力全过程文档及程序
  • [生信云问题分析] 为什么医院/单位/校园网络,无法通过ssh协议访问服务器
  • Macos下载 unity 的步骤与使用方法
  • 架构——LVS负载均衡主要模式及其原理、服务水平、优缺点
  • 正则表达式(竞赛篇)
  • Spring Boot 从 2.7.x 升级到 3.3注意事项
  • VS编译生成moc文件
  • 【Docker】容器被停止/删除的方式及命令:全面解析与实践指南
  • 文生图与图生图两款AI工具Midjourney(MJ)和Stable Diffusion(SD)对比
  • React生产环境下使用mock.js
  • C# 调用 C++ 动态库接口
  • 【LeetCode: 611. 有效三角形的个数 + 排序 + 双指针】
  • 07:串口通信(二):收发数据包
  • SQL SERVER的PARTITION BY应用场景
  • 滑动窗口算法篇:连续子区间与子串问题
  • 算法与数据结构(多数元素)
  • Spring篇--AOP