二面摘录
-
这种(短链接服务)场景里面写入(创建短链)耗时长可否容忍?
- 一定程度上是 OK 的因为创建短链的请求比访问短链的请求少很多,容忍度更高;
-
在这个大量 KV 数据读写的场景,为什么不考虑直接使用 KV 存储或者 Redis 来支撑?
- 考虑过,但是短链服务本质上更需要背后收集到的访问数据来体现业务价值,而访问数据的聚合分析需要数仓,公司内没有很好的 KV 存储到数仓的支持,不想当小白鼠;
-
为何不考虑数据仓库提供 HBase 来支持读写,节约掉 MySQL / KV 存储同步到数仓的过程?
- 嗯,好像是个可考虑的想法,但是不太了解 HBase;
-
能说一下 LevelDB 的存储结构吗?
- 内心:完了写上简历了但又没复习,啥都不记得了;
-
算法:定义 Redis 跳跃表的结构,再实现一版它的插入方法。
- 内心:orz。
反问
-
在字节的技术人对于公司的基础架构的满意程度如何?
- 该有的都有;
-
外出参加技术会议、交流在字节里机会是否丰富?
-
前面很多问题都没有答对,面试官的建议?
3.2 米哈游
整体来说面试问题都很基础和简单,能不能通过的话(如果没特意复习)就靠平时的积累了。Golang 岗位里对数据结构的提问非常频繁,个人认为对 map
、sync.Map
、context
等的熟悉程度应该达到能完整记忆每个结构体字段的水准。
详细记录:2023 年初的米哈游面试复盘
一面摘录
-
Go 里面使用 Map 时应注意问题和数据结构?
- 可以通过定义 value 为 struct 来节约内存;
- 哈希分桶的结构,用哈希值的高八位和低八位分别来做桶内定位的依据和分桶的依据等;
-
Map 扩容是怎么做的?
- 依照 Redis 渐进式 rehash 的思路说了一版;
-
Map 的 panic 能被 recover 掉吗?了解 panic 和 recover 的机制吗?
- 不懂,但是实际上是不可以的,具体原因可以看看 Map 并发读写的时候抛出的是什么,是不是普通的 panic;
-
Map 怎么知道自己处于竞争状态?是 Go 编码实现的还是底层硬件实现的?
- 通过结构体中的标记位实现的,可能是通过 CAS 操作的;
-
CAS 具体是怎么实现的呢?
-
并发使用 Map 除了加锁还有什么其他方案吗?
-
有对比过 sync.Map 和加锁的区别吗?
-
说一下(Redis)分布式锁的实现?
- setnx / 唯一 value / ttl
-
基于 Redis 的分布式锁会有什么问题?
- 主从模型下同步不保证一致会导致锁失效
-
Redis 分布式锁超时可以超时时间设长一点可以吗?不可以的话需要怎么解决?
- 不根本解决问题,可以考虑旁路的 goroutine 不断自旋续期
-
对 Redis 锁续期这个怎么实现呢?
-
日常在用的 Redis 集群都是什么架构?在主从模式和 Redis Cluster 中分布式锁会有什么问题?
反问
- Golang 在米哈游的使用场景?
- 项目组的一些细节,代码组织、管理形式等是怎样的?
- 项目质量的保障手段有哪些,单元测试覆盖率要求如何?
- 测试的同学主要以白盒测试还是黑盒测试为主?
- 前面很多问题都没有答对,面试官的建议?
3.3 富途牛牛(互联网-基础/接入)
4 家中富途牛牛问的基础知识是最多的,给我印象很深刻的是跟每位面试官的沟通都(提)很(示)顺(很)畅(多),那因为一些不熟悉的知识点我基本是依靠同类的工具去类比和猜想,面试官很愿意听我的这些猜想,有些思路上和所问的实现确实是不同的,面试官会提出来那(正确实现中)某某问题是如何(在我提出的实现中)解决的,引导我慢慢靠近或者推导出正确实现。
(阳哥面试的时候也是这么做的,并且在作为面试官的时候也会这么做。)
我认为作为面试官,这些应该是标配培训的能力,但是实际上在面试中能见到的甚少,一是面试时间有限,二是作为面试官一天面试很多人,耐心难免也会有消磨,这都是可以理解的。所以实际上能做到如此的话,对面试者确实会是非常好的体验。
详细记录:2023 年初的富途牛牛面试复盘
一面摘录
- 问一段代码输出结果?
func main() {
fmt.Println(test1())
fmt.Println(test2())
fmt.Println(test3())
fmt.Println(test4())
return
}
func test1() (v int) {
defer fmt.Println(v)
return v
}
func test2() (v int) {
defer func() {
fmt.Println(v)
}()
return 3
}
func test3() (v int) {
defer fmt.Println(v)
v = 3
return 4
}
func test4() (v int) {
defer func(n int) {
fmt.Println(n)
}(v)
return 5
}
技术问题:
-
Golang 标准库中 map 的底层数据结构是什么样子的?
-
Map 的查询时间复杂度如何分析?
-
极端情况下有很多哈希冲突,Golang 标准库如何去避免最坏的查询时间复杂度?
-
Golang map Rehash 的策略是怎样的?什么时机会发生 Rehash?
-
Rehash 具体会影响什么?哈希结果会受到什么影响?
-
Rehash 过程中存放在旧桶的元素如何迁移?
-
并发环境共享同一个 map 是安全的吗?
- panic
-
如果并发环境想要用这种哈希容器有什么方案?
- sync.Mutex / sync.RWMutex
- sync.Map
-
加锁存在什么问题呢?
-
sync.Map 比加锁的方案好在哪里,它的底层数据结构是怎样的?
- 缓存 + map 组成的结构
- 底层 map 的操作依然是加锁的,但是读的时候使用上缓存可以增加并发性能
-
sync.Map 的 Load() 方法流程?
-
sync.Map Store() 如何保持缓存层和底层 Map 数据是相同的? 是不是每次执行修改都需要去加锁?
- 或许是通过加锁和 CAS 保证的?(面试官:它下面还有一些 tricky 的思路,面试结束可以再去看看)
-
channel 被 close 操作之后进行读和写会有什么问题?
-
未被初始化的 channel 进行读写会有什么问题?
-
channel 底层数据结构是怎样的,尝试用结构体来表述一下?
反问
- 了解面试部门的基本情况?
- 部门内微服务的数量?每个研发大概会负责多少服务的开发工作?
- C++ 和 Golang 在团队内的使用场景和比例?
- 研发对开发质量的保障是如何完成的,测试和覆盖率是否有要求?
- 研发和测试的人员配置比例?
- 前面很多问题都没有答对,面试官的建议?
二面摘录
-
如果做一个翻译服务,翻译能力来自于供应商,如何从技术上对几家(A、B、C)供应商作出评估?
-
如果几家都要接入,且各家之间的翻译能力都各有优劣,那应该如何去搭建这个服务的框架?
- 调度器
- 数据采集 / 反馈机制,帮助调度器更好地工作
- 可扩展性,固化供应商的接入标准,方便未来扩展更多供应商选择
-
除了回答的这些方面,一个服务的设计还需要注意什么?
- 正常服务应该提供的网关,包括鉴权、限流、多租户
- 提供给外部的服务需要注意 SLA,SLA 则围绕日志、监控、Tracing 做文章
-
一副扑克牌中随机取 5 张,取到顺子的概率是多少?
- Hint 1:一种花色有多少种顺子?9 种
- Hint 2:一个顺子有 5 张牌,有多少种组合可能?4 ^ 5 种
- Hint 3:分子已经知道了,分母怎么表示,n 张取 m 张怎么表示?
反问
-
项目基本都是微服务 & Kubernetes 这套方案吗?
-
研发跟基础设施打交道能到什么样的深度,例如能使用 Kubernetes 的那些内容,中间件的使用权限上有什么样的管控?
-
正常业务的 CI/CD 里面都做了/集成了多少测试或检查?
-
业务的研发能在 Kubernetes 上具体写哪些东西呢,例如 sidecar、operator 等等?
- 有专门的团队去做,但是还在起步阶段,大家都可以贡献;
三面摘录
-
数据库迁移的原因是什么?
-
完成迁移之后 DB 成本降低多少?
-
迁移过程中双读双写具体是什么样的方案?
-
双写过程中只写成功了其中一个 DB,返回给用户报错,那是否会存在脏数据呢?
-
双读具体是什么方案,其中一个读成功了就返回还是要两个都读成功才可以?
-
HTTP 流量的录制工具主要是做什么用呢?
-
HTTP 流量录制会涉及到一些登陆态的处理吗?
-
掷骰子,游戏规则:希望结果尽可能大,如果对第一次的结果不满意可以掷第二次,但是第一次结果就作废了,以第二次的结果为准。这个掷骰子结果的数学期望是多少呢?
- Hint 1:如果第一次扔到 6,还考虑扔第二次吗?如果第一次扔到 1 考虑吗?
- Hint 2:那什么情况考虑扔第二次,什么情况不考虑?
-
输入两个整数 a 和 b,输出他们相除的结果,如果有循环小数用括号表示。如:
- a=-1,b=2,输出 “-0.5”
- a=1,b=3,输出 “0.(3)”
- a=10,b=80,输出 “0.125”
- a=-100,b=10,输出 “-10”
三面反问
- 一、二、三轮的面试官都是团队中的什么角色呢?
- 组织架构中小组、中心的概念和规模?
- 作为管理者如果看到团队中的技术氛围比较欠缺,会考虑什么样的手段(去提升)呢?
- 在已有组件能支撑业务的情况下,如何看待 Member 提出的一些组件的升级或引入呢?
- 对于 CI/CD 这块,可能不会直接产生业务影响(例如更高的订单量),在公司的现状如何,以及如何看待将时间投入在这上面呢?
- 前面很多问题都没有答对,面试官的建议?
3.4 猿辅导(大监控-日志)
其实最初有一点点惊讶原来猿辅导在国家一些政策影响下仍在继续活跃。由于投递的是更贴近基础设施的岗位,很多问题能听得出来都是从基础架构工程师的角度发问的。另外它们家的面试有一个比较印象深刻的点就是,每位面试官都喜欢问:“你觉得 XXXXX”,例如 “你觉得哪些项目挑战最大”、“你觉得这里面最难的点在哪里”。不过作为投递里面唯一完全没接触过的领域,他们问的很多问题我都非常有兴趣继续探讨下去,也是少有的关注简历上CDC同步方案的团队。
详细记录:待补充 orz
一面摘录
待补充 orz
二面摘录
待补充 orz
三面摘录
待补充 orz
4. 总结
整体来说面试没有出现想象中的地狱难度,几乎所有的面试官都很有耐心交流。但是被问到这么多的基础问题确实有一点点出乎意料,正常以为会是项目 & 基础各占 50% 的比例。
不过或许这也是好事情,个人非常赞同:基础扎实但业务薄弱的工程师 > 对业务有不错理解但基础不扎实(或比较远离一线开发、代码生疏)的工程师。 另外其实计算机基础确确实实有在我的日常开发中帮到过我(quick question:你有在实际工作、排查问题中找过 TIME_WAIT
的网络连接吗?)。
回顾开篇
然后回到最初面试的目的:
- 3年间自己的技术是线性成长、指数成长还是对数成长,跟同龄人相比如何?
是有成长的,但是没有那么理想,可能更介于线性成长和对数成长之间;
5. 一些推荐
关于面试我认为下面的材料很大程度帮到过我,所以也会推荐给在看本文的你,或者要求职的同学。
USENIX:https://www.usenix.org/conferences
如果想树立一些属于自己的亮点,一个捷径是了解面试官不懂的知识~~(不是)~~。关心前沿的学术和工业论文非常简单有效,USENIX 上覆盖了很多基础方向,例如计算机网络、操作系统、存储、分布式、安全,以及按职能划分的 SRE 等等。除了 USENIX 上的以外,如果有你关注方向的其他顶会那当然也是可以的,例如我以前会去看看 VLDB 和 SIGMOD 上的论文了解 KV 存储的一些新知识和研究方向。
操作系统导论:https://book.douban.com/subject/33463930/
一本很有意思的操作系统的入门书,可以写写里面代码了解一下 Linux 的 API,对于进程和内存相关的讲解让我印象非常深刻。
Go程序员面试笔试宝典:https://book.douban.com/subject/35871233/
首先声明一点这个书没帮到我面试,因为在面试前我没什么时间看它…正常来说我也不会推荐这种速食读物(手动狗头),但是结合面试遇到的提问来看,我认为它会对急着在一两个月内找到工作的同学很帮助。不过无论如何,程序员的学习是不建议走捷径的,如果对 Golang 感兴趣的话,有很多更好的替代品,包括 Draveness 老师、Russ Cox 的博客等等。