高德 面经
一面
Java 基础 & 核心
- 你觉得用的比较熟练的技术栈/基础中间件有哪些?(除了 Java 和 Spring/Spring Cloud Alibaba)还用到了其他的中间件吗?消息队列是 Kafka 吗?
- Java 的多态是怎么实现的?(底层原理方面)
- Java 里面的泛型是什么?
- 类型擦除是个什么样的机制?怎么理解这个东西?
- (泛型擦除后)声明一个 List<Integer>,编译完之后可以往里面放 String 类型吗?为什么不能放?是谁控制的?
- 用过 Java 里面的反射没?
- 反射有几个基本的类是什么?(面试官提示“三驾马车”,但候选人不清楚这个说法,后续追问具体类)
- 我们可以怎么获得那个 Class 实例?(class.forName之外还有吗?)
- 类名.class 是啥意思?
- 你了解过哪些场景比较适合用反射吗?
- AOP 的两种实现方式(JDK 和 CGLib)了解吗?它们有什么区别?
- (提到 Byte Body)它基于是怎么实现的?那 CGLib 不也是基于字节码吗?为什么重新写一个 Byte Body?它在哪方面优化会变得更好?
Java 并发 & 线程池
- Java 里面线程池创建的时候有几个基本的参数?都有哪些?
- 什么时候拒绝策略会生效?
- (针对候选人实践)为什么你们要把核心线程数和最大线程数设置成相等?是怕影响什么?(不让扩容的原因)
- (针对候选人实践)你们(核心=最大)不销毁线程是吗?最大的(线程数)会有多大?
- (针对候选人实践)你们是 CPU 密集型?没有 IO 密集型?(查 RDB 也算 IO)
- (针对候选人实践)你们没有一点复杂点的场景吗?(暗示业务简单)
- 假设(需要)处理业务(IO密集型),你还会这么配(核心=最大)吗?
- 如果有 IO 密集型,核心和最大不一样,那你的拒绝策略什么时候生效呢?
- (举例:核心4,最大9)来第五个任务的时候会怎么办?
- 我想去实时的监控这个线程池里面有多少处于活动的线程,可以怎么做?
- (如果让你实现动态线程池/监控)你有什么思路吗?
- 线程池里面他怎么记录有多少个线程的,你知道吗?(Worker 类相关)
JVM
- JVM 的运行时数据区域有哪些?
- 堆里面存什么东西?
- 那个虚拟机栈(虚拟基站)里面会存什么?
- (栈执行流程)当执行完 C 方法的时候,我怎么能找到 B 呢?
- 你们项目在发布运行过程中用的都是什么垃圾回收算法?(G1 还是 CMS)
- (如果用 CMS)为什么不统一用 G1?(追问 CMS 的问题,如参数调优复杂、STW)
- G1 和 CMS 相比有什么优势?(可控的停顿时长)
- G1 能保证那个(最大回收)时长固定吗?
Spring & Spring Boot
- Spring Boot 解决了什么问题?(区别于 Spring Framework)
- Spring 的 Bean 的生命周期有什么?(从产生到销毁有哪些阶段)
数据库 (MySQL)
- MySQL 支持事务吗?
- 事务的 4 大特性(ACID)是什么?
- 事务隔离级别有哪些?
- 幻读是个什么现象?
- 刚才提到的那几种隔离级别里面哪些会有幻读,哪些没有幻读?
- SQL 里面的主从复制那个机制是什么样子的?
- 为什么(主从复制)要让从库去向主库请求(拉模式),而不是主库向从库去做广播(推模式)?你觉得哪种会比较好一点?
- (如果用 MQ 类中间件转发 binlog)这种方式有什么问题?(如顺序性、数据丢失、实时性、主库无法感知同步状态等)
缓存 (Redis)
- Redis 有哪些数据类型?
- 我想要实现一个可以按照时间范围来查找订单的结构,用 Redis 里面怎么来做?
- (用 Sorted Set 实现按时间范围查找)只能用这种吗?List 可以吗?
- (如果用 List)一个 Key 会产生大 Key 问题,(如果不用 List)最好还是用 Sorted Set 会好点?
- 你用 Sorted Set 的话,它的查询的复杂度是啥?(LogN 还是 NLogN 或 M+LogN)
算法 & 编程题
- 做一个支持权重的负载均衡的算法。(提供代码框架,要求实现 getHost 方法)
- (针对代码实现)来讲一下你的思路。
- (针对代码实现)第 49 行,这里小于等于可以吗?为什么取(随机数时)左闭右开区间?(追问边界条件和小数精度问题)
二面
- 关于登录态 token 校验模块:你能大概介绍一下你具体你们是怎么做的吗?怎么保证它的这个高可用?
- 既然有了本地可以来做(token)解密校验的话,还需要 Redis 吗?
- 多端互踢是为了(什么)?为什么要有一个这样的机制?
- 为什么不能让他(用户)多个渠道能同时登录?
- 关于二级缓存(本地 Caffeine + Redis):这个具体是怎么做的?(第一层基于 ID,第二层具体实现)
- 你们这个活动(查询)的 QPS 大概有多高?
- 什么时候会查这个(活动)?它是什么场景触发的查询?
- 货拉拉的下单(场景)有 7 万的 QPS 吗?(对候选人提供数据的确认/质疑)
- 本地缓存存的是什么东西?
- 订单 ID 跟活动 ID 的关联关系也在本地缓存里存了吗?
- Redis 里面也是存的同样的结构是吧?
- 你们有多少台机器?本地缓存的命中率呢?
- (司机看单)每次都会查(活动)吗?你们的上游(调用方)不会做缓存吗?
- 一个订单下面有那么多活动 ID,然后每个司机看到命中的活动还(会)不一样吗?
- (针对缓存优化)用 get + 本地(缓存)代替 mget:为什么要做这个事情?
- 你觉得这个(get 代替 mget)有做优化吗?这个替换本身是合理的吗?
- (用 get 查询缺失 key)是串行的还是并行的?
- 那(如果 get 是)并行的,跟 mget(相比),那为什么不用 mget 呢?
- 你们这个接口 RT 减了 200 毫秒,是收益是从哪里来的?
- 你觉得它主要的收益点是(因为)你们的哪个优化动作(降低了 200 毫秒)?
技术方法论 & 问题排查
- 当你接到一个新任务,或者接触一个新的模块/系统时,你是怎么来着手做这个工作的?(可以结合活动模块来说)
- (针对服务治理任务)你梳理的那个系统,你觉得有啥问题吗?
- 你梳理超时时间,有总结出什么经验来?你觉得超时时间应该怎么配合适吗?
- (默认超时时间)500 毫秒怎么来的?
- 你觉得这个(500 毫秒超时)合理吗?
基础知识 & 对比
- 你们内部的交互是用的 RPC 是吧?能大概讲一下 RPC 跟 HTTP 的差别吗?