po 到现在主要是游戏行业后端,现在是 go+redis 这个样子,姑且也算是个 senior 了,到没到 MS 的 senior 的标准还不好说,感觉 system design 这方面还有很多自己不懂的东西。
其实不太想一直在游戏行业留着,比较想回一个不太加班的科技公司,外加英语好,所以一直比较注意这些机会,但苦于各种原因还一直在游戏行业。
之前有创业经历,去年创业不太灵的时候 linkedin 收到过微软 HR 的邀请,尝试投递了下然后没有进面试,原因不太清楚。半年后被在微软的同学强烈的意愿下试着让他内推了下,也是给到 HR 之后就没回音了。
今年微软的又找过来,我提了这个情况,结果这次第一个职位的面试官打电话过来约了面试时间。
遂开始准备面试。
第一个职位:
https://careers.microsoft.com/us/en/job/1048544因为简历主要是游戏后端,所以背景也没啥好说的。简历里写了自己现在项目的游戏(一个回合制卡牌,1202 年还在用自动战斗那种)自己完全负责了战斗系统,而且做到了 x 倍性能优化和 xx%内存占用下降。
面试的时候这个就多说了下,然后立刻 coding 题。结果第一题就整懵了。
leet 里微软题库有,但是没复习到。
input:一个 n*n 矩阵,有一个必然闭合的 1 围成的不规则区域,除了这个区域边缘由 1 组成外,矩阵其他项均为 0 。
output:把闭合区域内的 0 全部改成 2 输出。
知道是 DFS 但不太清楚搜索从哪里开始。后来知道是 floodfill 类型的题目(同类题在 leet 里难度算 easy )。在面试官几乎摁着教搜索方向(四方向)和从哪儿开始搜索(矩阵四条边,把外层 0 标记,最后把外层 0 还原,内层 0 置为 2 )之后题目算是答出来了。
当然当时就知道因为这个不完全算自己的思路,肯定有问题。
然后挂了。
当时以为有冷冻期,HR 说可以接着面,提供了一个 M365 的职位。而且追问了我是不是想做全栈,我说是的,确实很想转全栈方向。
第二个职位:
https://careers.microsoft.com/us/en/job/991340HR 说 JD 里面要求的语言可以无视,SDE2 也可以无视,看最后能力定职级。遂 ok,约了时间继续面。
今早 10 点进入面试。差不多介绍战斗系统优化方向到面试 15 分钟左右被打断。
然后开始追问你们现在游戏服务器每个 node 的日志量,日志怎么收集,服务器状态怎么监控,服务怎么批量部署。我说日志收集处理用 filebeat+kafka,介绍了下基本的部署和监控用的 devops 的工具。
然后被追问 kafka 单个 broker 能承载的最大日志量。我说这个目前没有做太多研究,这部分就过了。
然后开始问 SQL 相关,我说我以前有过经验但现在将近两年多没有用过 SQL,主要是 redis 相关。
问了 sql 语句问题,第一个是(name class score)这样的表,class=A 取 score top5 的学生名字。这个写出来了。
然后问每个 class 取 score top5 的学生名字。这个在我以前也都比较少用,现在更是不知道,然后这里就过了。
然后开始问语言的并发,线程怎么创建,我现在主要用 go 就简单介绍了 goroutine 和 channel 的机制,然后被问到 mutex 和 semaphore 的区别,这里也比较好答出来了。
接下来是一些有关分布式系统部署的问题,ACID 和 CAP 相关概念,CAP 在不同业务需要先满足 CP 还是 AP 。
然后问了一个问题,一个生成 [严格自增 ID ] 的服务,要在大型分布式系统中做到高可用性如何做。
我说可以用单个服务器(追问:规模太大时单个服务器不行)
我说因为实在没做过这方面,游戏后端没有相关业务只能估计一下。当时提到了给每个 node 分配 ID 段的做法,但这不能满足严格自增。
他要求既严格自增又高 availability,我就不太清楚这里怎么办了。(后来查到其实趋势自增是可以的,包括雪花算法之类的,这些确实不了解。)
最后 coding 题,此时面试已经是 10 点 38 。
coding 题是关于 gray code 的,leet 题目:
https://leetcode.com/problems/gray-code/ (难度 medium )
(之前为了这一轮狂刷 leet,这一题我也没刷到。也不要说格雷码的位运算做法之类的,毕竟之前几乎就没听过这个概念)
和 leet 版不同的是要按二进制输出,(包括高位的 0 )
观察和试结果了一阵(包括猜测了队列改位之类的,发现不对)大约五六分钟之后我发现了一个规律:
设 grayCode(n)的输出是一个 string array (或者说 go 的 slice,这里视为可变长度 array )
那么
grayCode(n, prefix = "") = grayCode(n-1, prefix + "0").append(reverseGrayCode(n-1, prefix + "1"))
(不是 go 的语法不要在意)
为了节省时间请求从网上 copy 一个 go 的 reverse slice 的方法,同意了
然后基本开始做了
最后面试进行到 10 点 50,快要 debug 的时候(还是有一些语法错误)面试官:“我也不太了解 go,可以不 debug 了,你给我讲一下你这个的思路”
然后我讲了一下这个递归执行的流程,他一开始没太看清楚 prefix 我后面加了"0"或者"1",以为我 n=0 时直接返回 prefix 返回的是空。我再带他看代码的时候他才确认我这个做法没有问题。问我时间复杂度我说 O(2^n)。
10 点 58 左右面试结束。因为早上面试没有请假,客套了几句没有问面试官问题(说接下来有面试机会再问)就结束面试回去上班了。
下午 6 点 20 左右被 HR 通知挂掉了,原因是 coding 没通过。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
https://www.v2ex.com/t/789563
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.