初级JAVA开发面试题分享(四)

53 阅读12分钟

面试题由23年8月开始记录,主要参考B站黑马程序员的视频(新版Java面试专题视频教程,java八股文面试全套真题+深度详解(含大厂高频面试真题)_哔哩哔哩_bilibili)和JavaGuide(项目介绍 | JavaGuide),并在多次面试中二次改进并增加题目。内容仅供参考,建议理解使用。

前言

本篇内容主要为RabbitMq、Redis和Mysql,这些内容在初级面试中被问到的频率较高,多数是基础问题。

RabbitMQ

RabbitMQ-如何保证消息不丢失

image.png

image.png

image.png

image.png

image.png

RabbitMQ消息的重复消费问题如何解决

image.png

RabbitMQ中死信交换机(RabbitMQ延迟队列有了解过吗)

image.png

image.png

image.png

image.png

image.png

RabbitMQ如果有100万消息堆积在MQ,如何解决(消息堆积怎么解决)

image.png

image.png

image.png

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

image.png

Redis

如果发生了缓存穿透、击穿、雪崩,该如何解决

缓存三兄弟

  • 穿透无中生有key,布隆过滤null隔离。
  • 缓存击穿过期key,锁与非期解难题。
  • 雪崩大量过期key,过期时间要随机。
  • 面试必考三兄弟,可用限流来保底。
缓存穿透

查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库

例子: 一个get请求: api/news/getById/1

image.png

  • 解决方案一

    • 缓存空数据,查询返回的数据为空,扔把这个空结果进行缓存
      • {key:1, value:null}
      • 简单
      • 但消耗内存,可能会发生不一致的问题
  • 解决方案二

    • 布隆过滤器
      • 内存占用少,没有多余的key
      • 但实现复杂,存在误判

image.png

布隆过滤器

bitmap(位图) : 相当于以(bit)位为单位的数据,数组中每个单元只能存储二进制数0或1

布隆过滤器作用: 可以用于检索一个元素是否存在一个集合中,拦截不存在的数据

image.png

误判情况: image.png 误判率: 数组越小误判率越大, 数组越大误判率就越小, 但是同时带来更多的内存消耗

  • 布隆过滤器实现方案
  • Redisson
  • Guava
缓存击穿

给某一个key设置了过期时间,当key过期时,恰好这时间点有大量对这个key的并发请求,这些并发请求可能瞬间把db压垮

例子: image.png

  • 解决方案一

    • 互斥锁

      • 强一致
      • 但性能差
      • 适用于支付业务

image.png

  • 解决方案二

    • 逻辑过期

      • 高可用
      • 性能优
      • 但不能保证数据绝对一直
      • 适用于注重用户体验业务

image.png

缓存雪崩

同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力

image.png

  • 解决方案

    • 给不同的key的TTL添加随机值

    • 利用Redis集群提高服务的可用性(哨兵模式、集群模式)

    • 给缓存业务添加降级限流策略(ngxin、Spring cloud gateway)

      • 降级可作为系统的保底策略,适用于穿透、击穿、雪崩
    • 给业务添加多级缓存(Guava或Caffeine)

redis作为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)

双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致 image.png

  • 读操作
  • 缓存命中,直接返回;
  • 缓存未命中,写入缓存,设定超时时间
  • 写操作
  • 延迟双删 image.png
  • 强一致性业务

    • 强一致
    • 性能低

image.png

  • 共享锁
  • 读锁readLock,加锁之后,其他线程可以共享读操作

image.png

  • 排它锁
  • 独占锁writeLock,加锁之后,线程阻塞其他线程读写操作

image.png

  • 允许短暂不一致业务

    • 异步通知保证数据的最终一致性

基于MQ

image.png

基于Canal

image.png

image.png

redis作为缓存,数据的持久化是怎么做的?

  • RDB

    • 全称Redis Database Backup file(Redis数据备份文件), 也叫Redis数据快照。
    • 简单来说就是把内存中的所有数据都记录到磁盘中。当redis实例故障重启后,从磁盘读取快照文件,恢复数据

image.png

  • RDB的执行原理
  • bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入RDB文件
  • fork采用的是copy-on-write技术
    • 当主进程执行读操作时,访问共享内存
    • 当主进程执行写操作时,则会拷贝一份数据,执行写操作

image.png

  • AOF

    • 全称Append Only File(追加文件)。Redis处理的每一个命令都会记录在AOF文件,可以看做是命令日志文件。AOF持久化方式是将redis的操作日志以追加的方式写入磁盘文件中。

image.png

AOF是默认关闭的,需要修改redis.conf配置文件来开启AOF

image.png

AOF的命令记录的频率也可以通过redis.conf文件来配

image.png

因为是记录命令,AOF文件会比RDB文件大得多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。

image.png Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置 image.png

RDB和AOF各有优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者使用。

image.png

加入redis的key过期之后,会立即删除吗?

Redis对数据设置的有效时间,数据过期之后,就需要将数据从内存中删除掉。可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略)。

  • 惰性删除

    • 设置key过期时间后,我们不去管它,当需要该key时,在检查其是否过期,如果过期,我们就删掉,反之返回该key
    • 对CPU友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查
    • 对内存不友好,如果一个key已经过期,但是一直没有使用,该key就会一直存在内存中,内存永远不会释放
  • 定期删除

    • 每隔一段时间,就对一些key进行检查,删除里面过期的key(从一定数量的数据库中取出一定数量的随机key进行检查,并删除其中过期的key)。
    • 可以通过限制删除操作执行的时长和频率来减少删除操作对CPU的影响。另外定期删除也能有效释放过期键占用的内存。
    • 但难以确定删除操作执行的时长和频率

定期清理有两种模式

  • SLOW模式是定时任务,执行频率默认为10hz,每次不超过25ms,以通过修改配置文件redis.conf的hz选项来调整这个次数
  • FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms Redis的过期删除策略: 惰性删除 + 定期删除进行配合使用 image.png

假如缓存过多,内存是有限的,内存被占满了怎么办?(redis的数据淘汰策略)

当Redis中内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中数据删除掉,这种数据的删除规则被称为内存的淘汰策略。

  • noeviction(默认策略)
    • 不淘汰任何key,但是内存满时不允许写入新数据
  • volatile-ttl
    • 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰
  • allkeys-random
    • 对全体key,随机进行淘汰
  • volatile-random
    • 对设置了TTL的key,随机进行淘汰
  • allkeys-lru
    • 对全体key,基于LRU算法进行淘汰
  • volatile-lru
    • 对设置了TTL的key,基于LRU算法进行淘汰
  • allkeys-lfu
    • 对全体key,基于LFU算法进行淘汰
  • volatile-lfu
    • 对设置了TTL的key,基于LFU算法进行淘汰

image.png

redis分布式锁是如何实现的?

Redis实现分布式锁

Redis实现分布式锁主要利用Redis的setnx命令。setnx是SET if not exists(如果不存在,则SET)的简写。

  • 获取锁
  •     # 添加锁,NX是互斥,EX是设置超时时间
        SET lock value NX EX 10
    
  • 释放锁
  •     # 释放锁,删除即可
        DEL key
    

image.png image.png

redisson实现的分布式锁

image.png image.png

加锁、设置过期时间等操作都是基于lua脚本完成

image.png image.png

image.png

其他面试题

五种基本数据类型

  • String(字符串)
    • 需要存储常规数据的场景
      • 举例:缓存 Session、Token、图片地址、序列化后的对象(相比较于 Hash 存储更节省内存)。
      • 相关命令:SETGET
    • 需要计数的场景
      • 举例:用户单位时间的请求数(简单限流可以用到)、页面单位时间的访问数。
      • 相关命令:SETGETINCRDECR
    • 分布式锁
      • 利用 SETNX key value 命令可以实现一个最简易的分布式锁(存在一些缺陷,通常不建议这样实现分布式锁)。
  • List(列表)
    • 信息流展示
      • 举例:最新文章、最新动态。
      • 相关命令:LPUSH、LRANGE。
  • Hash(散列)
    • 对象数据存储场景
      • 举例:用户信息、商品信息、文章信息、购物车信息。
      • 相关命令:HSET (设置单个字段的值)、HMSET(设置多个字段的值)、HGET(获取单个字段的值)、HMGET(获取多个字段的值)。
  • Set(集合)
    • 需要存放的数据不能重复的场景
      • 举例:网站 UV 统计(数据量巨大的场景还是 HyperLogLog更适合一些)、文章点赞、动态点赞等场景。
      • 相关命令:SCARD(获取集合数量) 。
    • 需要获取多个数据源交集、并集和差集的场景
      • 举例:共同好友(交集)、共同粉丝(交集)、共同关注(交集)、好友推荐(差集)、音乐推荐(差集)、订阅号推荐(差集+交集) 等场景。
      • 相关命令:SINTER(交集)、SINTERSTORE (交集)、SUNION (并集)、SUNIONSTORE(并集)、SDIFF(差集)、SDIFFSTORE (差集)。
  • Sorted Set(有序集合)
    • 需要随机获取数据源中的元素根据某个权重进行排序的场景
      • 举例:各种排行榜比如直播间送礼物的排行榜、朋友圈的微信步数排行榜、王者荣耀中的段位排行榜、话题热度排行榜等等。
      • 相关命令:ZRANGE (从小到大排序)、 ZREVRANGE (从大到小排序)、ZREVRANK (指定元素排名)。

3 种特殊数据类型详解

  • Bitmap
    • 需要保存状态信息(0/1 即可表示)的场景
      • 举例:用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)。
      • 相关命令:SETBIT、GETBIT、BITCOUNT、BITOP。
  • HyperLogLog
    • 数量量巨大(百万、千万级别以上)的计数场景
      • 举例:热门网站每日/每周/每月访问 ip 数统计、热门帖子 uv 统计、
      • 相关命令:PFADDPFCOUNT
  • GEO
    • 需要管理使用地理空间数据的场景

      • 举例:附近的人。
      • 相关命令: GEOADDGEORADIUSGEORADIUSBYMEMBER

MYSQL

基础

优化

在MYSQL中,如何定位慢查询?

image.png

  • 方案一:开源工具
    • 调试工具
      • Arthas
    • 运维工具
      • Prometheus、Skywalking
  • 方案二:Mysql自带慢日志
    • 慢日志记录所有执行时间超过制定参数(long_query_time,单位: 秒,默认10秒)的所有SQL语句的日志
    • 需要再mysql的配置文件(/etc/my.cnf)中配置开启慢查询日志 image.png
    • 配置完成之后,重启mysql服务器进行测试,查看慢日志文件中记录的信息/var/lib/mysql/localhost-slow.log image.png

image.png

SQL语句执行很慢,如何分析

可以采用EXPLAIN或者DESC命令获取MySQL如何执行SELECT语句的信息 image.png

  • type
    • sql的连接类型
  • prossible_key
    • 当前sql可能用到的索引
  • key
    • 当前sql实际命中的索引
  • key_len
    • 索引占用的大小
  • Extra
    • 额外的优化建议

image.png

了解过索引吗?(什么是索引)

详情可看B站尚硅谷的视频115-为什么使用索引及索引的优缺点_哔哩哔哩_bilibili

MySQL索引详解 | JavaGuide

image.png

什么是聚簇索引,什么是非聚簇索引?

image.png

image.png

知道什么叫覆盖索引吗?

image.png

MYSQL超大分页处理 image.png image.png image.png

适合建立索引的情况

  • 字段的数值有唯一性的限制
  • 频繁作为 WHERE 查询条件的字段
  • 经常 GROUP BY 和 ORDER BY 的列
  • UPDATE、DELETE 的 WHERE 条件列
  • DISTINCT 字段需要创建索引
  • 多表 JOIN 连接操作时,创建索引注意事项
  • 使用列的类型小的创建索引
  • 使用字符串前缀创建索引
  • 区分度高(散列性高)的列适合作为索引
  • 使用最频繁的列放到联合索引的左侧
  • 在多个字段都要创建索引的情况下,联合索引优于单值索引

不适合建立索引的情况

  • where中使用不到的字段,不要设置索引
  • 数据量小的表最好不要使用索引
  • 大量重复数据的列上不要建立索引
  • 避免对经常更新的表创建过多的索引
  • 不建议用无序的值作为索引
  • 删除不再使用或者很少使用的索引
  • 不要定义冗余或重复的索引

索引创建原则有哪些?

image.png

image.png

什么情况下索引会失效?

image.png

谈谈对sql的优化经验

image.png

Mysql锁有哪些,如何理解

  • 表锁
    • 读锁、写锁
    • 意向锁
    • 自增锁
    • 元数据锁
  • 行锁
    • 记录锁
    • 间隙锁
    • 临键锁
    • 插入意向锁
  • 页锁
  • 悲观锁
  • 乐观锁
  • 显式锁、隐式锁
  • 全局锁
  • 死锁

其他面试题

事务的特性是什么?可以详细说一下吗?(ACID)

image.png

并发事务带来哪些问题?怎么解决这些问题?MySQL默认的隔离级别是什么?

  • 并发事务问题
    • 脏读
    • 不可重复读
    • 幻读
  • 隔离级别
    • 读未提交
    • 读已提交
    • 可重复读
    • 串行化

image.png

undo log和redo log的区别

image.png image.png image.png

image.png

事务的隔离性说如何保证的呢?

  • 排他锁
    • 如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁
  • MVCC
    • 多版本并发控制

image.png image.png image.png image.png image.png image.png image.png

image.png

尾声

本篇为初级面试题最后一篇,后续会抽空分享面试心得与工作心得,感谢您的阅读。