面试题

以下结合投资研究系统,针对SHEIN Java开发工程师社招一面问题,逐一给出回答思路与示例,突出业务场景与技术结合:

1. 说下项目的亮点难点

回答思路:聚焦投资研究系统,选「多源研报智能整合 + 高并发证券数据查询」场景,讲清业务价值、技术挑战、创新解法。

示例
在投资研究系统中,多源研报智能整合是核心亮点与难点:需从外部券商(如Wind、东方财富 )、内部投研团队同步研报,支持全文检索、关键信息抽取(如目标价、核心逻辑 ),还要保障证券信息管理模块的高并发查询(投研人员实时查股票基本面 )。

  • 亮点

    • RabbitMQ 异步化:外部研报接入时,通过 MQ 解耦,接入服务只负责接收,消费端异步解析、入库,峰值时每秒处理 200+ 份研报,吞吐量提升 3 倍;
    • Elasticsearch 全文检索:构建研报索引,支持按标题、关键词、作者检索,结合 Redis 缓存热门研报,查询响应从 500ms 压降到 80ms 。
  • 难点

    • 多源数据格式异构:外部研报有 PDF、Word、HTML 等,解析规则复杂(如 PDF 表格提取 )。通过 策略 + 模板模式,定义 ReportParser 接口,实现不同格式解析类,Spring 动态加载,新增格式只需扩展类;
    • 证券数据高并发冲突:投研人员同时查询、修改证券信息(如财务指标 ),用 Redis 乐观锁(watch + multi )做并发控制,结合 Oracle 行锁,解决数据不一致问题。

2. 知道哪些限流算法,分别说一下底层原理,滑动窗口和令牌桶的区别

回答思路:列举常用算法,结合投资系统场景(如研报上传、证券查询限流 )讲原理、差异。

示例
常用限流算法有 固定窗口、滑动窗口、令牌桶、漏桶,在投资系统中,证券查询接口用滑动窗口,研报上传用令牌桶。

  • 固定窗口
    原理:将时间划分为固定窗口(如 1 分钟 ),统计窗口内请求数,超阈值则限流。
    场景:证券信息管理模块的低频配置接口,简单易实现,但临界时间(如窗口切换 )可能突增流量。

  • 滑动窗口
    原理:把时间窗口拆成小格子(如 1 分钟拆 6 个 10 秒格子 ),实时滑动,统计最近窗口内请求数。
    场景:证券实时行情查询(高并发 ),比固定窗口更平滑,避免临界突刺。

  • 令牌桶
    原理:令牌桶以固定速率生成令牌,请求需获取令牌才能执行,桶满则暂停生成。
    场景:研报上传接口(需限制带宽 ),允许一定突发流量(桶内积累令牌 ),又能控制长期速率。

  • 滑动窗口 vs 令牌桶

    • 滑动窗口控频更精准,适合纯请求数限流;
    • 令牌桶支持流量突发,兼顾速率与突发,适合有带宽/资源限制的场景(如投资系统的文件上传 )。

3. 线程的状态有哪几个?

回答思路:基于 Java 线程状态(Thread.State ),结合投资系统线程池、MQ 消费场景说明。

示例
Java 线程有 6 种状态:

状态 场景说明(投资系统)
NEW 初始化证券数据同步线程,未调用 start()
RUNNABLE 研报解析线程执行中(CPU 运行/等待资源 )
BLOCKED 线程竞争 Oracle 行锁,等待进入同步块
WAITING 线程池线程调用 LockSupport.park() ,等待 MQ 消息触发
TIMED_WAITING 证券缓存预热线程 Thread.sleep(1000) ,定时刷新
TERMINATED 历史数据归档线程执行完毕,资源释放

4. Java线程和操作系统线程的区别

回答思路:从映射关系、调度、生命周期管理切入,结合投资系统性能优化场景说明。

示例

  • 映射关系
    Java 线程早期(JDK 1.2 前 )是用户级线程,现在(JDK 8+ )与 OS 线程 1:1 映射(通过 pthread 实现 )。投资系统中,证券查询线程对应 Linux 内核线程,由 OS 调度。

  • 调度机制
    Java 线程调度由 JVM 负责(如线程优先级 ),但最终依赖 OS 调度器;OS 线程直接由内核调度。投资系统的策略回测线程池,通过设置线程优先级(setPriority ),让关键策略计算线程优先执行。

  • 生命周期管理
    Java 线程由 JVM 管理(创建、销毁 ),OS 线程由内核管理。投资系统中,Executors.newFixedThreadPool 创建的线程,JVM 统一回收,避免 OS 线程泄漏。

5. 线程和线程池的生命周期

回答思路:拆分线程、线程池的状态流转,结合投资系统线程池(如证券数据更新池 )说明。

示例

(1)线程生命周期(简化版 ):

NEWRUNNABLETERMINATED(正常结束 ),或中途进入 BLOCKED/WAITING 等状态。

(2)线程池生命周期(以 ThreadPoolExecutor 为例 ):

  • 运行状态(RUNNING ):接收任务,证券数据更新池初始化后,持续处理 updateStockData 任务;
  • 关闭中(SHUTDOWN ):调用 shutdown() ,不再接收新任务,处理队列剩余任务(如系统优雅停机 );
  • 停止(STOP ):调用 shutdownNow() ,中断正在执行的任务,清空队列(紧急故障恢复 );
  • 终止(TERMINATED ):所有任务处理完毕,线程池彻底关闭,资源释放。

6. MQ熟悉哪几个?rabbitmq和其他mq的区别?他们都是怎么保证消息的顺序?

回答思路:对比 RabbitMQ、Kafka、RocketMQ ,结合投资系统消息场景(研报同步、证券数据变更 )说区别与顺序保证。

示例

(1)熟悉 MQ:

投资系统用 RabbitMQ(研报异步解析、证券信息变更通知 )、Kafka(日志采集、大数据流处理 )。

(2)RabbitMQ vs 其他 MQ(以 Kafka 为例 ):

维度 RabbitMQ Kafka
定位 通用消息中间件,侧重可靠投递 大数据流处理,侧重高吞吐
消息顺序 单队列 + 单消费者保证顺序 分区内有序,多分区需全局排序
适用场景 研报解析(低延迟、高可靠 ) 行情数据实时流(高吞吐 )
生态 插件丰富(如延迟队列 ) 生态完善,适合大数据链路

(3)消息顺序保证:

  • RabbitMQ:发送到同一队列的消息,由单消费者顺序消费,投资系统中「证券评级变更通知」用单队列,保证投研人员收到顺序消息;
  • Kafka:分区内消息有序,投资系统的行情数据(按股票代码分区 ),同一股票的行情变更消息发同一分区,消费时顺序处理。

7. 你知道java有哪几种锁?cas原理是什么?aba问题怎么解决呢

回答思路:分类锁(乐观/悲观、公平/非公平等 ),结合投资系统并发场景(证券数据修改 )讲 CAS 与 ABA 。

示例

(1)Java 锁分类:

  • 悲观锁:如 synchronized(证券信息管理的 Oracle 数据更新 ),认为并发冲突概率高,直接加锁;
  • 乐观锁:如 AtomicInteger(基于 CAS ),证券缓存计数用 AtomicLong ,先操作再校验;
  • 公平锁/非公平锁:ReentrantLock 可配置,投资系统的策略回测线程池用非公平锁,提升吞吐量;
  • 分段锁:ConcurrentHashMap 的分段机制,证券代码哈希分段,减少锁竞争。

(2)CAS 原理:

Compare-And-Swap(比较并交换 ),3 个核心值:内存值(V )、预期值(A )、新值(B )。
投资系统中,证券缓存版本号更新用 CAS:

// 伪代码:更新证券缓存版本
AtomicReference<StockCache> ref = ...;
StockCache old = ref.get();
StockCache newCache = old.updateVersion();
// 比较并交换,版本号一致才更新
ref.compareAndSet(old, newCache);

(3)ABA 问题解决:

版本号/时间戳 ,投资系统中证券数据变更消息带版本号:

// 证券数据对象
class StockData {
    private int version; // 版本号,每次变更 +1
    private String data; 
}
// CAS 时,对比版本号 + 数据
ref.compareAndSet(oldVersion, newVersion);

8. 你们怎么做的分库分表?为什么要这样做分库分表?

回答思路:结合投资系统数据规模(证券数据、研报、模拟组合 ),说分库分表策略(垂直/水平 )、路由规则、业务价值。

示例

(1)分库分表原因:

投资系统初期用单 Oracle 库,证券表超 5000 万条、研报表超 2000 万条,查询慢(如按股票代码查历史数据 ),DML 操作锁表严重,因此分库分表。

(2)分库分表策略:

  • 垂直分库:按业务拆分,将「证券信息管理库」「研报库」分离,减少跨业务干扰;
  • 水平分表:证券表按 股票代码哈希分表stock_info_0 ~ stock_info_31 ),研报表按 上传时间 + 机构 ID 哈希分表,路由规则:
    // 证券表路由:股票代码哈希取模
    String tableName = "stock_info_" + (stockCode.hashCode() & 31);
    

(3)价值:

  • 查询性能:证券查询从 500ms 降到 80ms ,研报检索从 1s 降到 300ms;
  • 扩展性:支持后续证券数据量增长,新增分表只需扩展路由规则。

9. 数据库索引了解吗?B+树有什么特征吗?

回答思路:讲清索引类型(聚簇、非聚簇 )、B+ 树结构,结合投资系统 Oracle 表设计说明。

示例

(1)数据库索引:

投资系统中,证券表建 聚簇索引(按股票代码 ),研报表建 非聚簇索引(按上传时间 + 机构 ID )

  • 聚簇索引:数据物理存储与索引顺序一致,适合范围查询(如查某行业股票 );
  • 非聚簇索引:索引与数据分开存储,适合高频点查(如查某机构最新研报 )。

(2)B+ 树特征:

  • 结构:叶子节点有序且连成链表,非叶子节点存索引键,叶子节点存数据地址(或数据 );
  • 优势
    • 投资系统中,证券代码查询走 B+ 树,范围查询(如查代码 600000~600100 的股票 ),可通过叶子节点链表快速遍历;
    • 高度低(3 层可存千万级数据 ),证券表 5000 万条数据,B+ 树高度 3 ,查询只需 3 次 IO 。

10. 你觉得这样做能解决什么问题?又会带来什么问题?

回答思路:承接分库分表、MQ 等技术决策,说解决的业务问题(性能、扩展性 )与引入的新挑战(分布式事务、运维复杂度 )。

示例(以分库分表为例 ):

(1)解决的问题:

  • 性能:证券、研报查询从「全表扫描」变「索引 + 分表查询」,响应时间从秒级→毫秒级;
  • 扩展性:支持未来 3 年数据增长(证券新增 10 万+ 、研报新增 500 万+ );
  • 隔离性:垂直分库后,证券业务与研报业务故障互不影响。

(2)带来的问题:

  • 分布式事务:跨分表更新(如证券代码变更需同步更新关联研报 ),用 Seata 补偿机制,增加复杂度;
  • 运维成本:分库分表后,需维护多库多表,监控、备份、恢复难度提升;
  • 跨表查询:如查「某机构发布的所有证券研报」需跨分表聚合,用 Elasticsearch 辅助解决。

11. 项目里面说有解决慢sql、cpu飙高、数据库死锁等经验,说下怎么解决的

回答思路:分场景(慢 SQL、CPU 高、死锁 ),结合投资系统实际案例,说排查流程与解法。

示例

(1)慢 SQL 解决(证券历史数据查询 ):

  • 现象:投研人员查「某股票近 5 年财务数据」,SQL 执行 10s+;
  • 排查
    1. 用 Oracle AWR 报告,发现全表扫描(未走索引 );
    2. 分析 SQL:SELECT * FROM stock_finance WHERE stock_code = '600000' AND year BETWEEN 2018 AND 2023year 字段无索引;
  • 优化
    建复合索引 idx_stock_year (stock_code, year) ,SQL 执行时间降到 80ms 。

(2)CPU 飙高解决(研报解析线程池 ):

  • 现象:研报解析服务 CPU 长期 90%+ ,系统卡顿;
  • 排查
    1. top 命令发现 Java 进程 CPU 高,top -Hp 定位到解析线程;
    2. jstack 分析,发现正则表达式匹配(研报正文提取 )存在回溯爆炸;
  • 优化
    替换正则表达式(如用非贪婪匹配 .*? 替代 .* ),优化后 CPU 降到 30% 以内。

(3)数据库死锁解决(证券信息更新 ):

  • 现象:证券代码变更与研报关联更新,出现死锁;
  • 排查
    1. 查 Oracle 死锁视图 v$lock ,发现两个事务互相等待对方锁;
    2. 分析代码,证券更新与研报更新的 SQL 顺序不一致(事务 A:先更证券 → 再更研报;事务 B:先更研报 → 再更证券 );
  • 优化
    统一 SQL 执行顺序(先更证券主表 → 再更关联研报 ),加锁超时重试(select ... for update wait 3 ),死锁率从 5%→0 。

12. 有什么想问我的吗?

回答思路:问岗位技术栈、团队业务方向、成长路径,体现对岗位的关注。

示例
想了解 SHEIN 目前 Java 后端在高并发场景(如全球业务、海量订单 )的技术挑战,以及团队在云原生、微服务治理方面的实践规划。另外,想知道团队内技术分享与新人成长支持(如有没有定期的技术 workshop ),方便我提前准备融入~

以上回答紧扣投资研究系统业务,将技术问题融入真实场景,既体现技术深度,又展示业务思考,适配SHEIN Java开发岗位需求。可根据实际项目细节调整,让回答更贴合自身经历!

posted @ 2025-08-16 11:23  一刹流云散  阅读(16)  评论(0)    收藏  举报