面试系列|蚂蚁金服技术面【2】

ops/2025/3/16 19:38:35/

今天继续分享一下蚂蚁金服的 Java 后端开发岗位真实社招面经,复盘面试过程中踩过的坑,整理面试过程中提到的知识点,希望能给正在准备面试的你一些参考和启发,希望对你有帮助,愿你能够获得心仪的 offer !
在这里插入图片描述
第一轮面试完成后的第二天收到电话通知简历面过了,是另外一位面试官打的,通知进行下一轮面试。还是约的是晚上 8 点,不过这次的面试官应该是在忙事情,通过电话沟通,应该还在加班,大概推迟了半个小时,这一次是视频远程面试,需要开摄像头,并且有笔试环节,下面是面试时语音实录复盘。

面试首先简单自我介绍一下。

候选者:好的,balabala…(按照提前准备的进行答复)。


面试讲一下自己现在所负责的项目。

候选者:好的,balabala…(按照提前准备的进行答复)。


面试说一下你负责这个项目模块的架构设计及原因?

候选者:嗯,自己负责的这个项目的架构设计主要考虑以下几个方面。

候选者:首先考虑微服务架构,各模块职责单一、独立部署、独立扩容。

候选者:其次考虑高可用性 用户登录状态和数据存储在 Redis 中。这样服务可以在任意节点处理请求实现负载均衡。通过 Nginx 进行负载均衡,并集成 Sentinel 做熔断降级,保证服务在高峰期稳定运行。

候选者:还考虑了可扩展性,支持横向扩容, 服务节点可以动态增加或减少,并通过 Nacos + Spring Cloud Gateway 实现自动注册与发现,从而支持弹性伸缩。


面试你有没有处理过 CPU 高和 内存 高的问题,如何排查的?

候选者:有遇到过,首先要排查定位到具体原因。CPU 高的排查方法可以使用 top 命令检查占用 CPU 较高的进程,再使用 jstack 查看线程堆栈,分析是否有死循环或锁竞争内存高排查方法可以使用 jmap 分析内存快照,查找内存泄漏。


面试官: 如何解决项目中锁竞争比较频繁的情况?

候选者: 嗯…(思考中)有的,主要是通过几个方式应对。

候选者: 使用 读写锁(如 ReentrantReadWriteLock)降低写锁的竞争;使用 分段锁(如 ConcurrentHashMap);使用 CAS 操作(如 AtomicInteger, AtomicReference 等);缩小锁的粒度,避免锁住大块代码。


面试官: 就项目中遇到过什么比较有挑战性的问题,说说如何分析与解决?

候选者: 第一个挑战是项目中遇到的高并发环境下的性能瓶颈分析与优化,通过查看系统的资源消耗情况(CPU 内存 、磁盘 IO 、网络等)定位到具体的性能瓶颈,分析数据库、缓存、 消息队列等是否是瓶颈。查看是否有锁竞争、 死锁等问题。进行缓存优化、数据库优化、SQL查询优化、异步处理、线程池调优等操作提升性能。持续监控确保优化操作后避免新的瓶颈再次出现。

候选者: 第二个挑战是系统的高可用性 与系统容灾设计,系统在遭遇数据中心故障时,如何确保高可用性。主要考虑进行多数据中心部署:分析当前系统是否仅部署在单一数据中心,是否存在单点故障问题。负载均衡与流量切换:确认流量切换策略是否合理,是否能在发生故障时迅速切换到备用数据中心。备份与恢复:检查数据的备份策略是否能满足灾难恢复的要求,尤其是实时备份和快速恢复。


面试官: 死锁问题的分析与具体解决办法(具体排查思路与实践过程)?

候选者: 排查步骤可以使用 jstack 检查线程堆栈,分析死锁状态,分析日志,找到涉及的锁对象,使用死锁检测工具,如 Arthas 进行排查。发现死锁分析解决办法,可以通过避免嵌套锁,使用 tryLock 尝试获取锁,避免阻塞。


面试官:解释一下 MySQL 中的幻读?

候选者:(八股文来了,这题我熟)幻读指的是在同一事务内,多次执行相同查询,结果集却发生了变化,比如事务 A 先查询 WHERE age > 18,事务 B 插入一条 age = 20 的数据,事务 A 再次查询时,结果发生了变化。这种现象通常出现在 REPEATABLE READ 隔离级别下。

面试官:那么幻读问题如何解决?

候选者: (开始继续追问,稳住)MySQL 主要通过 间隙锁(Gap Lock) 解决幻读问题,它会锁住查询范围内的间隙,防止其他事务插入新数据。例如 SELECT … FOR UPDATE 在可重复读级别下会锁住查询范围,避免新数据插入导致幻读。此外,升级到 Serializable 隔离级别 也能彻底避免幻读,但代价较高,会影响并发性能。

面试官:你提到间隙锁,那么说一下间隙锁死锁原因与排查思路,如何预防?

候选者: 嗯…(三连问,GG,要思考一下,当时没有答好)首先形成死锁的情况主要有 (1)事务锁定范围重叠,相互等待。(2)索引未命中,触发不必要的间隙锁。(3)并发插入,多个事务尝试插入相同区间数据。
候选者: 排查思路:可以通过 SHOW ENGINE INNODB STATUS\G 查死锁详情。以及 SHOW PROCESSLIST 查看等待锁的事务。
候选者: 可以使用唯一索引,减少间隙锁。避免大范围 FOR UPDATE,改用主键锁定。降低隔离级别(如 READ COMMITTED)。固定事务顺序,避免交叉锁。


面试官:好的,我们继续, redolog 日志在磁盘上的存储方式?落盘的策略有哪些?

候选者: 存储方式是通过 Redo Log 循环写的固定大小日志文件;落盘策略是 innodb_flush_log_at_trx_commit 控制落盘频率参数:0: 每秒刷新到磁盘、1: 每次事务提交时刷新 2: 每次提交时写入系统缓存,每秒刷新到磁盘。


面试官: RabbitMQ的镜像集群与普通集群有什么区别,如何保证高可用,消息的持久化机制?

候选者: 嗯…(当时不知道,思考片段后还是直说不知道)这个自己不熟悉。(下来看了下复盘知识点镜像集群所有节点都存储完整的队列,避免单点故障,缺点: 性能下降,带来更高的同步开销;普通集群: 只有主节点存储队列数据:高可用: 使用 Quorum Queues 或者 镜像队列策略 )。


面试官: ThreadLocal 原理,以及在线程池中使用需要注意什么问题,或者说有没有遇到 ThreadLocal 的坑?

候选者: ThreadLocal 原理为每个线程单独存储变量,避免线程间数据共享。线程池中的问题主要是线程复用导致 ThreadLocal 数据未清理,可能引起内存泄漏。可以使用 ThreadLocal.remove() 手动清理;还有一个问题是ThreadLocal无法跨线程传递变量,这个时候可以使用阿里的 TransmittableThreadLocal (TTL) 来传递变量。


面试官:下面我们做两道题,可以先说一下你的思路

1、算法题:最靠近目标数的和

题目描述: 给定一个整数数组 nums 和一个目标值 target,请从数组中找到三个整数,使得它们的和最接近 target,并返回这个和。

候选者: 思路:排序 + 双指针: 1)先对数组进行排序。2)固定一个数 nums[i],使用双指针 leftright 查找最接近 target 的两个数

面试官:说一下时间复杂度和空间复杂度

候选者: 时间复杂度: O(n^2)空间复杂度: O(1)

public int threeSumClosest(int[] nums, int target) {Arrays.sort(nums);int closestSum = Integer.MAX_VALUE;for (int i = 0; i < nums.length - 2; i++) {int left = i + 1, right = nums.length - 1;while (left < right) {int sum = nums[i] + nums[left] + nums[right];if (Math.abs(target - sum) < Math.abs(target - closestSum)) {closestSum = sum;}if (sum < target) {left++;} else {right--;}}}return closestSum;
}

2、考察多线程的熟悉程度:有两个线程,一个打印奇数,一个打印偶数,调度两个线程,升序打印1到100的数字

public class PrintOddEven {private static final Object lock = new Object();private static int count = 1;private static final int MAX = 100;public static void main(String[] args) {Thread oddThread = new Thread(() -> {while (count <= MAX) {synchronized (lock) {// 判断是否是奇数if (count % 2 == 1) {System.out.println(Thread.currentThread().getName() + " : " + count);count++;// 唤醒偶数线程lock.notify();} else {try {// 等待偶数线程打印lock.wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}}}, "奇数线程");Thread evenThread = new Thread(() -> {while (count <= MAX) {synchronized (lock) {// 判断是否是偶数if (count % 2 == 0) {System.out.println(Thread.currentThread().getName() + " : " + count);count++;// 唤醒奇数线程lock.notify();} else {try {// 等待奇数线程打印lock.wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}}}, "偶数线程");oddThread.start();evenThread.start();}
}

面试官:还有没有其他写法?
候选者:还有可以通过信号量 Semaphore 来进行线程之间的协作。

import java.util.concurrent.Semaphore;public class PrintOddEvenWithSemaphore {private static final int MAX = 100;private static final Semaphore semaphore = new Semaphore(1);private static int count = 1;public static void main(String[] args) {Thread oddThread = new Thread(() -> {while (count <= MAX) {try {// 奇数线程等待信号量semaphore.acquire();// 判断当前是否是奇数if (count % 2 == 1 && count <= MAX) {System.out.println(Thread.currentThread().getName() + " : " + count);count++;}} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {// 释放信号量,唤醒偶数线程semaphore.release();}}}, "奇数线程");Thread evenThread = new Thread(() -> {while (count <= MAX) {try {// 偶数线程等待信号量semaphore.acquire();// 判断当前是否是偶数if (count % 2 == 0 && count <= MAX) {System.out.println(Thread.currentThread().getName() + " : " + count);count++;}} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {// 释放信号量,唤醒奇数线程semaphore.release();}}}, "偶数线程");oddThread.start();evenThread.start();}
}

面试官:那么还有没有其他的?

其实这里还有写法是通过 Condition 来做,当时没有想到,这道题还是比较经典,是面试官常考的一道题。

面试官:还有没有想问我的?
还是照例问了技术栈和团队的主要方向是什么。

面试官: 后续有结果会邮件通知你这边,感谢你参与今天的面试


第二轮面试大概持续将近有一个小时,由于面试官迟到了一会,面试流程完成后他还主动聊了一会,当然第二轮面试完成后还是照样等通知。

📢 如果对你有帮助的话,还请帮忙点赞 + 收藏!!!(谢谢!!!)


http://www.ppmy.cn/ops/166295.html

相关文章

Liunx启动kafka并解决kafka时不时挂掉的问题

kafka启动步骤 先启动zookeeper&#xff0c;启动命令如下 nohup ./zookeeper-server-start.sh /home/kafka/kafka/config/zookeeper.properties > /home/kafka/kafka/zookeeper.log 2>&1 &再启动kafka&#xff0c;启动命令如下 nohup ./kafka-server-start.sh…

redis部署架构

一、redis多实例部署 实例1 安装目录&#xff1a;/app/6380 数据目录&#xff1a;/app/6380/data 实例2 安装目录&#xff1a;/app/6381 数据目录&#xff1a;/app/6381/data 1、创建实例安装目录 2、拷贝实例的配置文件 3、编辑实例的配置文件 第…

自定义tiptap插件

本文为开发开源项目的真实开发经历&#xff0c;感兴趣的可以来给我的项目点个star&#xff0c;谢谢啦~ 具体博文介绍&#xff1a; 开源&#xff5c;Documind协同文档&#xff08;接入deepseek-r1、支持实时聊天&#xff09;Documind &#x1f680; 一个支持实时聊天和接入 - 掘…

华为欧拉操作系统安装Docker服务

华为欧拉 20.03 操作系统安装 Docker 服务 一、安装前准备 系统环境检查 确认当前运行的操作系统为华为欧拉 24.03。可通过在终端执行以下命令查看&#xff1a; cat /etc/os - release欧拉系统可以使用以下命令&#xff1a; cat /etc/openEuler-release确保系统已连接互联…

如何在AVL树中高效插入并保持平衡:一步步掌握旋转与平衡因子 —— 平衡因子以及AVL结构篇

文章目录 AVL树的概念AVL树的结构AVL树的插入平衡因子更新终止条件插入以及平衡因子的保持AVL树的查找 AVL树的概念 AVL树&#xff08;Adelson-Velsky and Landis Tree&#xff09;是一种自平衡二叉查找树&#xff0c;它的特点是每个节点的左子树和右子树的高度差不能超过1。这…

Spring、Spring Boot、Spring Cloud 的区别与联系

1. Spring 框架 定位&#xff1a;轻量级的企业级应用开发框架&#xff0c;核心是 IoC&#xff08;控制反转&#xff09; 和 AOP&#xff08;面向切面编程&#xff09;。 核心功能&#xff1a; 依赖注入&#xff08;DI&#xff09;&#xff1a;通过 Autowired、Component 等注解…

STM32——GPIO介绍

GPIO(General-Purpose IO ports,通用输入/输出接口)模块是STM32的外设接口的核心部分,用于感知外界信号(输入模式)和控制外部设备(输出模式),支持多种工作模式和配置选项。 1、GPIO 基本结构 STM32F407 的每个 GPIO 引脚均可独立配置,主要特性包括: 9 组 GPIO 端口…

MyBatis一对多查询方式

在 MyBatis 中&#xff0c;一对多查询是指一个实体对象&#xff08;如 Order&#xff09;关联多个子对象&#xff08;如 OrderItem&#xff09;。这种关系在数据库中通常通过外键实现&#xff0c;而在 MyBatis 中可以通过 resultMap 的嵌套集合&#xff08;<collection>&…