
--- 摄于 2017 年 9 月 藏川线前段
最近发生的事情不算少。从十一月初开始,我就病倒了。这是一种皮肤病,导致左腿肿胀到原来的 1.2 倍,右腿情况稍好,但也肿了,一碰就疼。养病期基本持续了一个月,至今也未能痊愈,只能说恢复得差不多了。肿胀已基本消退,疼痛感也几乎消失,剩下的一点小问题,就交给时间慢慢修复吧。雪上加霜的是,生病的同时我还扭伤了手腕,真是祸不单行。
皮肤病对我而言并不陌生。从小到大,说三年一遇也不夸张,早已是常客。遇到时,先换掉床单被套,然后静观其发展加重,再静待其自行恢复。2020 年左右也碰到过一次,全身都起了症状,奇痒无比,但不疼。医院诊断为一种来源不明的教科书级自限性疾病,只需辅助治疗,等待痊愈即可。因为症状与梅毒极为相似,我还做了一次 HIV 检测,结果是阴性——当然,我当时也没有过任何高危行为。这次也是如此,近三个月活动范围都没超出家附近方圆五公里,也未在外过夜。但既然发生了,就安心等待康复。
几个月前,我心血来潮接了两家面试邀请,想体验一下近期的面试氛围,主要有以下几个目的:
结果是:一家聊得不错,但在第三轮面试后被 HR 拒绝,理由是我的求职意向不强——这确实是事实,毕竟我的主要目的并非跳槽;另一家则聊得不甚愉快,第一轮面试就失败了。
其实,第一家二面过后,我就觉得后续机会不大了。从沟通中我了解到,他们需要的是一位精通内存操作、写过类似内存数据库的大师,能够随心所欲地处理内存中的各种数据。这种经验我不能说完全没有,但远未达到大师级别,无法轻松地从零构建一个类 Redis 的系统。整体而言,那次面试沟通顺畅,彼此都明确了需求和预期,最后被 HR 拒绝也合情合理,我并无怨言。
但第二家的面试体验就相当糟糕了,甚至让我感觉受到了冒犯。众所周知,我的临场反应能力有限,直到面试结束后查阅资料,才发现面试官竟然在忽悠我。例如,他问了这样一个问题:
面试官:“如何判断网络中节点间的距离?” 我:“要实现这个,工程量会比较大……”(我还没来得及说要把 traceroute 的逻辑实现在节点里) 面试官:“这怎么会复杂?直接用两个 IP 地址进行异或运算,结果越小就越近。有论文支撑的。”
这个说法看似正确,但实际上,通过 IP 地址异或值来判断距离仅在少数场景下有效。不过,既然他都搬出了“论文”,我当时便没有深究,心想“你说得都对”。
我可以举一个简单的反例:在家庭网络中,假设划分了两个子网,每个子网下各有一台服务器,通过一个路由器相连。这种情况与两台服务器在同一个子网内直连路由器相比,网络距离并无本质区别,但后者的 IP 异或值会更小。这种场景并不少见,比如在 BGP 组网中,通过关键路由,可以一跳到达一个逻辑距离很远但物理距离很近的 IP 段。
实际上,这两场面试我都是即兴参与,没有做任何特别准备,甚至连自己的项目介绍都没仔细回顾,纯粹是凭日常经验应对。与第一家相比,第二家的面试更像是在走标准流程。无论你的背景和经验如何,都得过一遍题库——除了算法题,甚至还问到了 MySQL 底层表结构的实现细节。
面试结束后,我仔细看了一下招聘信息,职位描述里确实没有要求 DBA 的技能。我很好奇,这类问题是如何进入他们的面试题库的?至于面试中的算法题,说实话,在当今时代,只要上下文信息充足,绝大多数人编写代码的速度和质量都无法超越 AI。我不太确定这种筛选方式能否真正找到合适的候选人。
我强烈认为,面试在很大程度上看缘分。半小时到一小时的简单交谈,远不足以全面了解一个人的技能水平、工作能力和心理状态,它仅仅是一个缩影。在这个过程中,面试官最想找到什么样的人,才是决定性的因素。完全依赖流程和题库,至少找不到我想要的那种同事。
我做面试官时,希望找到的人不仅要具备一定的技术水平,更重要的是要对技术抱有热情,能够自发、自主地工作。当然,这只是我的个人偏好,也正因如此,我才说“面试完全是缘分”。
候选人当场写不出算法题没关系,因为面试前我通常会浏览他们的 GitHub 项目,通过代码大致了解其水平。面试时,我甚至不会出算法题,而是会问思路,探讨项目中遇到的难题、解决方案以及有无更优方案等。编程语言本身也不是关键,纠结于 Python 的七种格式化写法或 Go 的 defer 优化实例之类的问题,我认为意义不大。况且,如今的 AI 只要得到一个函数签名和足够的信息,就能写出又快又好的算法。很多时候,我自己也会被它启发,找到新的解决方案。AI 对知识的整理和提炼能力远超人类,善用工具远比死记硬背更重要。
有人或许会批评我这种面试方式成本太高,认为求职者众多,用标准题库筛选即可,通过了才有资格获得更深入的了解。怎么说呢,大公司确实可以这样做,但又有几家公司称得上是“大公司”呢?我虽未在互联网大厂工作过,但也了解那种环境:感觉自己可有可无,比一颗螺丝钉还不如,却仍要应对各种莫名其妙的压力,内心既憋屈又无奈。我讨厌那种感觉,所以我选择了离开。每个人都有自己的选择,也都要承担选择的后果。我的看法不一定是对的。
这并非我第一次在现场被误导,事后才反应过来。还是那句话:我的临场思维能力确实有限。
我记得在一次技术讨论中,有人断言,某个用 Go 实现的协议,其内存分配是一次性的,数据能从上层协议直通内核,中间无需任何额外的内存分配。我当即反问:“你确定吗?要实现多协议组合下的零拷贝,需要上层协议知晓下层协议的头部(Header)构成,甚至要预知多个头部的总长度,在构建消息时预留出足够空间,以便下层协议直接在预留位置写入数据,而无需复制。”对方斩钉截铁地给予了肯定的答复。当时我没有验证,事情就这么过去了。事后查证才发现,这完全是在蒙人。没有哪个独立的协议库会这样实现,这属于严重的“抽象泄漏”,已经泄漏到不知哪里去了。
简单解释一下这个问题:标准的网络协议都有自己的格式,通常由“头部 + 消息体”(Header + Body)组成。头部用于说明消息体的大小和当前消息的特性,如连接验证、状态切换、行为模式变更等,最简单的模式就是“长度 + 消息体”(Length + Body)。当多个协议层层嵌套时,每一层都有自己的头部和消息体,在将最终的数据包交给内核前,其结构可能已经变成了类似 header1 + (header2 + (header3 + body)) 的形式。若要确保协议在传递过程中不产生任何内存分配,就必须在最顶层预先分配好能容纳所有头部和最终消息体的总内存,并在 header3 的位置写入当前层的数据,然后逐层向下传递,由下层协议在指定位置填充各自的头部内容。这完全不符合协议独立实现的设计逻辑,除非所有协议都在同一个代码库中统一维护,且不考虑将它们作为独立模块使用——但这种实现方式本身就非常奇怪。
好了,这里主要是报个平安,虽然也没人知道我的具体病情,后面可能会针对一些工作上遇到的问题写点东西,这期就这样了。
请登录后评论
评论区
加载更多