在上篇 文章 https://github.com/farmerjohngit/myblog/issues/21 中, 说了 java 后端面试中常问的基础问题, 而面试除了考察基础以外, 很重要的另一部分是'经验','经验'泛指以往做过的项目, 解决的问题, 以及一些开放性问题.
本文主要说两点: 1. 项目 2. 开放性问题. 注意两篇文章 针对都的是 java 一线研发岗位 .
更多文章见个人博客: https://github.com/farmerjohngit/myblog
公众号(刚申请, 之后文章会往上面发):
先说点题外话, 有同学对于上篇文章中有些看法: 比如, xxx 的底层实现和大多数程序员日常开发几乎无关, 有种应付考试的感觉.
我说说我的观点,
第一, 大厂面试 就是 会问 jvm, 中间件, 数据库等原理性的问题, 你要想去大厂 就必须在日常中积累和在面试前准备. 简单粗暴吧?
第二, 挺多公司被调侃是面试时造火箭, 工作时拧螺丝. 这样的情况是很普遍的, 那大厂为什么喜欢问这些问题? 我认为原因有几点:
1. 人才储备, 可能你面试的岗位平时就是搬搬砖, 不会涉及到有技术深度的问题, 但是对于大公司而言, 必须要确保当出现技术难题时是有人来解决的. 比如很多部门的并发量并不高, 但是面试时也会问高并发相关的问题, 其目的就是为了确保万一 QPS 高起来了, 部门里的人都是有方案, 有经验的. 这么说应该很容易明白吧.
2. 筛选人才, 如果两个候选人, 一个对于所有的框架都只是会使用, 另一个除了会使用以外还清楚框架内部是如何实现的. 如果你是面试官, 你会选谁呢?
3. 有技术热情的人 一定 会对某块领域上有过比较深入研究(可以是 jvm, 中间件, 数据库以及其他)
回到本文正题, 先来聊聊项目.
项目
对于简历上写的项目, 要从这几个方面去准备:
项目介绍: 用最简洁的语言介绍清楚你的项目, 包括项目的背景, 方案, 用到的关键技术, 承担的角色, 介绍时不要扯太多细节, 让面试官有个大致了解就行, 面试官遇到感兴趣的点时自然会追问. 准备时要考虑到面试官可能完全不了解你的业务(比如面试官是做电商的, 你的是金融项目).
项目架构: 能把项目的架构说清楚, 能画出项目架构图, 能说清楚项目在整个系统中的位置.
项目价值: 想清楚做这个项目的价值在哪里? 比如让业务数据提高了 XX 点, 开发效率提升了 XX 倍. 比较忌讳的是直接说老板让我做所以我就做了.
技术选型: 如何做技术选型的? 有考虑过哪些技术方案, 是什么让你选择了最终的方案?
数据: 项目带来的成果, 比如业务项目转化率或点击率提高了 XXX. 对系统日常数据要有个大概印象, 比如集群的总 QPS 是什么量级, 大概多少台机器等, 真正参与了的基本上也都知道, 就怕是把别人项目说成自己的, 这些数据一问就很容易看出来.
预案: 很多小公司的项目实现功能就好了, 对于可用性, 一致性等要求没那么高. 但在面试前准备时需要对项目中有缺陷的点做好预案. 举个例子: 数据落库后要发消息通知到其他系统, 可能你的项目中是:
- // 1. 数据落库
- writeToDB();
- // 2. 发消息
- sendMsg();
以上伪代码的问题是写完数据库后, 如果系统挂了 (可能是你的系统挂了也可能是消息中间件挂了) 导致消息没发送成功, 就会有不一致的情况发生. 可能你的项目中漏发几条消息也没关系, 但是当面试官问到如何保证写 DB 和发消息同时成功或同时失败时, 你心中要有预案 .
规划(如有): 项目之后要做成什么样子, 要添加哪些功能, 目前有哪些做的不好的地方需要优化.
开放题
下面是我面试被问的比较多的场景题, 系统设计方面的题, 开放题跟个人经历也有关系, 所以仅供参考.
分布式事务
分布式事务这块实现方案比较多, 互联网公司很少用 2pc 这样的方案, 一般都是保证事务的最终一致性, 常用事务消息实现(以及 tcc 等). 要知道如何利用事务消息去实现最终一致性, 以及事务性消息是如何实现的.
分布式事务没有一个绝对的方案, 都是因业务场景的不同而不同. 举个例子, 电商场景中如何保证订单落库和减库存, 锁券的最终一致性的(不同公司有不同方案, 只是列举个我知道的).
收到用户下单请求时, 在订单库中创建一条不可见订单.
同步调用减库存接口, 如失败跳转到 4
同步调用锁券接口, 成功跳转到 5, 失败跳转到 4
发送一条废单消息, 收到消息后回库存, 回券
将订单改为可见
分布式事务的问题, 我面试的公司基本上都问过.
如何保证系统高可用
这个一般会结合你的项目来问, 比如上游系统请求量过大, 依赖的下游非核心应用挂掉, 系统出问题如何及时发现等等. 主要是从限流, 降级, 监控, 报警, 主从备份, 容灾等角度出发
分布式锁
实现分布式锁常见方案有: 利用 db 的唯一键, Redis,zk 等. 其中 Redis 实现分布锁应该是用的最多的. 关于如何用 Redis 实现分布式锁可以看下这篇 文章 , 当然更严谨的实现还是看 Redis 的分布式锁官方实现: Redisson https://redis.io/topics/distlock
缓存与 DB 一致性
我们经常会在 DB 和应用之间加一层 Redis 缓存, 以提高查询效率, 但是当数据发生更新时, 如何保证缓存与 DB 的数据一致性呢? 可以看看这篇 文章 https://coolshell.cn/articles/17416.html , 之后我也写写阿里是如何保证缓存一致性的.
缓存击穿
Redis 缓存穿透, 缓存雪崩和缓存击穿几个问题, 在网上都有比较成熟的解决方案了. 比如加空 value, 设置随机超时时间, 加互斥锁等方式
海量数据处理
如海量日志数据, 提取出某日访问百度次数最多的那个 IP.
一般是 hash + 归并, 布隆过滤, Map Reduce 的思路
这篇 文章 说的很好了
限流
常见限流的方案, 如令牌桶算法, 可以看下我之前写的 来谈谈限流 - 从概念到实现 https://github.com/farmerjohngit/myblog/issues/18 , 来谈谈限流 - RateLimiter 源码分析 https://github.com/farmerjohngit/myblog/issues/19
问题排查
一些常见线上问题比如系统的 CPU 占用过高, RT 突然飙升, 频繁发生 full gc,OOM 等如何定位并解决?
这主要来自于日常的积累了, 排查问题主要依赖监控, 日志, 常用工具(top jstack jmap jstat vmstat 等).
End
去年底找工作找了 2 个多月, 中间也经历了很多坎坷, 庆幸的是最后结果还不错, 也祝各位在找工作的朋友拿到满意的 offer.
来源: http://www.tuicool.com/articles/riqmIjm