Back End Daily Internship Second Round Failure
小鹅通-后端开发日常实习二面凉经
问题
Q:你先简单自我介绍一下吧
A:面试官您好,我叫某某,我来自深圳大学,我是 27 届,我的专业是电子信息工程,目前我是在一家主营业务是海外网文平台的公司做后端开发岗位的实习生,我个人目前的技术栈的话,我是学 C++ 出身,然后大概在去年十一月十二月的样子接触到 go 语言,我个人主要是想往后端发展,所以开始用 go 语言写一些项目,然后我目前实习的这个公司他们的项目主要是用 php 来写的,所以说我对 php 也有一些了解
然后我个人学校方面的话我去年是参加一个打创赛相关的社团,然后今年大二的话呢主要是在华为智能基座社团有一个软件开发部,在里面写一些项目之类的,我大概情况就是这样,谢谢
Q:目前是在另一家公司实习是吧?就是内部的这个系统
A:是的
感觉实习经历包装的不是很好所以面试官不太感兴趣,没有问下去,我自己当时也没有多补充,还是要再润色一下
Q:你之前自己学了一些 go,现在又写了一点 php,这两个语言你觉得写起来各自有哪些优劣?各方面都可以讲
A:我觉得 php 最大的一个特点就是它构建项目起来比较快,因为它有很多包工具或者像是什么那种命令行工具之类的,你可以写一些脚本快速把你的项目搭建起来,然后它有很多那种相对轻量级一些的框架,比如说 laravel,额 laravel 是比较全栈一些的,像是那个 gateway-worker,它就是那种现有的框架你可以直接拿来用,而且可以针对不同的场景(进行开发),这是 php
然后 go 语言最大的好处就是它语法非常简单,而且它的学习曲线没有那么的陡峭,而且我感觉它是对于程序员来说更加友好的一种语言,就是它会让你更专注于逻辑的开发而不是纠结于,比如说 php 它可能会语法稍微有点繁琐,或者是它的框架跟我要用到的一些工具或者中间件不兼容,比如说可能你在写库用 ORM 的时候,php 有一些额外的安全限制之类的
但是像 go 语言反正我自己目前使用开发项目感受下来这方面限制是比较少,就相当于你学了它怎么用之后,你就可以专注于你自己项目和业务的开发,而不是去纠结于诶我这里遇到了某个问题应该怎么解决,或者是这里语法可能有点问题之类的,这是我自己的理解
Q:刚才你提到了 php 的一些安全机制,你接触过哪些?
A:我目前接触过的就是比如说我用那个 webman 框架,在我写,因为 php 它这个框架它用 ORM 是用那个 illuminate 的 eloquent 的 ORM,它是对于比如说我要写库,我想往库里写一个那种类似于数组一样的数据进去的话,它会有一个安全限制,就是它不能直接像 go 里面那样直接用 gORM 那样直接写一个类似于 SQL 的命令,它必须要求你在这个数组里面每一个字段你都要给上一个声明,就是你要去声明它是什么类型的,让这个 ORM 来识别出来它合不合法,来避免一些安全问题,但是它底层可能我没有了解
又是自己给自己挖坑,根本没想到面试官会问 php 的东西
Q:那 go 这样写的话听上去是不是会有隐患呢?
A:我觉得 go 它本身很多问题都是在,因为它的运行时很强大,很多问题都是运行时来帮助我们避免了某个问题的发生,就它的编译器可能会自己就是在编译的时候就避免了这个问题,就不需要我们再手动去写了
Q:诶刚刚你提到这种可能是跟 SQL 注入这种安全问题有关吧,有了解过 SQL 注入吗?
A:(在我把 MySQL 的安全问题搞清楚之前再也不会说安全相关的东西,,不仅这个没答上来还被一顿说教,说逻辑有问题什么的,把我上一个问题扯的东西全都否定了,我试图扯一下事务和并发相关的还被无视了)
Q:既然说到了 MySQL,MySQL 你之前有用过是吧,那你比如说你知道的 MySQL 跟性能有关的参数你知道一些什么呢?
A:跟性能有关的参数的是指?
Q:比如说你自己在安装 MySQL 的时候会去做哪些配置,比如说它的默认配置你会去关注哪些参数,你会去改哪些吗?
A:这个可能要根据实际业务来看吧,比如说并发场景的话,首先因为 MySQL 它自己有一个缓存池一样的东西嘛,它那个缓存池大小就是可以修改的,如果说不考虑走 redis 的话那可能这个缓存池参数是需要修改的(被打断)
Q:你这个缓存池是指什么?
A:MySQL 它本身是一个持久化类型的数据库,它是会把数据写到磁盘的,它相当于是两部分东西,一部分是存储引擎,另一部分是上层一些的东西类似于应用层的东西,比如说优化器或者是解释器选择器这种,然后缓存池就是在我这个上层的应用想要去调用下层的引擎里面的东西,因为读磁盘操作的时间开销可能比读内存会大很多,所以我想加快我的读取速度,那么 MySQL 就有这样一个内存池的机制,我可以缓存一部分数据,来加快我应用层上层的东西来读取原本数据的速度
Q:这块有遇到过什么性能方面的问题吗,用 MySQL 的时候
A:性能方面的问题主要还是它在高并发场景下面肯定不如 redis 嘛,读写速度啊或者优化器的选择之类的,就是你可能查表的时候如果遇到一个那种比较大的表然后字段比较复杂数据比较复杂什么的,然后如果你没有加索引或者索引加的不太好的话可能就是查询速度会有限制嘛,然后再加上如果你想要读写的话它肯定是没有 redis 快的
Q:有用过联合索引吗,就是多个字段建一个索引
A:有用过,也是要就是最左前缀嘛,要从左到右,然后你不能用范围索引,最好是以等号为主的,然后它有时候如果你用的不太好的话会失效
Q:那比如说你要在一张表上去加一个索引,这个会比较快吗,还是其实挺慢的,你有没有试过
A:这个也要看怎么加吧,看你选的字段怎么样,如果说你选的字段是那种比较常用的,也要看你加的索引类型,如果是比较容易被查到的字段,那你加个普通索引,可能就比较快一些,然后(被打断)
Q:我是说加索引的这个动作本身,不是说加索引的效果,相当于对表结构做变更嘛,我需要加一个索引
A:那如果是加索引本身也要考虑加索引的类型嘛,如果索引类型比较简单的话那加索引肯定就比较快,对表的结构变更也不会说开销特别大,但如果是要加那种特别复杂的索引,比如说联合索引你一长串字段下来的话,那可能开销就会比较大比较复杂,而且如果说表里面本身有很多那种冗余的索引用不到的索引,那可能索引这块存储本身也是一个开销,更何况读写这方面也是有一定开销
Q:假如说现在有一个表它现在需要加索引,它除了你刚刚提到那些字段多少,它加索引的耗时还跟哪些因素有关系?
A:加索引耗时应该跟比如说我这个表选用的存储引擎是哪一种,然后它底层存储机制是什么样的,以及我这个索引它本身的机制是什么样的,比如说它的存储结构方面如果是 B+ 树,然后可能会快一些,如果纯粹只是用 B 树可能就没有 B+ 树快,然后如果是用全文索引的就要看是针对字符串类型还是其他类型随便加的,然后其他的可能时间开销我目前可能还不太清楚
Q:嗯,跟硬件的哪些因素会有关系吗?
A:索引跟硬件相关可能就是会涉及到系统调用方面的一些 I/O 操作吗,这个方面我没有具体去了解过,但我推测的话,因为 MySQL 本身是持久化类型的数据库,所以我需要将数据写入到磁盘,那写入到磁盘就会涉及到 I/O 操作,那索引它又是为了加快我去读磁盘数据的,所以说它可能会跟这个加快我系统级调用或者是尽量减少 I/O 操作来跟硬件方面有一些关系,或者是说磁盘方面的硬件的结构化存储方面(被打断)
Q:比如说你加这个索引的时候你是在一台机器上加,机器它硬件有不同的规格,比如像你刚刚说的磁盘 I/O,如果它是高性能的固态硬盘,I/O 就快,那还有一些这个什么样的影响因素吗?
A:嗯硬件方面可能也跟比如说我的电脑我的服务器的处理器的性能如果说多核多线程可以并发请求的话这个索引的速度就会快一些,然后如果说硬件配置没那么好的话那速度可能就会相对慢一些
Q:我们再把这个场景具象一些,就是比如说现在有一个线上运行的服务,然后它有一个表结构,现在它要做这个表结构变更,可能是加索引,可能是加字段,那为了避免说这个表结构的变更动作对现有业务产生影响,或尽量减少影响,你觉得有什么样的这个准备工作或策略
A:我觉得首先最基础的就是先做备份嘛,然后可能有一个实时监控的告警之类的,然后如果说崩了什么的能够及时发现然后去调整,然后提前的预案的话因为这个表结构是要变更的嘛,我可以,如果说用了 redis,我可以先去把缓存给变更了,缓存变更好之后我再去变更库里面的,因为这样可以防止库里面有什么变更之后缓存还没有变更的话那可能用户对于库里面新变更的字段的请求打到缓存上面去却缓存失效的这种情况
然后另外的话因为是要变更表结构嘛,我可以把这个表先复制一份出来,我先去考虑一下我这个表结构的变更具体是要怎么变更,就是我是要修改某个字段,还是把这个表的结构包括索引那些大改一下,去考虑一下它跟其他字段之间互相的影响,然后因为是要涉及到迁移嘛,如果说它是一个大表的话,虽然这里只是改字段,但是如果是那种比较大的表然后业务涉及比较多的话,可以就是把这个表逐步地开放,就是做一个类似于那种灰度测试这种的,就是不要变更完之后一次性全部上线,同样也可以就是(被打断)
Q:诶那个表结构怎么逐步变更啊,它是一张表,它可以部分数据变部分数据不变吗?
A:不是我是说就是,大表不是数据很多吗,我是说变更之后数据是逐步开放,不要一次性全部开下来
Q:什么意思,什么叫不要一次性全部开下来
A:就是比如说我改完这个结构之后会有对应的数据写进来嘛,就是对外请求的时候我可以把这个表的服务不要一次性全部暴露到对外的生产环境上面,比如(被打断)
Q:那业务要部分停机吗?
A:不是啊,就是我这个假设说有多个环境的话,我可以先在测试环境上把这个表改好之后发到预发,看预发有没有问题,预发没有问题的话就上生产,就是我可以一步一步的,尽量不要我这个变更在没有测试的情况下直接全部跑到生产上去,尽量不要影响业务
Q:好,还有吗?
A:其次的话,因为我要修改一个表的结构,所以说可能还是索引方面的问题吧,我觉得要考虑一下这个新建的字段对其他的索引有没有影响,或者会不会影响我现有索引的效率之类的,它会不会导致我事务方面的一些问题,就是比如说我高并发同时多次请求这个字段的话,它会不会出现一些比较经典的脏读幻读这种问题
一个性能问题追问这么多真的被压力懵了完全不知道答啥只好胡说..
Q:刚刚你说了很多,那具体比如说我们在加这个索引或者做别的 DDL 的时候,我们对现有业务还可能带来什么样的风险呢?你已经提到两类风险,一个是这个表别给它搞坏了,那还有什么吗?
感觉是我没好好说,讲得太混乱
A:您是说单独变更表结构这个动作带来的风险是吗?(面试官说是)那风险的话可能,因为我这一张表可能会牵扯到其他张表,或者我这张表我做了分表,可能会有一个数据同步方面的问题,就是我要避免我在这一张表上面改了,但是在其他表上面没有改,或者是说我主表主要是负责写的,然后多个从表是负责读的,如果说我只是主表做了修改但我多个从表没有修改,多个从表又是读的话那可能就会带来比较大的这种数据库读写问题
Q:你说的从表是说有两个实例在做主从同步是吧,还是怎么样
A:嗯可以是多个实例做主从同步,也可以是我单独把一个表分出来,然后把一个大表分成多个小表,每个表可以存储不同的数据,但这种就不会涉及到主表读从表写,它们都只是用来读的嘛,它只是单独分数据的
Q:那如果是主从同步的场景,这种表结构变更也需要在多个实例中去重复做吗?
A:应该有那种自动化脚本吧,就是我主表变更之后,我先跑一个脚本,就是我去检测多个从节点它的结构跟我当前主节点的结构是不是一样的,如果不一样就把它变更一下
Q:主从同步的机制是什么样的?是哪些操作会同步哪些操作不会同步?
A:如果是比如说主表写从表读的话那主从同步可能主要是同步主表和从表之间的数据,比如我主表的数据可能分到多个不同的从表,或者是说干脆每个从表里都存一份一样的数据,那这个时候主从同步比较重要就是要同步主表和从表它表的结构以及具体的数据,然后如果是说比如说我对于某个数据的读,或者是比如说我某个从表里面某一个字段它被读得特别频繁特别热点的话,那我可能要在这个从表里面加这个索引,但如果在别的从表里这个数据却没有这种情况的话,那可能这个就是不需要去做同步的,嗯
Q:我说的不是同步策略,我说的是机制是什么样的,比如你说的主从同步是说我们要靠运维主动去做一个这样的数据同步的脚本还是说 MySQL 自己有一些同步的机制
A:MySQL 它的同步机制,感觉它本身并没有特别多的这种同步机制,感觉还是要靠脚本去做一些同步,就相当于你,就还是拿刚刚那个环境来说,你在测试上面跑了一遍之后要在预发上面再跑一遍然后这个生产上面再自己跑一遍这个脚本
MVCC 我都忘记说了我服了,这几个问题感觉自己一直都在胡言乱语
Q:刚刚你提到一个很有用的质量保证的措施就是做监控,比如说你来做监控的时候,你觉得我们应该监控哪些方面的指标?
A:监控指标的话首先最主要就是抛出异常嘛,这方面就是直接搞一个告警出来,还有一些指标的话就是比如说我加了缓存,那我的缓存命中率是多少,如果缓存命中率过低也要有对应的告警,我目前,因为一个服务框架下面可能会涉及到很多流量问题嘛,我可能需要去监测一下我目前高并发的实时流量是多少,看我的服务器能不能承担的住当前的流量,是有容余还是说比较紧张这种
其他指标的话更多就是那种服务监测方面的,比如说我要做并发或者长连接,那可能我要监测一下这个心跳,就我要去看对方有没有响应,如果没有响应就把这个异常抛出去看能不能及时解决这种
Q:我们先不说这些指标,我们先说就是你要监控的对象是哪些,因为一个正常运行的服务,它可能中间涉及到服务器、这个数据库实例本身,还可能涉及到别的一些比如说网关,那我们监控到底是监控谁,刚刚你说的抛异常是谁抛异常,哪个环节你觉得是最应该去监控的
A:您刚刚说的是数据库,网关还有什么来着?
Q:数据库网关和服务器,因为你是一整个对外的服务嘛,你不是说直接数据库拿出去用,我们监控也要分对象嘛,那监控的是哪个环节的东西
A:我觉得如果拿 go 来说的话主要是 go 方面的,因为它本身有很多框架是能够我直接去操作数据库或操作对外暴露的协议之类的,就像 go 它本身对于抛出异常也比较方便嘛,所以我觉得更多还是去监测 go 它自己的运行时抛出来的一些异常,而不是去监测它底层的一些东西
答得一塌糊涂啊啊啊啊啊,感觉就是被问到知识盲区之后不知所云了,下面是反问环节
Q:我了解得差不多了,你有什么想了解的吗
A:咱们部门目前的业务有哪一些,因为我之前有了解过咱们部门是基础设施部门
Q:基础设施部门听这个名字业务就不多嘛(笑),业务是在我们别的部门,你说的业务是经营上的业务还是指什么
A:就是有可能工作方面是做什么或者跟其他部门是什么关系这种
Q:就可能比较泛了,我们部门是人比较多,是分了很多组,分很多方向,比如偏运维的,偏基础设施建设的,业务中台或者技术安全,就比较多了
A:那您觉得就是如果我有幸能入职的话,您觉得我目前应该去学一些什么东西呢,还需要学一些什么呢
Q:你现在是大二是吧,27 年才毕业是吧,还挺早的,语言这块的东西我估计你应该是指令什么的都还有点熟了,因为我刚才聊,虽然聊的只是数据库,但是可能一些偏整个计算机体系方面的一些东西,因为你毕竟现在也就读了一年多书对吧,高中的时候有接触过计算机吗?
A:没怎么接触过
Q:可能一些偏基础的东西我感觉可能还是有一些那个,书本上面的你应该学了,就是网络啊,操作系统啊,但是可能在中间的那一段就是没有那么基础,但是又没有到上层实际写业务代码,就是中间这一段,比如说我们整个计算机常用的这些体系里面的一些东西,可能网络分层,包括像刚刚聊的这些数据库的同步机制什么的可以再去了解一下,但是也还好,毕竟你现在也才大二嘛对吧
反思总结
这场面下来最大的感受就是自己对于数据库方面的理解还是不够细致也不够深入,很多都是浮于表面的,然后可能很多东西自己也没有实操过,回答的时候也更多是从理论层面出发
而且因为自己这场答得实在是有点太烂了,导致疯狂被面试官打断,整体的面试体验也不是特别好,但现在来看感觉这种体验还是利大于弊的,因为更能发现自己究竟是在哪里如此薄弱,以至于影响了发挥
还是要把基础夯实才行,多说无益,多做才行
(但我五一玩得有点嗨哈哈哈,因为之前都是周末也不怎么休息的,就干脆给自己好好放了个假,光子那篇面经也在路上啦,然后可能这两篇面经都不会有过多反思总结的内容了,我是准备面经发完之后再把最近的情况一起整理总结一下,重新再发一篇规划相关的帖子)
继续加油~