阿里国际 AI 应用研发 二面+HR面(暑期)
1. 数据库索引的作用及实现原理是什么?
答案:数据库索引的作用是减少扫描数据量,把全表扫描变成按索引快速定位。没有索引时,数据库可能要逐行判断条件;有合适索引时,可以通过树结构快速定位到目标行或目标范围。
MySQL InnoDB 常用 B+ 树索引。B+ 树的非叶子节点只存 key 和指针,叶子节点存真实数据或主键值,叶子节点之间还有链表,所以既适合等值查询,也适合范围查询、排序和分页。Hash 索引适合等值查询,但不适合范围查询和排序,所以通用性不如 B+ 树。
CREATE INDEX idx_order_user_time ON order_info(user_id, created_at); EXPLAIN SELECT order_id, status, amount FROM order_info WHERE user_id = 10001 AND created_at >= '2026-01-01' ORDER BY created_at DESC LIMIT 20;
2. 事务的特性与隔离级别有哪些?
答案:事务的 ACID 包括原子性、一致性、隔离性和持久性。原子性表示事务内操作要么全部成功,要么全部失败;一致性表示事务前后数据满足业务约束;隔离性表示并发事务之间互不干扰;持久性表示提交后的数据即使宕机也不能丢失。
隔离级别包括读未提交、读已提交、可重复读和串行化。隔离级别越高,并发异常越少,但性能成本越高。MySQL InnoDB 默认是可重复读,通过 MVCC 解决一致性读问题,通过锁机制处理当前读和写冲突。
Read Uncommitted:可能脏读 Read Committed:解决脏读,可能不可重复读 Repeatable Read:解决不可重复读,MySQL 默认级别 Serializable:串行执行,并发能力最低
3. MySQL 的 MVCC 机制原理及不同隔离级别下的应用场景是什么?
答案:MVCC 是多版本并发控制,核心是让读写尽量不互相阻塞。InnoDB 每行记录有隐藏字段,比如事务 ID 和回滚指针。事务更新数据时不会直接覆盖旧版本,而是生成新版本,并通过 undo log 保存旧版本。查询时根据 ReadView 判断当前事务能看到哪个版本。
在读已提交下,每次普通查询都会生成新的 ReadView,所以同一事务里两次查询可能看到不同结果。在可重复读下,事务第一次一致性读生成 ReadView,后续复用它,所以同一事务内多次查询结果稳定。MVCC 适合读多写少、并发查询高的业务,但对当前读、更新、删除仍然需要加锁。
-- 一致性读,走 MVCC SELECT * FROM account WHERE id = 1; -- 当前读,需要读取最新版本并加锁 SELECT * FROM account WHERE id = 1 FOR UPDATE;
4. 跨平台转账程序设计的核心逻辑是什么?
答案:跨平台转账不能设计成简单的“扣 A 账户、加 B 账户”,因为它涉及外部渠道、网络超时、重复回调、对账、补偿和资金安全。核心逻辑应该是状态机 + 幂等 + 冻结资金 + 异步确认 + 对账补偿。
一般流程是先创建转账单,校验账户和风控,冻结付款方资金,调用外部渠道扣款,等待渠道回调或主动查询,收款方入账,最后完成转账。如果中间失败,要根据状态决定退款、补偿、人工介入还是继续重试。
transfer_fsm = {
"INIT": ["RISK_CHECKED", "FAILED"],
"RISK_CHECKED": ["FROZEN", "FAILED"],
"FROZEN": ["CHANNEL_PROCESSING", "UNFROZEN"],
"CHANNEL_PROCESSING": ["DEBIT_SUCCESS", "DEBIT_FAILED", "UNKNOWN"],
"DEBIT_SUCCESS": ["CREDIT_SUCCESS", "COMPENSATING"],
"CREDIT_SUCCESS": ["FINISHED"],
"UNKNOWN": ["QUERYING", "MANUAL_CHECK"],
"COMPENSATING": ["COMPENSATED", "MANUAL_CHECK"]
}
5. 支付宝转账资金保障的核心流程与异常处理机制是什么?
答案:资金保障的核心是不能让任何异常导致多扣、少扣、重复入账或资金状态不明。流程上通常会使用转账单、资金流水、账户账本、渠道流水和对账任务共同保证。每个业务请求都要有全局唯一幂等号,资金变动要有可追溯流水,账户余额变动要满足借贷平衡。
异常处理重点是处理中间态。比如扣款成功但入账失败,要进入补偿;渠道超时但不确定是否扣款,要进入 UNKNOWN 状态并主动查询;重复回调要通过幂等表和状态机拦截;日终对账发现不一致,要生成差错单并进行补单、冲正或人工审核。
CREATE TABLE fund_flow (
flow_id BIGINT PRIMARY KEY,
transfer_id BIGINT NOT NULL,
account_id BIGINT NOT NULL,
direction VARCHAR(16) NOT NULL,
amount BIGINT NOT NULL,
status VARCHAR(32) NOT NULL,
request_id VARCHAR(128) NOT NULL,
created_at DATETIME NOT NULL,
UNIQUE KEY uk_request(request_id)
);
6. 在分布式订单创建流程中,若后续环节失败,如何实现事务回滚?
答案:分布式订单创建通常跨订单、库存、优惠券、支付、物流等多个系统,不能依赖单机数据库事务。常见方案是 Saga、TCC、本地消息表和最终一致性。核心思想是每一步都有对应的补偿动作,失败后按相反顺序补偿。
比如创建订单成功、库存预占成功、优惠券锁定成功,但支付单创建失败,就需要释放优惠券、释放库存、关闭订单。补偿动作必须幂等,因为补偿任务也可能重试。对于资金类强一致场景,可以用 TCC;对于订单履约类场景,Saga 更常见。
class Saga:
def __init__(self):
self.compensations = []
def step(self, action, compensation):
result = action()
self.compensations.append(compensation)
return result
def rollback(self):
for compensation in reversed(self.compensations):
compensation()
saga = Saga()
try:
saga.step(create_order, cancel_order)
saga.step(reserve_inventory, release_inventory)
saga.step(lock_coupon, unlock_coupon)
saga.step(create_payment, close_payment)
except Exception:
saga.rollback()
7. Redis 分布式锁的底层实现原理是什么?
答案:Redis 分布式锁的核心是利用 SET key value NX PX ttl 保证加锁原子性。NX 表示 key 不存在才设置,PX 表示设置过期时间,避免业务宕机后锁永远不释放。value 必须是唯一随机值,释放锁时要先判断 value 是否一致,防止误删别人的锁。
释放锁不能用简单的 GET 再 DEL,因为两条命令不是原子的。正确做法是使用 Lua 脚本保证判断和删除原子执行。
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
lock_key = "lock:order:10001" lock_value = "uuid-request-001" # SET lock:order:10001 uuid-request-001 NX PX 30000
8. Redis 集群主节点宕机对分布式锁有什么影响?解决方案是什么?
答案:如果 Redis 主节点刚写入锁,还没同步到从节点就宕机,集群发生主从切换后,新主节点可能没有这把锁。此时其他客户端可能再次加锁成功,导致多个客户端同时进入临界区。这是 Redis 单主异步复制带来的锁安全问题。
解决方案要看业务风险。如果是普通防重复提交,可以接受短暂风险;如果是资金、库存这类强一致场景,不能只依赖 Redis 锁,还要结合数据库唯一约束、状态机和乐观锁。也可以使用 RedLock、ZooKeeper、etcd 这类更强一致的协调组件,但 RedLock 在极端时钟漂移和网络分区下也不是万能方案。
-- 关键业务仍然要用数据库约束兜底 ALTER TABLE order_dedup ADD UNIQUE KEY uk_biz_request(biz_id, request_id);
9. 什么是数据库回表?如何减少回表?
答案:回表是指通过二级索引查到主键后,还需要再去聚簇索引查询整行数据。InnoDB 的主键索引叶子节点存整行数据,二级索引叶子节点存索引列和主键值。如果查询字段不在二级索引里,就要回表。
减少回表可以使用覆盖索引,也就是让查询字段都在索引中。这样只扫描二级索引就能返回结果。实际设计时不能把所有字段都塞进索引,因为索引越大,写入和维护成本越高。
CREATE INDEX idx_user_status_time_amount ON order_info(user_id, status, created_at, amount); SELECT user_id, status, created_at, amount FROM order_info WHERE user_id = 10001 AND status = 'PAID' ORDER BY created_at DESC LIMIT 20;
10. 电商订单如何设计多维度查询存储方案以应对用户和商家的检索需求?
答案:电商订单查询有两个典型视角:用户查自己的订单,商家查店铺订单。用户侧更关注用户 ID、订
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏聚焦 AI-Agent 面试高频考点,内容来自真实面试与项目实践。系统覆盖大模型基础、Prompt工程、RAG、Agent架构、工具调用、多Agent协作、记忆机制、评测、安全与部署优化等核心模块。以“原理+场景+实战”为主线,提供高频题解析、标准答题思路与工程落地方法,帮助你高效查漏补缺.