ITPub博客

首页 > 数据库 > 数据库开发技术 > 有点意思,她腾讯一面就过了!

有点意思,她腾讯一面就过了!

原创 数据库开发技术 作者:皇子谈技术 时间:2024-03-25 18:06:23 0 删除 编辑

网址:https://itgogogo.cn

大家好,我是皇子。

腾讯 25 届暑假实习已经开展了快一个月了,有同学反馈,一面已经通过,有些即使挂了,也会被重新捞起来面试,看了下腾讯今年春招的技术类岗位挺多的,包括:软件开发、技术运营、安全技术等。

今天分享一位同学腾讯TEG(技术工程事业群)的暑假实习校招面经,她学得是Golang,发现很多面试官也都是C++/Golang技术栈的,不过除了编程语言,腾讯还考察了一些了很多计算机基础知识,这很符合腾讯对实习生的要求,基础必须要牢靠!


这次面经考察的内容,我帮大家罗列一下:

  • Golang:使用 Go 的优势、Slice 的扩容机制、GMP的调度流程
  • 计算机网络:计算机网络体系结构、IP 地址编码方式
  • Linux:孤儿进程、僵尸进程
  • Http:短连接与长连接、HTTPS 采用的加密方式
  • MySQL:MySQL的基本架构、SQL 的执行过程
  • 算法:合并两个有序数组、反转链表

Golang

使用 Go 的优势

  • Go 代码的设计是务实的。每个功能和语法决策都旨在让程序员的编码更轻松。
  • Golang 针对并发进行了优化,并且在规模上运行良好。
  • 由于单一的标准代码格式,Golang 通常被认为比其他语言更具可读性。
  • 自动垃圾收集明显比 Java 或 Python 更有效,因为它与程序同时执行。

Slice 的扩容机制

Go 1.18 之前

Go 中切片扩容的策略是这样的:

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

Go 1.18+

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

扩容前后的 Slice 是否相同

情况一

如果 slice 还有足够的容量,添加新元素时不会发生扩容,因此扩容前后的 slice 底层数组是相同的。在这种情况下,添加新元素只会改变 slice 的长度,而不会改变容量。

需要注意的是,如果 slice 的容量不足以容纳新元素,添加新元素时就会发生扩容,此时扩容前后的 slice 底层数组是不同的。因此,在使用 slice 时,我们应该尽可能地预估其容量,以避免不必要的扩容操作,提高程序的性能。

情况二

在 Go 语言中,当一个 slice 的容量不足以容纳更多的元素时,它就会自动扩容。这个过程中,Go 会创建一个新的底层数组,并将原有的元素复制到新的数组中。因此,扩容前后的 slice 底层数组是不同的。

具体来说,当一个 slice 的长度达到其容量时再向其添加元素时,Go 会按照以下步骤进行扩容:

  1. 扩容时创建一个新的底层数组
  2. 将原有数组中的元素复制到新的数组中。
  3. 将新的元素添加到新的数组中。
  4. 返回一个新的 slice,其底层数组为新创建的数组。

因此,扩容前后的 slice 底层数组是不同的,但是它们包含的元素是相同的。如果您需要比较两个 slice 是否相同,应该使用 Go 语言提的内置函数 reflect.DeepEqual() 进行比较。这个函数可以比较两个 slice 是否包含相同的元素,但是它不能比较两个 slice 的底层数组是否相同。

GMP的调度流程

  • G(Goroutine):我们所说的协程,为用户级的轻量级线程,每个 Goroutine 对象中的 sched 保存着其上下文信息。
  • M(Machine):对内核级线程的封装,数量对应真实的 CPU 数(真正干活的对象)。
  • P(Processor):即为 G 和 M 的调度对象,用来调度 G 和 M 之间的关联关系,其数量可通过 GOMAXPROCS()来设置,默认为核心数。

计算机网络

计算机网络体系结构

  • 应用层:为特定应用程序提供数据传输服务,例如 HTTP、DNS 等协议。数据单位为报文。

  • 表示层:数据压缩、加密以及数据描述,这使得应用程序不必关心在各台主机中数据内部格式不同的问题。

  • 会话层:建立及管理会话。

  • 传输层(运输层):为进程提供通用数据传输服务。由于应用层协议很多,定义通用的传输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。

  • 网络层:为主机提供数据传输服务。而传输层协议是为主机中的进程提供数据传输服务。网络层把传输层传递下来的报文段或者用户数据报封装成分组。

  • 数据链路层:网络层针对的还是主机之间的数据传输服务,而主机之间可以有很多链路,链路层协议就是为同一链路的主机提供数据传输服务。数据链路层把网络层传下来的分组封装成帧。

  • 物理层:考虑的是怎样在传输媒体上传输数据比特流,而不是指具体的传输媒体。物理层的作用是尽可能屏蔽传输媒体和通信手段的差异,使数据链路层感觉不到这些差异。

IP 地址编码方式

IP 地址的编址方式经历了三个历史阶段:

  • 分类

  • 子网划分

  • 无分类

1. 分类

由两部分组成,网络号和主机号,其中不同分类具有不同的网络号长度,并且是固定的。

IP 地址 ::= {< 网络号 >, < 主机号 >}

2. 子网划分

通过在主机号字段中拿一部分作为子网号,把两级 IP 地址划分为三级 IP 地址。

IP 地址 ::= {< 网络号 >, < 子网号 >, < 主机号 >}

要使用子网,必须配置子网掩码。一个 B 类地址的默认子网掩码为 255.255.0.0,如果 B 类地址的子网占两个比特,那么子网掩码为 11111111 11111111 11000000 00000000,也就是 255.255.192.0。

注意,外部网络看不到子网的存在。

3. 无分类

无分类,即无类别域间路由(Classless Inter-Domain Routing、CIDR)消除了传统 A 类、B 类和 C 类地址以及划分子网的概念,使用网络前缀和主机号来对 IP 地址进行编码,网络前缀的长度可以根据需要变化。

IP 地址 ::= {< 网络前缀号 >, < 主机号 >}

CIDR 的记法上采用在 IP 地址后面加上网络前缀长度的方法,例如 128.14.35.7/20 表示前 20 位为网络前缀。

CIDR 的地址掩码可以继续称为子网掩码,子网掩码首 1 长度为网络前缀的长度。

一个 CIDR 地址块中有很多地址,一个 CIDR 表示的网络就可以表示原来的很多个网络,并且在路由表中只需要一个路由就可以代替原来的多个路由,减少了路由表项的数量。把这种通过使用网络前缀来减少路由表项的方式称为路由聚合,也称为构成超网 。

在路由表中的项目由网络前缀和下一跳地址组成,在查找时可能会得到不止一个匹配结果,应当采用最长前缀匹配来确定应该匹配哪一个。

Linux

孤儿进程

一个父进程退出,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。

孤儿进程将被 init 进程(进程号为 1)所收养,并由 init 进程对它们完成状态收集工作。

由于孤儿进程会被 init 进程收养,所以孤儿进程不会对系统造成危害。

僵尸进程

一个子进程的进程描述符在子进程退出时不会释放,只有当父进程通过 wait() 或 waitpid() 获取了子进程信息后才会释放。如果子进程退出,而父进程并没有调用 wait() 或 waitpid(),那么子进程的进程描述符仍然保存在系统中,这种进程称之为僵尸进程。

僵尸进程通过 ps 命令显示出来的状态为 Z(zombie)。

系统所能使用的进程号是有限的,如果产生大量僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程。

要消灭系统中大量的僵尸进程,只需要将其父进程杀死,此时僵尸进程就会变成孤儿进程,从而被 init 进程所收养,这样 init 进程就会释放所有的僵尸进程所占有的资源,从而结束僵尸进程。

Http

短连接与长连接

当浏览器访问一个包含多张图片的 HTML 页面时,除了请求访问的 HTML 页面资源,还会请求图片资源。如果每进行一次 HTTP 通信就要新建一个 TCP 连接,那么开销会很大。

长连接只需要建立一次 TCP 连接就能进行多次 HTTP 通信。

从 HTTP/1.1 开始默认是长连接的,如果要断开连接,需要由客户端或者服务器端提出断开,使用 Connection : close;

在 HTTP/1.1 之前默认是短连接的,如果需要使用长连接,则使用 Connection : Keep-Alive。

HTTPS 采用的加密方式

HTTPS 的加密方式是采用混合的加密机制

  • 使用非对称密钥加密方式(一般是:RSA),传输对称密钥加密方式所需要的 Secret Key,从而保证安全性;
  • 获取到 Secret Key 后,再使用对称密钥加密方式进行通信,从而保证效率。(下图中的 Session Key 就是 Secret Key)

关于对称密钥加密

关于对称密钥加密,加密和解密使用同一密钥。

  • 优点:运算速度快;

  • 缺点:无法安全地将密钥传输给通信方。

关于非对称密钥加密

非对称密钥加密,又称公开密钥加密(Public-Key Encryption),加密和解密使用不同的密钥。

公开密钥所有人都可以获得,通信发送方获得接收方的公开密钥之后,就可以使用公开密钥进行加密,接收方收到通信内容后使用私有密钥解密。

非对称密钥除了用来加密,还可以用来进行签名。因为私有密钥(私钥)无法被其他人获取,因此通信发送方使用其私有密钥进行签名,通信接收方使用发送方的公开密钥(公钥)对签名进行解密,就能判断这个签名是否正确。

  • 优点:可以更安全地将公开密钥传输给通信发送方;
  • 缺点:运算速度慢。

MySQL

MySQL的基本架构

  • 客户端:最上层的服务并不是MySQL所独有的,大多数基于网络的客户端/服务器的工具或者服务都有类似的架构。比如连接处理、授权认证、安全等等。

  • Server层:大多数MySQL的核心服务功能都在这一层,包括查询解析、分析、优化、缓存以及所有的内置函数(例如,日期、时间、数学和加密函数),所有跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等。

  • 存储引擎层:第三层包含了存储引擎。存储引擎负责MySQL中数据的存储和提取。Server层通过API与存储引擎进行通信。这些接口屏蔽了不同存储引擎之间的差异,使得这些差异对上层的查询过程透明。

一条查询 SQL 的执行过程

1、先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限会先查询缓存(MySQL8.0 版本以前,MySQL8.0 版本之后去除大部分的查询缓存)。

2、如果没有缓存,解析器进行语法分析,提取 sql 语句中 select 等关键元素,然后判断 sql 语句是否有语法错误,比如关键词是否正确等等。

3、语法解析之后,MySQL的服务器会对查询的语句进行优化,确定执行的方案。

4、完成查询优化后,按照生成的执行计划调用数据库引擎接口,返回执行结果。

算法

  • 合并两个有序数组

  • 反转链表

推荐阅读

挺看好的一位阿里妹子,很上进

错过阿里,冲腾讯吧

小米有点意思,选择不躺平,冲!

我开源了一个工具!

关注公众号,后台发送【简历】,领取简历摸板

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

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

注册时间:2023-12-21

  • 博文量
    113
  • 访问量
    56524