ITPub博客

首页 > 数据库 > 数据库开发技术 > 上市公司,面试过了但测评卡住,有点懵逼

上市公司,面试过了但测评卡住,有点懵逼

原创 数据库开发技术 作者:皇子谈技术 时间:2024-08-01 11:54:15 0 删除 编辑

测评都能卡住了,是万万没想到的

大家好,我是皇子。

今天分享一个上市公司社招后端Golang开发工程师的艰难历程。

走的内推渠道进入了该公司的社招面试流程,但简历筛选通过后,很快收到了HR的邮件。

以为是面试邀请邮件这么简单,但是想多了,毕竟是上市公司,流程那是一套一套的标准化。

共收到了三封邮件,第一封是视频面试邀请;一封是社招自适应能力测评,实际上是自适应cate测评,另外一封是价值观测评。

这两封邮件对应的是两个流程,一边是面试,一边是测评,测评包括:cata测评和价值观测评(没有对错)。

两个流程同步进行,任意流程不通过,则另外一个流程中断,等待确认。


而这位同学呢,对于自适应cata测评也是一无所知,后来咨询我了之后,这部分是顺利通过了。

但是另外一个价值观测评虽然没有对与错,但是第一波面试的时候却被面试官告知:cata 测评分数挺高的,但是价值观分数有点低,应该问题不大,到时候说明情况就OK了,我们继续面试。


听这位同学讲述,面试官还挺Nice的,这种情况下没有为难他,而是让他继续面试,他也认真的对待努力表现自己的经验和优势。

第二天果然面试通过了,并安排了下一轮的视频面试。

在第二波面试中,他才知道因为价值观测评这事,第一波面试官已经帮他申请走了内部特批流程,他也没放在心上,然后面试过程中也正常发挥着。


没想到,两天后,该同学跟跟内推的那位朋友资讯第二波进展情况,结果尴尬的一幕发生了,这同学也是懵逼了。

“第二轮面试也通过了,但是因为价值观测评分数这事在走内部特批流程还没下来,没办法让你继续后面流程”

说来也神奇,说好的价值观测评没有对错,只为匹配更适合的职业发展路径,但是流程竟然因为这个卡住了,估计是某些方面跟在招聘的能力确实不太匹配,毕竟到了今天这位同学还没有收到通知。


这么尴尬的局面,只能再等等了,祝好运~

我们也开始分享这位上市公司社招后端Golang开发工程师的面经。

除了深挖项目部分,其他的总体难度不大。

网络

OSI参考模型

  • 应用层:为特定应用程序提供数据传输服务,例如 HTTP、DNS 等协议。数据单位为报文。
  • 表示层:数据压缩、加密以及数据描述,这使得应用程序不必关心在各台主机中数据内部格式不同的问题。
  • 会话层:建立及管理会话。
  • 传输层(运输层):为进程提供通用数据传输服务。由于应用层协议很多,定义通用的传输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。
  • 网络层:为主机提供数据传输服务。而传输层协议是为主机中的进程提供数据传输服务。网络层把传输层传递下来的报文段或者用户数据报封装成分组。
  • 数据链路层:网络层针对的还是主机之间的数据传输服务,而主机之间可以有很多链路,链路层协议就是为同一链路的主机提供数据传输服务。数据链路层把网络层传下来的分组封装成帧。
  • 物理层:考虑的是怎样在传输媒体上传输数据比特流,而不是指具体的传输媒体。物理层的作用是尽可能屏蔽传输媒体和通信手段的差异,使数据链路层感觉不到这些差异。

五层协议没有表示层和会话层,而是将这些功能留给应用程序开发者处理。

TCP/IP 协议:它只有四层,相当于五层协议中数据链路层和物理层合并为网络接口层。

TCP/IP 体系结构不严格遵循 OSI 分层概念,应用层可能会直接使用 IP 层或者网络接口层。

Golang

如何在运行时检查变量类型?

类型开关(Type Switch)是在运行时检查变量类型的最佳方式。类型开关按类型而不是值来评估变量。

每个 Switch 至少包含一个 case 用作条件语句,如果没有一个 case 为真,则执行 default。

new和make的作用

new 创建一个该类型的实例,并且返回指向该实例的指针。new 函数是内建函数,函数定义:func new(Type) *Type

注意:

  • 传递给 new 函数的是一个类型,而不是一个值
  • 使用 new 函数来分配空间
  • 返回值是指向这个新分配的地址的指针

make 的作用是为 slice, map or chan 的初始化,然后返回引用。

make 函数是内建函数,函数定义:func make(Type, size IntegerType) Type

make(T, args)函数的目的和 new(T)不同,make仅仅用于创建 slice, map, channel 而且返回类型是实例。

defer 的作用和特点是什么?

defer 的作用

当定义 defer 语句时,跟在 defer 后面的函数会被延迟执行。直到包含该 defer 语句的函数执行完毕时,defer 后的函数才会被执行,不论包含 defer 语句的函数是通过 return 正常结束,还是由于 panic 导致的异常结束,defer 后的函数都会执行。

defer 的执行顺序

只需要在调用普通函数或方法前加上关键字 defer,就完成了 defer 所需要的语法。可以在一个函数中执行多条 defer 语句,它们的执行顺序与声明顺序相反。

defer 的常用场景

  • defer 语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁。
  • 通过 defer 机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放。
  • 释放资源的 defer 应该直接跟在请求资源的语句后。

Slice 的底层实现

  • 切片是基于数组实现的,本身并不是动态数组或者数组指针
  • 切片内部实现的数据结构(指向底层数组的指针、切片的长度、切片的容量)通过指针引用底层数组,设定相关属性将数据读写操作限定在指定的区域内
  • 切片本身本身非常小不拥有任何数据,只是对现有数组的引用,可以理解为对底层数组的抽象
  • 因为基于数组实现,所以它的底层的内存是连续分配的,效率非常高,还可以通过索引获得数据。

Slice 的扩容机制,有什么注意点?

Go1.18之前 Go 中切片扩容的策略是这样的:

  • 首先判断,如果新申请容量大于 2 倍的旧容量,最终容量就是新申请的容量
  • 否则判断,如果旧切片的长度小于 1024,则最终容量就是旧容量的两倍
  • 否则判断,如果旧切片长度大于等于 1024,则最终容量从旧容量开始循环增加原来的 1/4, 直到最终容量大于等于新申请的容量
  • 如果最终容量计算值溢出,则最终容量就是新申请容量

Go1.18开始内置函数Append对切片的扩容算法发生变化:和Go 1.17以1024作为大小分界不同,Go 1.18使用256作为threshold

GMP 调度过程中存在哪些阻塞

  • I/O(文件/网络)
  • block on syscall
  • select{}
  • channel
  • 等待锁
  • runtime.Gosched()

MySQL

MySQL中 in 和 exist 的区别?

MySQL中的in语句是把外表和内表作hash 连接,而exist语句是对外表作loop循环,每次loop循环再对内表进行查询。

我们可能认为exists比in语句的效率要高,这种说法其实是不准确的,要区分情景:

  • 如果查询的两个表大小相当,那么用in和exists差别不大。

  • 如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in。

  • not in 和not exist:如果查询语句使用了not in,那么内外表都进行全表扫描,没有用到索引;而not exist的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。

MySQL的基本架构

  • 客户端:最上层的服务并不是MySQL所独有的,大多数基于网络的客户端/服务器的工具或者服务都有类似的架构。比如连接处理、授权认证、安全等等。
  • Server层:大多数MySQL的核心服务功能都在这一层,包括查询解析、分析、优化、缓存以及所有的内置函数(例如,日期、时间、数学和加密函数),所有跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等。
  • 存储引擎层:第三层包含了存储引擎。存储引擎负责MySQL中数据的存储和提取。Server层通过API与存储引擎进行通信。这些接口屏蔽了不同存储引擎之间的差异,使得这些差异对上层的查询过程透明。

MySQL索引的数据结构

MySQL的默认存储引擎是InnoDB,它采用的是B+树结构的索引。

B+树:只有叶子节点才会存储数据,非叶子节点只存储键值。叶子节点之间使用双向指针连接,最底层的叶子节点形成了一个双向有序链表。

在这张图里,有两个重点:

  • 最外面的方块,的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(粉色所示)和指针(黄色/灰色所示),如根节点磁盘包含数据项(左开右闭)17和35,包含指针P1、P2、P3,P1表示小于等于17的磁盘块,P2表示在大于17和小于等于35之间的磁盘块,P3表示大于35的磁盘块。真实的数据存在于叶子节点即3、4、5……、65。非叶子节点不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。
  • 叶子节点之间使用双向指针连接,最底层的叶子节点形成了一个双向有序链表,可以进行范围查询。

回表了解吗?

在InnoDB存储引擎里,利用辅助索引查询,先通过辅助索引找到主键索引的键值,再通过主键值查出主键索引里面没有符合要求的数据,它比基于主键索引的查询多扫描了一棵索引树,这个过程就叫回表。

索引失效的场景

  • 在索引列上使用mysql的内置函数,索引失效。
  • 对索引列运算(如,+、-、*、/),索引失效。
  • 索引字段上使用(!= 或者 < >,not in)时,可能会导致索引失效。
  • 索引字段上使用is null, is not null,可能导致索引失效。字段为空是可以走索引的,但是部分场景可能会失效,字段尽量设置为非null然后设置默认值
  • 如果字段类型是字符串,where时一定用引号括起来,否则会因为隐式类型转换,索引失效
  • like通配符可能导致索引失效。最左前缀不仅仅适用于组合索引,还适用于varchar的like语句,但是要注意,只有like "XXX%"的情况走索引,like "%XXX"和like "%XXX%"是不走索引的。
  • 查询条件包含or或者in,可能导致索引失效。具体是由MySQL优化器内部决定是全表扫描还是索引查找,用效率较高的一种方式。
  • 联合索引,查询时的条件列不是联合索引中的第一个列,索引失效。
  • 左连接查询或者右连接查询查询关联的字段编码格式不一样,可能导致索引失效。
  • MySQL优化器估计使用全表扫描要比使用索引快,则不使用索引:MySQL优化器内部就是找到一个索引扫描行数最少的方案去执行语句。那么扫描行数怎么来判断的?是逐行统计数据表的数据吗?其实并不是,而是根据统计信息来预估的值,这个统计信息就是我们常说的索引的“区分度”。

建议:在使用前最好还是先用 explain 来试试到底sql语句走不走索引,然后选择较优的sql。

Redis

什么是缓存穿透问题?

先来看一个常见的缓存使用方式:读请求来了,先查下缓存,缓存有值命中,就直接返回;缓存没命中,就去查数据库,然后把数据库的值更新到缓存,再返回。

缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。

通俗点说,读请求访问时,缓存和数据库都没有某个值,这样就会导致每次对这个值的查询请求都会穿透到数据库,这就是缓存穿透。

缓存穿透一般都是这几种情况产生的:

业务不合理的设计,比如大多数用户都没开守护,但是你的每个请求都去缓存,查询某个userid查询有没有守护。

业务/运维/开发失误的操作,比如缓存和数据库的数据都被误删除了。

黑客非法请求攻击,比如黑客故意捏造大量非法请求,以读取不存在的业务数据。

如何避免缓存穿透呢?一般有三种方法

1.如果是非法请求,我们在API入口,对参数进行校验,过滤非法值。

2.如果查询数据库为空,我们可以给缓存设置个空值,或者默认值。但是如有有写请求进来的话,需要更新缓存哈,以保证缓存一致性,同时,最后给缓存设置适当的过期时间。(业务上比较常用,简单有效)

3.使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。

布隆过滤器(BloomFilter)是一种数据结构。

特点是存在性检测:

  • 如果布隆过滤器中不存在,那么实际数据一定不存在;
  • 如果布隆过滤器中存在,实际数据不一定存在。

相比于传统数据结构(如:List、Set、Map等)来说,它更高效,占用空间更少。缺点是它对于存在的判断是具有概率性。

什么是缓存雪奔问题?

缓存雪奔:指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至down机。

产生的原因:缓存雪奔一般是由于大量数据同时过期造成的

解决:

可通过均匀设置过期时间解决,即让过期时间相对离散一点。如采用一个较大固定值+一个较小的随机值,5小时+0到1800秒酱紫。

Redis 故障宕机也可能引起缓存雪奔。这就需要构造Redis高可用集群啦。

什么是缓存击穿问题?

缓存击穿:指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。

缓存击穿与缓存雪崩的区别:看着有些像但其实是有区别的,缓存雪奔是指数据库收到大量的请求,造成压力过大甚至down机;缓存击穿只是大量并发请求到了DB数据库层面。可以认为击穿是缓存雪奔的一个子集吧。有些文章认为它俩区别,是区别在于击穿针对某一热点key缓存,雪奔则是很多key。

解决方案就有两种:

  1. 使用互斥锁方案。缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(Redis的setnx)去操作,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存。
  2. “永不过期”,是指没有设置过期时间,或者是热点数据快要过期时,通过定时任务去更新和设置过期时间。

项目

考察点:性能指标的理解、执行性能测试的工具与方法、性能瓶颈的判断等

常用的性能指标

响应时间(Response Time):衡量系统或服务处理请求并返回响应的速度。对于用户来说,这是直接影响体验的重要指标。响应时间应根据业务场景设定合理阈值,如对于网页加载期望在2-3秒内完成。

吞吐量(Throughput):单位时间内系统能够处理的请求数量或事务数量,如TPS(Transactions Per Second)或QPS(Queries Per Second)。吞吐量的设定应基于系统设计容量和预期用户量来确定。

TPS(Transactions Per  Second):即每秒事务数,是衡量系统处理事务能力的一个关键性能指标,广泛应用于数据库、支付系统、电子商务平台等需要处理复杂业务逻辑的应用场景。TPS强调的是“事务”这一概念,每个事务可能包含一个或多个操作,完成一定的业务逻辑,而不仅仅是一个简单的查询或请求。

QPS(Queries Per Second):即每秒查询率,是衡量系统处理能力的一个重要性能指标,尤其是对于那些以处理大量查询请求为主要任务的服务,如数据库、搜索引擎、API服务器等。QPS表示服务器在一秒内可以处理的查询请求的数量。

并发用户数(Concurrency):系统同时处理的用户请求的数量,反映了系统的并发处理能力。设定时需考虑高峰时段的用户访问模式和系统承受的最大并发压力。

资源利用率(Resource Utilization):包括CPU使用率、内存使用率、磁盘I/O、网络带宽等,用于评估系统资源的使用效率和是否存在瓶颈。合理区间依硬件配置和应用需求而定,避免长时间满载导致性能下降或不稳定。

如何计算QPS

计算QPS的基本公式是:

QPS = 总请求数时间周期(秒)QPS / 时间周期(秒)总请求数

然而,实际计算中可能会根据不同的上下文和可用数据采用不同的变体,以下是几种常见的计算方式:

  • 基于直接观测:如果可以通过工具直接观测到一段时间内的总请求数,可以直接使用上述公式计算QPS。
  • 基于并发量和平均响应时间:

QPS=并发量平均响应时间QPS=平均响应时间并发量

这里并发量指的是系统同时处理的请求数量,平均响应时间是从请求发出到接收到响应的平均时间

  • 估算峰值QPS:

当需要预估系统的峰值处理能力时,可能会使用二八原则来估算峰值时间的请求量,然后除以该时间段的秒数得到QPS。

峰值时间QPS=总PV数×80%(每天秒数×20%)峰值时间QPS=(每天秒数×20%)总PV数×80%

你是如何进行性能测试的?

测试工具:这里分享我们个人可以免费、快速使用的工具

  • Apache JMeter:开源工具;支持多种协议;可以模拟多用户并发访问,进行负载和压力测试;提供图形界面和强大的结果分析功能。
  • **ab (ApacheBench)**:ab是Apache HTTP服务器附带的一个命令行工具,简单易用,直接从命令行运行,无需复杂的配置;能够生成基本的性能报告,包括吞吐量、请求时间等指标;对客户端资源要求低,但能给目标服务器带来高负载;和基础的HTTP(S)协议测试,对于更复杂的测试场景可能功能有限。
  • wrk:wrk是一个现代的、轻量级的性能测试工具,特别适合做HTTP基准测试;它使用Lua脚本进行配置,提供了更高的灵活性和定制性;相比ab,wrk通常能提供更高的并发连接数,适用于大规模并发测试。

考虑高性能的需从哪入手?

负载均衡:

  • 配置负载均衡器,如Nginx、HAProxy或云服务商提供的负载均衡服务,确保请求均匀分配。
  • 实施动态负载均衡策略,根据服务实例的实时负载自动调整流量分配。

缓存策略:

  • 利用缓存技术(如Redis、Memcached)减少数据库访问,加速热点数据访问。
  • 设计合理的缓存更新策略,确保数据一致性。

数据库优化:

  • 选择合适的数据库类型(关系型、NoSQL等)并进行适当的数据分片、分区。
  • 优化SQL查询,建立索引,减少JOIN操作,使用读写分离和数据复制提高性能。

异步处理与消息队列:

  • 使用消息队列(如RabbitMQ、Kafka)实现任务异步处理,减轻主流程负担,提高响应速度。
  • 适用于邮件发送、数据分析等非即时反馈任务。

以上,觉得有用点亮【赞与在看】让我们心中充满力量、披荆斩棘、挑战自我。

推荐阅读

2024年最新,被卷到“准下岗”的9种编程语言,哪些你还在用?

苦等3天阿里巴巴,终于收到通知了

三面无手撕,怀疑这是字节吗?


关于作者:一位热爱技术,并在职场与自媒体间探索的实践者,希望通过分享个人经验和见解,帮助更多人实现自我成长和价值。

如果您对我的公众号内容感兴趣,欢迎关注我。

也可以在下方添加我微信和一支烟花AI社区技术群,一起交流技术、职场心得。

原文作者:皇子谈技术;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2023-12-21

  • 博文量
    113
  • 访问量
    56511