【面经分享,附答案】字节 系统架构,二面凉经,后端,秋招提前批,22/07/18

2022-11-08 14:37:53 浏览数 (1)

本文收录于 www.cswiki.top

今日面经来源:https://www.nowcoder.com/discuss/985106

总结:问的很细,网络编程中间的好多 API 我只是粗略的了解过,答得不好,最后算法题做的也不好,虽然做出来了,但过程有点曲折,就很离谱,给个数组,要我自己建树,然后序列化,再输出数组。

小牛肉 PS:这个部门应该偏底层,基础知识深度不够的建议避雷

1)先是聊项目

2)Redis 跳表怎么设计实现

关键点:level[] 数组(forward 指针指向同一层的后继节点、span 跨度)、backward 指针(每个节点都带有一个高度为 1 层的 backward 指针,用于逆序处理的命令从表尾方向向表头方向迭代),所以 Redis 中的 skiplist 也是一个双端链表

3)Redis 的持久化(一面问过)

4)Redis 崩溃后怎么恢复数据,介绍下恢复的过程

因为 AOF 文件的更新频率通常比 RDB 文件的更新频率高,所以如果开启了 AOF,那么就用 AOF 进行恢复,否则用 RDB 进行恢复

  • RDB 载入过程:服务器启动时自动执行的,Redis 并没有提供专门用于加载 RDB 文件的命令,载入 RDB 文件的过程中 Redis 服务器被阻塞
  • AOF 载入过程:Redis 的命令只能在客户端上下文中执行,而载入 AOF 文件时所使用的命令直接来源于 AOF 文件而不是网络连接,所以服务器使用了一个没有网络连接的【伪客户端 fake client】来执行 AOF 文件保存的写命令,伪客户端执行命令的效果和带网络连接的客户端执行命令的效果完全一样

5)Redis 的字符串底层数据结构实现

三种实现:Long 型整数 REDIS_ENCODING_INT、压缩的 SDS REDIS_ENCODING_EMBSTR、SDS REDIS_ENCODING_RAW

6)Redis 怎么对字符串进行管理

问的应该就是 Redis 对于对象是怎么进行管理的吧。 Redis 中每个数据库都对应一个 redisDb 结构,其中有一个字典属性 dict,key 保存数据库中的键,每个键都是一个字符串对象,value 保存这个 key 对应的值,每个值可以是任意一种 Redis 对象

7)数据库的索引原理

8)TCP 的状态机,详细介绍

9)HTTP 1/2/3 介绍

HTTP 1.0:短连接 HTTP 1.1:长连接、管道机制(允许并发请求,不能并发响应,存在响应的队头阻塞问题) HTTP 2.0:采用二进制格式传输数据、数据流、多路复用(允许并发请求和并发响应)、头部压缩、支持服务端主动推送。但 HTTP2.0 存在 TCP 层面的队头阻塞问题 HTTP 3.0:HTTP2.0 由于 TCP导致了队头阻塞问题,所以 HTTP 3.0 直接弃用 TCP,采用基于 UDP 的 QUIC 协议

10)HTTP 和 HTTPS 的区别

HTTP 不安全,HTTPS 其实就是在 HTTP 的外面套了一层 SSL/TLS 协议的壳:

  • 可能被窃听(第三方可以获知通信内容):HTTPS 的方案 - 加密技术(对称加密、非对称加密、混合加密)
  • 可能遭遇伪装(第三方可以冒充他人身份参与通信):HTTPS 的方案 - 数字证书
  • 可能被篡改(第三方可以修改通信内容):HTTPS 的方案 - 数字签名(防止数字证书被篡改)

11)介绍下 SSL/TLS(上面提到了)

HTTPS 保证安全的机制其实就是 SSL/TLS 协议干的事,基本过程是:

  • 客户端向服务器端索要并验证服务端的公钥(这其中就涉及数字证书/数字签名的传递)
  • 双方协商生成 "对称密钥"
  • 双方采用"对称密钥"进行加密通信。

上面过程的前两步,又称为 "握手阶段"(handshake)。握手阶段结束后客户端与服务器就进入加密通信,就完全是使用普通的 HTTP 协议,只不过用"对称密钥"加密内容。 如果熟悉的话可以再详细介绍下 SSL/TLS 的四次握手过程

12)接触过网络编程吗,介绍下

Socket 编程,其实就是把 TCP 协议的细节封装成一个一个的 API 了,调用 socket 函数创建 Sokcet,调用 bind 函数绑定 IP 地址和端口,服务端调用 listen 监听端口,进入了监听状态后,通过调用 accept()函数,来获取客户端的连接,如果没有客户端连接,则会阻塞等待客户端连接的到来;客户端调用 connect 请求建立连接。 连接建立后,客户端和服务端就开始相互传输数据了,双方都可以通过 read()write() 函数来读写数据。

13)select,poll,epoll 介绍下

select:基于数组(长度受限于 FD_SETSIZE = 1024);涉及两次用户态和内核态的切换 两次拷贝;时间复杂度 O(N),并发连接越多性能越低 poll:基于链表;突破了 select 的长度限制,但本质上没有区别 epoll:基于红黑树(只存储待检测的 Socket 文件描述符) 链表(存储已经就绪的 Socket 文件描述符);两种事件触发模式:边缘触发 水平触发

14)你提到了 select 有长度限制,那长度超过了怎么办,为什么会限制成 1024 个

不知道对不对,长度超过了即数组越界

15)IO 多路复用介绍下

关键点:同步;IO 的两个阶段都是阻塞的;优势不在于处理单个连接可以更快,而在于可以同时监听多个连接

16)介绍下红黑树,插入过程说一下呢

17)以 TCP 连接过程为例,介绍下 Socket 编程过程中用到的 API(同上 11 题)

18)三次握手发生在哪个 API 调用的阶段(具体哪两个 API 之间发生三次握手)

TCP 三次握手发生在客户端 connect 和服务端 accept 两个 API 之间

19)介绍下拥塞控制算法

慢启动、拥塞避免、快重传和快恢复

20)基于什么样的场景判断发生拥塞了

所谓拥塞:对网络中某一资源的需求超过了该资源所能提供的可用部分(即需 > 供),网络的性能变差 只要发送方没有在规定时间内接收到 ACK 应答报文,也就是触发了重传机制(超时重传 or 快速重传),就会认为网络出现了拥塞

21)为什么要用三个连续重复确认是发生轻微拥塞(上面提到了)

因为网络包有时会乱序,乱序的包一样会触发重复的 ACK,但是为了乱序而重传没有必要(会按照 seq 进行重组)。由于一般乱序的距离不会相差太大,比如 2 号包也许会跑到 4 号包后面,但不太可能跑到 6 号包后面,所以限定成 3 个或以上可以在很大程度上避免因乱序而触发快速重传

22)udp 了解吗,说下 udp 和 tcp 的区别

23)从 udp 和 tcp 的数据包头来说下区别呢

TCP 首部包含可选项,所以总体长度可变,但包含 20 字节的固定部分(和 IP 首部一样);UDP 首部只有 8 字节(源端口、目的端口、源 IP 地址、目的 IP 地址)

24)操作系统的进程和线程,从底层分析下区别

25)进程间的通信方式

管道、消息队列、共享内存、信号量和 PV 机制、信号、Socket

26)管道通信说一下

只能单向通信;匿名管道和有名管道;本质是把对管道文件的操作映射为对内核中的缓冲区的操作;效率较低,不适用于频繁的通信

27)消息队列,说一下你的了解

消息队列的本质就是内核存放在内存中的消息的链表,而消息本质上是用户自定义的数据结构,如果进程从消息队列中读取了某个消息,这个消息就会被从消息队列中删除;数据量较大会造成频繁的系统调用

28)posix 详细说说

29)共享内存说下呢,期间会用到哪些具体的 linux api 呢

共享内存就是将不同进程的虚拟地址空间中的某段地址指向同一段物理内存地址,使得这些进程可以访问同一个物理内存,这个物理内存就成为共享内存

30)Linux 的死锁说下,怎么解决死锁

31)算法题 :二叉树的序列化和反序列化

虽然是个很常见的 hard,但是我感觉一般面试出个 hard 大概率就是前面答得不好

长风破浪会有时,我是小牛肉,小伙伴们下篇文章再见

0 人点赞