分页题目
后端开发工程师相关题目第 2 页
分布式锁代码逻辑里如果发生异常 catch 的时候需要做什么?
分布式锁保护的业务逻辑发生异常时,catch 的重点不是立刻解锁,而是让失败可见、记录足够上下文、决定补偿或重试。锁释放应统一放在 finally,并在释放前确认当前请求仍然持有锁,避免锁泄漏、误删他人锁和异常被吞导致的数据不一致。
MySQL 底层数据结构?
MySQL 底层数据结构在 InnoDB 中主要围绕“页、B+树索引、聚簇索引、二级索引、Buffer Pool、事务日志”展开。真正决定查询性能的不是某一个抽象结构,而是这些结构如何协同:数据按页组织,索引以 B+树维护有序访问路径,主键索引叶子节点保存完整行记录,二级索引叶子节点保存主键值,内存中的 Buffer Pool 缓存热点页,变更再通过 redo log、undo log 等机制保证事务与崩溃恢复。理解这些内容,才能解释为什么 MySQL 不直接使用普通二叉树、红黑树或单纯哈希表作为主要索引结构。
mysql慢查询优化方案?
这道题考察的不是背几个索引原则,而是候选人能否把“发现慢查询、判断瓶颈、制定优化方案、验证效果、防止回退”串成闭环。优秀回答应覆盖慢查询日志与监控定位、EXPLAIN 执行计划分析、索引设计、SQL 改写、表结构与数据规模治理、分页与排序优化、锁等待排查、缓存与业务链路优化,以及上线后的持续观测。
内存资源很宝贵,为什么不能直接访问数据库表?
不能直接访问数据库表的原因是,表不是应用进程里可随意读取的一块内存数组,而是数据库引擎管理的持久化数据结构。应用需要通过 SQL、连接、权限、索引、事务和数据库协议访问数据;数据库内部再决定从磁盘、Buffer Pool、索引页或缓存中读取哪些页。绕过数据库引擎或把全表搬到内存,会破坏一致性、并发控制、恢复能力、安全边界和资源隔离。
InnoDB 和 MyISAM 区别?
InnoDB 和 MyISAM 的核心区别不是简单的谁快谁慢,而是存储引擎目标不同。InnoDB 面向事务一致性、崩溃恢复和高并发 OLTP,支持事务、行级锁、MVCC、外键、聚簇索引和可靠恢复;MyISAM 是早期非事务引擎,主要使用表级锁,不支持事务和外键,恢复能力弱,适合范围非常有限。
后端通过什么连接到数据库?
后端连接数据库的核心链路通常是:业务代码通过 ORM 或数据访问框架发起数据库操作,框架从连接池拿到连接,连接池底层使用数据库驱动,驱动按照数据库协议与数据库实例、代理或中间件建立 TCP 连接,并完成认证、参数协商、SQL 发送、结果解析、事务控制和连接复用。以 Java 后端连接 MySQL 为例,常见链路是 Service/DAO -> MyBatis/JPA/JdbcTemplate -> DataSource/HikariCP/Druid -> JDBC Driver/MySQL Connector/J -> MySQL 协议 -> MySQL Server 或数据库代理。
MySQL事务的四种特性,分别解释?
MySQL 事务的四种特性是 ACID:原子性、一致性、隔离性、持久性。在 InnoDB 中,原子性主要依赖 undo log 回滚;隔离性依赖 MVCC、ReadView 和锁;持久性主要依赖 redo log 及刷盘机制;一致性不是某一个日志单独保证的,而是由数据库约束、事务语义、隔离控制、崩溃恢复和应用正确性共同保证。
索引下推是什么?
索引下推(Index Condition Pushdown,ICP)是 MySQL 优化器把部分原本由 server 层判断的 WHERE 条件,下推到存储引擎层,在扫描二级索引时先利用索引记录中的列做过滤,再决定是否回表读取完整行。它的核心价值不是减少索引扫描本身,而是减少无效回表次数,尤其适合联合索引中部分条件不能继续用于定位范围、但仍包含在索引列里的场景。
MySQL B+ 树索引的实现
这题考察 InnoDB 如何用页式 B+ 树降低磁盘 I/O,并把等值查询、范围扫描、聚簇索引、二级索引和回表串成一条完整链路。
同题还出现在 2 个公司岗位
Spring 事务失效有哪些常见场景?
Spring 事务失效不要只背 @Transactional 场景清单,核心要答出声明式事务的运行条件:方法调用必须进入 Spring AOP 代理,由 TransactionInterceptor 配合 TransactionManager 在调用前后开启、提交或回滚事务;常见失效本质上分为三类:没有经过代理、异常没有触发回滚、真实数据库资源没有加入同一个事务。
MySQL 事务隔离级别有哪些?
这题考察对 SQL 标准隔离级别和 MySQL InnoDB 实现差异的理解。面试中不能只背四个名字,还要说明每个级别解决哪些并发读问题、MySQL 默认为什么是可重复读,以及 InnoDB 通过 MVCC、快照读、当前读和 next-key lock 在不同读场景下处理一致性与幻读的边界。
分库分表如何设计?
分库分表不是先选中间件,而是先判断单库单表在容量、吞吐、可用性、隔离性上的瓶颈,再设计一套可路由、可扩容、可治理、可回滚的数据架构。好的回答要把垂直拆分、水平拆分、分片键、路由、全局 ID、事务、查询、扩容、热点、读写分离和灰度治理串成一个完整工程方案。
B 树和 B+ 树有什么区别?
B 树和 B+ 树都是面向磁盘页设计的多路平衡搜索树,核心差异不只是数据放在哪里,而是由此带来的扇出、树高、查询路径稳定性、范围扫描能力和索引工程实现差异。数据库索引更偏好 B+ 树,因为它能用更高扇出降低磁盘访问次数,并用叶子节点顺序结构支撑范围查询、排序、覆盖索引和顺序预读。
ArrayList 和 LinkedList 有什么区别?
ArrayList 和 LinkedList 都实现了 List 接口,但核心差异来自底层结构:ArrayList 基于可扩容数组,擅长随机访问、顺序遍历和末尾追加;LinkedList 基于双向链表,单个节点插入删除本身很快,但定位节点通常需要线性遍历。面试中不能只背数组查询快、链表增删快,还要结合容量扩容、内存占用、CPU 缓存、迭代器删除、fail-fast 和真实业务场景来回答。
一致性哈希的原理和使用场景是什么?
一致性哈希用于解决分布式分片在节点扩缩容时的数据大规模迁移问题。它把 key 和节点映射到同一个哈希环上,key 顺时针寻找第一个节点作为归属节点。相比普通取模,节点变化时只影响相邻区间,但工程上还要处理虚拟节点、热点、权重、复制和故障恢复。
常见设计模式有哪些,分别适合什么场景?
常见设计模式不适合只罗列名称,面试官更关注候选人是否理解模式背后的变化点、解耦方式和落地边界。高质量回答应按创建型、结构型、行为型展开,结合 Spring 和业务代码说明真实使用场景,同时明确模式不是越多越好,核心是让代码在扩展时少改动、在维护时更清晰。
Spring 和 Spring Boot 有什么区别?
Spring 是基础框架和生态体系,核心价值在于 IoC 容器、AOP、事务管理、MVC、数据访问等通用能力;Spring Boot 不是替代 Spring,而是在 Spring 之上提供约定优于配置的应用启动脚手架,通过自动配置、starter 依赖、内嵌服务器、外部化配置和运行监控,降低搭建与运维成本。
服务端限流常见方案有哪些?
服务端限流的核心不是单纯拒绝请求,而是在系统容量有限时,把入口流量、服务调用、关键资源和热点参数控制在可承受范围内,优先保护核心链路稳定性。面试回答应从限流位置、算法模型、分布式实现、限流 key、被限流后的处理、与熔断降级的区别、监控和误伤治理几条线展开。
ConcurrentHashMap为什么性能比较好?
ConcurrentHashMap 性能好,本质上不是因为完全没有锁,而是把锁的范围、锁的频率和锁竞争都压到了更低水平。它通过读操作无锁、写操作尽量 CAS、冲突时只锁单个桶、扩容时多线程协作迁移、计数时分散热点等方式,避免了 Hashtable 或直接给 HashMap 加 synchronized 那种全表串行化的瓶颈。回答时要区分 JDK7 的 Segment 分段锁模型和 JDK8 的 Node 数组加 CAS、synchronized 桶级锁模型。
Java 动态代理的实现原理是什么?
Java 动态代理本质上是在运行期生成一个实现目标接口的代理类,把接口方法调用统一转发给 InvocationHandler。面试回答不能只说“反射”或“运行期生成对象”,还要讲清 JDK 动态代理的接口约束、Proxy 生成代理类、方法调用链、Spring AOP 的代理选择,以及 final、private、自调用等失效边界。
Java三大特性 多态是怎么实现的?
Java 三大特性是封装、继承和多态。高质量回答不能只背三个词,而要说明它们分别解决对象状态保护、类型复用扩展、抽象行为分派的问题。多态的实现重点在方法重写、向上转型和动态绑定:编译期确认引用类型上是否存在可调用方法,运行期根据对象真实类型分派到具体实现。
HashMap 的底层实现原理是什么?
HashMap 的核心是用哈希表存储键值对,通过 key 的 hash 值定位数组桶,再在桶内处理哈希冲突。JDK 1.7 主要是数组加链表,链表采用头插法,扩容迁移时在并发场景下可能形成链表环;JDK 1.8 改为数组、链表、红黑树组合,链表采用尾插法,并在冲突严重时树化,把极端情况下的查找从线性复杂度优化到对数复杂度。
了解哪些不同 JDK 版本的新特性?
这道题考察的不是背版本号,而是能否把 JDK 演进和工程实践联系起来。回答时应先按主线概括:JDK 8 是现代 Java 的分水岭,引入 Lambda、Stream、Optional、默认方法和新的日期时间 API;JDK 9 到 10 开始模块化、集合工厂方法、JShell、接口私有方法和局部变量类型推断;JDK 11 作为常用长期支持版本,补齐 HTTP Client、字符串和文件 API、ZGC 初步可用等能力;JDK 17 是当前大量生产系统升级的关键长期支持版本,带来 sealed class、record、switch 表达式、文本块、模式匹配等语言能力,并强化 JVM、GC 和封装边界;JDK 21 进一步把虚拟线程、结构化并发、模式匹配 switch、record pattern、分代 ZGC 等特性推向成熟,重点提升高并发服务的线程模型和表达能力。
JAVA中的hashmap怎么实现的?
HashMap 的核心是用数组承载桶位,用链表或红黑树解决哈希冲突。回答这题时要把结构、hash 扰动、桶定位、put/get 流程、扩容机制、树化条件、equals 与 hashCode 契约,以及非线程安全风险串起来,重点说明为什么容量是 2 的幂、为什么扩容会重新分布元素,以及 JDK8 后为什么在冲突严重时引入红黑树。
JDK25 有些什么新特性?
JDK 25 的面试回答应先定位版本:它在 2025-09-16 GA,并且是多数发行版选择的 LTS 基线。然后要区分 final、preview、incubator、experimental 四类能力。生产升级重点看正式特性、运行时变化、诊断能力、安全 API 和兼容性变化,预览、孵化、实验能力更适合评估与提前适配。
HashMap 的扩容机制是什么?
HashMap 的扩容本质是当键值对数量超过 threshold 后创建更大的 table,并把旧桶中的节点迁移到新桶。JDK 8 利用容量始终为 2 的幂这一特性,通过 hash & oldCap 把同一桶内节点拆成低位组和高位组,避免重新完整寻址,也保持链表相对顺序。
Java 的多态是怎么实现的?
Java 多态的核心是:编译期看引用的静态类型决定能调用哪些成员、选择哪个方法签名;运行期看对象的实际类型决定执行哪个被重写的方法实现。它主要依赖方法重写、动态分派以及虚方法调用指令完成,字段、静态方法、私有方法和构造方法不按同样规则参与多态。
Java 类加载流程和双亲委派机制是什么?
这道题要回答清楚两层:第一是类从字节码进入 JVM 到可执行状态的生命周期,通常按加载、验证、准备、解析、初始化来讲,其中验证、准备、解析属于链接阶段;第二是类加载器如何查找类,也就是双亲委派模型。面试中不能只背阶段名称,还要说明每阶段做什么、初始化触发时机、类身份由类名和加载器共同决定,以及为什么工程框架有时会打破或绕开双亲委派。
java中重载和重写有什么区别,分别用什么关键字?
Java 中重载是同一个类或继承关系中方法名相同、参数列表不同,属于编译期静态分派;重写是子类重新实现父类或接口中可被覆盖的实例方法,属于运行期动态分派。二者都没有专门关键字,@Override 是注解不是关键字。
Java里抽象类和接口的区别是什么?
Java 中抽象类和接口的核心区别不只是语法,而是建模意图:抽象类用于表达“是什么”的继承关系和共享骨架,接口用于表达“能做什么”的能力契约。抽象类可以保存状态、定义构造器、复用模板流程;接口更适合定义跨层级、可多实现的规范,并通过 default、static、private 方法支持演进和少量公共逻辑。
熟悉Java的哪些框架?
这类问题不是让候选人背框架名称,而是考察你是否真正理解 Java 后端技术栈如何支撑业务系统。高质量回答应该从“核心开发框架、Web 请求链路、数据访问、微服务治理、RPC 通信、异步消息、缓存与性能、项目落地经验”几个层次展开,体现你不仅会用 Spring Boot 写接口,也理解框架背后的设计思想、运行机制、适用边界和工程实践。
怎么看待Java和Go的后端开发?
这道题考察的不是候选人是否偏爱 Java 或 Go,而是能否从后端工程的完整生命周期判断技术选型:语言生态、运行时模型、并发能力、性能与 GC、部署形态、可观测性、团队成熟度、业务适配和迁移风险。高质量回答应避免“Java 老、Go 快”这类简单结论,而是说明两者各自擅长的场景,以及在真实系统中如何做渐进式选型。
go和java的接口有什么不同?
Go 和 Java 的接口都用于抽象行为,但核心模型不同:Java 接口是名义类型系统的一部分,类需要显式声明实现关系;Go 接口是结构化类型系统的一部分,只要类型的方法集满足接口要求,就自动实现接口。这个差异会进一步影响方法匹配、接收者规则、空值语义、泛型约束、运行时派发方式以及工程设计风格。
synchronized底层实现的原理?
synchronized 是 JVM 级别的内置同步机制。它通过 monitorenter/monitorexit 或方法访问标志进入对象监视器,基于对象头 Mark Word 记录锁状态,并在不同竞争程度下使用轻量级锁、重量级锁等实现互斥。它支持可重入,退出同步块会建立 happens-before 关系,也与 wait/notify 的条件等待机制绑定。
volatile 的作用和底层原理是什么?
volatile 是 Java 并发里用于解决共享变量可见性和一定程度有序性的轻量级机制。它保证对 volatile 变量的写入对后续读取可见,并通过 JMM 规定的 happens-before 关系约束指令重排;但它不保证 i++、check-then-act 这类复合操作的原子性。
Java 线程池的核心参数和执行流程是什么?
这道题考察的不是背出几个构造参数,而是要说明 ThreadPoolExecutor 如何用线程数、队列、线程工厂和拒绝策略共同定义资源边界。高质量回答应先点明线程池复用线程、控制并发、削峰和保护系统的目的,再按任务提交后的执行路径解释:先看核心线程,再入队,再扩容到最大线程,最后触发拒绝策略,同时补充队列选择、参数取舍、异常处理、关闭流程和线上监控。
synchronized锁底层CS了解么?
synchronized 是 JVM 提供的内置互斥机制,核心不是简单的操作系统锁,而是围绕对象头 Mark Word、Monitor 监视器和字节码 monitorenter/monitorexit 协作完成。它支持可重入,具备明确的内存可见性语义,并会结合轻量级锁、CAS、重量级锁以及锁消除、锁粗化等优化来降低同步成本。
java中加锁的方式有哪些,怎么个写法?
Java 加锁常见方式包括 synchronized、ReentrantLock、ReadWriteLock、StampedLock,以及更轻量的原子类、并发容器、线程封闭等替代方案。面试回答不能只背 API,重点要说清楚锁住的对象、写法、释放方式、适用场景、风险和性能取舍。
java中的锁有哪些?
Java 中的锁不能只回答 synchronized 和 ReentrantLock,而要按实现机制、语义特征、等待方式、读写模型和 JVM 优化层级来拆解。面试时应从对象监视器、AQS 显式锁、读写锁、StampedLock、CAS 原子类、LockSupport 与 Condition 这些核心工具出发,再说明乐观/悲观、公平/非公平、可重入/不可重入、自旋/阻塞等分类维度,并结合适用场景、性能取舍和常见陷阱给出判断依据。
JVM 垃圾回收机制是什么?
JVM 垃圾回收机制的核心,是 JVM 自动识别已经不可达的对象并回收其占用的内存,从而降低手动释放内存的负担。面试回答要先明确:GC 主要发生在 Java 堆,尤其是新生代;同时也要补充方法区或元空间在类卸载、常量废弃时也可能被回收,但虚拟机栈、本地方法栈和程序计数器通常随线程或栈帧生命周期自动释放,不是 GC 的主要战场。
JVM中的【堆】是用什么数据结构来实现的?
JVM 中的堆不是二叉堆、最大堆、最小堆这种数据结构,而是 JVM 运行时用于存放对象实例和数组的一块共享内存区域。它的具体组织方式取决于垃圾收集器:可能按年轻代、老年代划分,也可能按 Region 管理;对象分配通常依赖 TLAB、指针碰撞、空闲列表等机制,而对象回收依赖可达性分析和 GC 元数据。
JVM 运行时内存区域如何划分?
JVM 运行时内存区域可以按线程私有和线程共享来划分:程序计数器、虚拟机栈、本地方法栈属于线程私有;堆和方法区属于线程共享。面试回答不能只背名称,还要说明每块区域存什么、生命周期如何、会抛什么错误、和垃圾回收的关系,以及 JDK 8 以后永久代被元空间替代这一常见边界。
JVM 如何判断对象可以被回收,分代收集如何工作?
这道题核心不是背垃圾收集器名称,而是说明 JVM 如何从“对象是否还可被程序使用”推导出“是否可回收”,再解释为什么堆会按年轻代和老年代组织。回答时要把可达性分析、GC Roots、引用强度、finalize 的特殊边界,以及 Minor GC、Major GC、Full GC、对象晋升和跨代引用处理串成一条完整链路。
设计一个线程安全的HashMap?
设计线程安全的 HashMap,核心不是简单给每个方法加 synchronized,而是先明确一致性、吞吐量、内存、迭代语义等需求边界,再选择合适的锁粒度和扩容协调方案。一个可落地的设计通常会从桶级锁或分段锁出发,保证单个 key 的 put、get、remove 线性化,同时通过安全发布、volatile、CAS、锁顺序和 resize 协议避免数据丢失、死锁、读到半迁移结构等问题;如果追求工业级性能和复杂场景,通常应优先使用 ConcurrentHashMap,而不是自行实现。
ConcurrentHashMap 为什么能保证线程安全?
ConcurrentHashMap 的线程安全不是靠一个全局大锁实现的,而是把可见性、原子性和局部互斥组合起来:数组槽位和节点关键字段用 volatile 保证可见性,空桶插入、初始化和扩容状态切换用 CAS 保证原子更新,非空桶写入时只锁住单个桶的头节点,读操作基本无锁;再配合扩容协作、红黑树化和分散计数,既保证并发访问下结构不被破坏,又尽量降低锁竞争。
Java 实现线程安全的方式?
线程安全的核心不是某个关键字,而是多个线程访问共享可变状态时,程序仍能保持正确性。回答时应先界定共享、可变、并发访问这三个条件,再按避免共享、限制共享、控制访问、使用并发工具和改进设计几个层次展开。
java中有哪些以队列、链表为底层实现的数据结构?
Java 里要区分“队列接口”和“链表底层”。Queue、Deque 是行为抽象,表示先进先出、双端队列或优先级访问;LinkedList、ConcurrentLinkedQueue、LinkedBlockingQueue 这类才是链式节点结构。ArrayDeque、ArrayBlockingQueue、PriorityQueue 虽然暴露队列接口,但底层分别是循环数组、有界数组和二叉堆数组,不是链表。LinkedHashMap 则是哈希表加双向链表,用链表维护插入顺序或访问顺序,但它本身不实现 Queue。
怎么保证map的线程安全?
保证 Map 线程安全的核心是先明确并发语义:是只要单次 get/put 安全,还是复合操作也要原子;是允许弱一致迭代,还是必须看到稳定快照;是读多写少、写多读少,还是配置类读多且整体替换。常见方案包括外部加锁、Collections.synchronizedMap、ConcurrentHashMap、不可变 Map、读写锁和快照/COW。面试中不能只说“用 ConcurrentHashMap”,还要说明它解决了什么、不解决什么,以及复合操作、迭代一致性、内存可见性和选型边界。