java面试总结-20250605

发布于:2025-06-15 ⋅ 阅读:(21) ⋅ 点赞:(0)

synchronized和lock API的区别

区分点 synchronized lock api
来源 java内置关键字 java.util.concurrent包
获取锁时是否可以响应中断 不能响应中断 可以,使用lock.lockInterruptibly()
支持的锁类型 非公平锁,有锁升级的过程(无锁->偏向锁->轻量级锁->重量级锁) 支持非公平锁和公平锁(ReentrantLock lock = new ReentrantLock(boolean fair))
加锁和释放 自动释放锁 手动释放锁,在finally中释放
锁信息获取 不可获取锁信息 可以通过lock.isLocked()查看是否获取到锁
获取锁方式 阻塞 支持阻塞lock.lock()和非阻塞方式获取锁lock.tryLock()、lock.tryLock(timeout)
实现方式 对象头中的监视器 AQS

注意:synchronized和lock在获取锁之后都可以响应中断,java的中断Thread.interrupt()方法只有在线程执行如Thread.sleep()、Thread.sleep(timeout)、Thread.join()、Thread.join(timeout)、Object.wait()、Object.wait(timeout)等阻塞时才会抛出InterruptedException异常,其他情况下只会设置中断标志为true。

AQS原理

todo 补充aqs原理

java内存模型分为哪些区域,哪些区域会发生GC,哪些区域会发生OOM?

区域 是否发生GC 是否发生OOM
程序计数器
虚拟机栈
本地方法栈
元空间
直接内存

java垃圾收集器和工作原理?

todo 补充具体工作流程

CMS

分代模型:新生代+老年代
工作流程:
初始标记(STW),并发标记,重新标记(STW)、并发清除
问题:

  • 使用标记-清除 回收算法产生内存碎片,可能会触发fullgc
  • cpu敏感,并发阶段占用cpu资源
  • 浮动垃圾:无法处理标记后产生的新垃圾

G1:
分代模型:新生代+老年代
工作流程:
初始标记(STW),并发标记,重新标记(STW)、并发清除
问题:

  • 使用标记-清除 回收算法产生内存碎片,可能会触发fullgc
  • cpu敏感,并发阶段占用cpu资源
  • 浮动垃圾:无法处理标记后产生的新垃圾

MySQL主从同步数据机制?

主从同步流程

  • 主库写操作
  • 写入binlog
  • binlog dump线程发送给从库
  • 从库I/O线程接收写入relay log中
  • 从库SQL线程重放

复制方式

  • 异步复制
    主库提交事务后立即返回客户端,不等待从库确认。吞吐量高,但主库故障数据可能丢失。
  • 半同步复制
    主从提交事务后,等待至少一个从库确认接收binlog才返回。降低了数据丢失风险,吞吐量下降。
  • 全同步复制
    主库事务需从库全执行完才返回成功。强一致性系统,性能消耗明显。

binlog格式对比差异

格式 定义 优点 缺点
statement 记录sql语句 日志量小 UUID随机函数、时区不一致导致主从数据不一致
row 记录每行数据变更,原始值、新值 主从数据一致 日志量大
mixed 混合模式,默认statement,涉及到不确定操作时切换到row 平衡性能和一致性 -

undolog、redolog分别是什么含义,用来做什么?

先进行一个总体比较

维度 undolog redolog
含义 用来做事务的回滚 用来做事务的持久化和奔溃恢复
日志类型 逻辑日志 物理日志,记录物理页的修改
写入时机 事务修改数据前 事务提交前
生命周期 异步清理(purge线程) 固定大小,循环覆盖

TODO 补充各自特性

Innodb一级索引和二级索引的区别?

一级索引:又称聚簇索引,叶子节点存储的是数据列,数据行按照主键顺序物理排列。
一级索引的生成:如果显示定义了主键,直接使用主键作为_row_id;如果有唯一索引,则使用唯一索引作为_row_id;否则隐式生成_row_id作为一级索引。

二级索引:又称非聚簇索引,叶子节点存储的主键值。查询时如果使用二级索引,需要回表获取具体的数据行。

Innodb和myisam主键索引的区别?

innodb主键索引即数据文件,物理存储按照主键顺序,如果频繁插入无序主键,会有页分裂和索引调整,性能下降;
myisam所有索引均为非聚簇索引,主键索引和数据文件分开存储,索引文件存储主键值和数据文件地址的偏移量,主键索引需要两次IO(索引-数据文件)。无需维护主键顺序,适合频繁插入无事务的场景。

相比于B树,B+树的优势?

在innodb中,索引和数据的存储单位都是页,innodb中页大小为16K。对于主键索引,非叶子节点存储的是主键值+下层页的地址指针,叶子节点存储的是数据行。

  • 假设数据行大小为1K,叶子节点一页16K能存储16行数据记录;
  • 主键是bigint类型,8字节;页指针大小为6字节,非叶子节点一页能存储 16*1024/(8+6)字节=1170
  • 2层能存储的数据行大小为 1170 * 16= 18720
  • 3层能存储的数据行大小为 1170 * 1170 * 16 = 21902400 (2千万)

也就是说,3层的B+树能存储千万的数据,而层数相当于IO次数,B+树能有效减少IO次数。而且叶子节点使用双向链表,范围查询高效。

在 InnoDB 的表空间文件中,约定 page numbe r为 3 的代表主键索引的根页,而在根页偏移量为 64 的地方存放了该 B+ 树的 page level。

间隙锁解决啥问题?

间隙锁解决了可重复读事务隔离级别的幻读问题。如果只有行锁进行事务更新时锁定,如下:

假如只有 (id=2,age=‘1’) 这一行数据。
事务开始
1 select * from user where id > 1 and id < 4;
2 select * from user where id > 1 and id < 4;
事务结束

查询语句1返回了id=2这条数据,在执行语句2之前,别的事务进行了插入

insert into user (id, age) values(3, ‘3’);

语句1和2的执行结果不一致,出现了幻读。此时锁定id=2和 (1,2) 和(2,4)这个范围,让其他插入语句不能对此范围操作,避免事务执行前后不一致。

Sql调优

调优步骤:分析执行计划->优化索引->改写sql->参数调整
执行计划:

  • 全表扫描ALL需优化为 ref 或 range
  • rows预估扫描行数;
  • 额外操作:using filesort(文件排序)、using temporary(临时表)

排查思路:

  • 检查是否索引失效或者索引缺失
  • 驱动表选择不当多次回表
  • 索引使用函数或者隐式类型转化导致索引失效

优化思路:

  • 唯一性高的数据优先作为索引;
  • 索引覆盖:索引包含查询字段,减少回表;
  • 索引下推:在索引中增加条件,减少回表次数;

SQL优化:

  • 避免使用select *,减少内存和网络开销;
  • 分页优化,增加定位起始id,避免深分页;
  • 减少数据扫描:在join前用条件减少数据量;

架构优化:

  • 读写分离减少主库压力;
  • 增加缓存减少数据库访问频率;

监控手段:

  • 启用慢查询日志;
  • 实时监控数据库QPS和连接数等指标;

执行计划

执行计划中包含的字段:

  • rows(扫描行数):用来判断是否全表扫描或者扫描行数过多;
  • possible keys:可能命中的索引
  • type:如何查找表数据,一般优化到range到ref就可以,枚举如下:

system:查询系统表,表中仅有一行数据,比如查询information_schema 等系统表。
const:通过主键或唯一索引精确匹配单行。
eq_ref:多表关联时,被驱动表通过主键/唯一索引等值匹配。
ref:非唯一索引等值匹配,可能返回多行。
ref_or_null:类似 ref,但包含 NULL 值过滤。
fulltext:全文索引检索。
index_merge:合并多个索引的结果(OR 条件优化),减少回表次数。
unique_subquery:子查询返回唯一值(主键/唯一索引),等价于 eq_ref。
index_subquery:子查询返回非唯一索引值。
range:索引范围扫描(BETWEEN、IN、LIKE ‘xxx%’)。
index:全索引扫描(扫描整个二级索引),若需回表则退化为 ALL。
all:全表扫描(逐行检查),无索引的 WHERE 条件。
null:表示不会访问到表数据,从索引中就可以获取所需数据。如查询主键索引的主键字段。

  • key:sql执行中真正用到的索引
  • ref:查询执行时,通过哪些列或常量与索引进行匹配​​。

​​核心价值​​:ref 字段帮助开发者理解查询如何利用索引,识别低效的索引使用场景(如函数、未命中索引)。
​​优化方向​​:
确保 ref 显示为列名或常量(而非 NULL)。
多表连接时,检查 ref 是否包含关联字段。
避免在索引列使用函数或隐式类型转换。

可能的取值为:
const:等值查询使用主键或唯一索引的常量值。如select * from user where id=1;仅匹配单行,效率最高。
列名(column)​:非唯一索引的等值查询或者范围查询。
多列(col1,col2):复合索引的部分列匹配。
函数或表达式:索引列参与函数计算(可能导致索引失效)。
NULL:未使用索引条件(如全表扫描或未命中索引的查询)。

ref 与 key 的区别:
key:实际使用的索引名称,如idx_age;
ref:索引匹配的具体列或常量,如age、const。

  • extra:sql执行过程中额外的细节,常见的情况如下:

需要优化的情况:

Using filesort​:使用了文件排序;比如sql为:select * from user where created_at > ‘2024-01-01 00:00:00’ order by created_at, age; 但是created_at上有索引,而age上没有,此时如果过滤后的数据大小超过了sort_buffer_size,就会创建一个临时文件进行排序。如果没有超过sort_buffer_size,则会进行内存排序。需要注意的是,这个参数是每个连接独享的,设置得过大可能会浪费内存资源。

​​Using temporary​:需要创建临时表存储中间结果,常见于GROUP BY/DISTINCT/JOIN。优化方案:减少查询不必要的字段;调大临时表内存参数;强制直接使用磁盘临时表(省掉内存临时表转换为磁盘临时表的过程);

Using join buffer​:连接操作使用缓存(通常因关联字段无索引),大表关联时未命中索引。

积极提示:

Using index​:覆盖索引(查询字段全在索引中,无需回表)。
Using index condition (ICP)​:索引条件下推(MySQL 5.6+),部分条件在存储引擎层过滤,WHERE 条件包含索引列的非等值过滤。
Using where​:存储引擎返回数据后,MySQL 需回表过滤(可能涉及回表操作)。索引未完全覆盖 WHERE 条件。
Select tables optimized away​:优化器跳过表扫描(如 COUNT(1) 直接通过索引统计)。比如:SELECT COUNT(id) FROM orders;(id 为主键)
Impossible WHERE​:WHERE 条件永远不成立(如 WHERE 1=0),直接返回不查询。
Distinct​:MySQL 自动去重(优化 DISTINCT 查询)。

数据库和缓存一致性

todo 待补充

缓存击穿如何解决

查询数据库中没有的数据,加布隆过滤器,提高误判率可以增加位图大小,也可以修改hash函数减少hash冲突。

Redis持久化策略

AOF:
RDB:
AOF+RDB:

Redis删除了一个key在物理上删除了吗,用什么方式解决删除的key访问不到

Redis的io 模型

Kafkaack机制有哪几种情况

什么样的副本能进去isr

如何增加消费速度

Rebalance会重新分配分片中的数据吗


网站公告

今日签到

点亮在社区的每一天
去签到