【面经】百度C++/Go开发岗一面面经

一 TCP三次握手和四次挥手

三次握手机制:

  • 第一次握手:客户端请求建立连接,向服务端发送一个同步报文(SYN=1),同时选择一个随机数 seq = x 作为初始序列号,并进入SYN_SENT状态,等待服务器确认。

  • 第二次握手:服务端收到连接请求报文后,如果同意建立连接,则向客户端发送同步确认报文(SYN=1,ACK=1),确认号为 ack = x + 1,同时选择一个随机数 seq = y 作为初始序列号,此时服务器进入SYN_RECV状态。

  • 第三次握手:客户端收到服务端的确认后,向服务端发送一个确认报文(ACK=1),确认号为 ack = y + 1,序列号为 seq = x + 1,客户端和服务器进入ESTABLISHED状态,完成三次握手。

四次挥手机制:

  • 第一次挥手:客户端向服务端发送连接释放报文(FIN=1,ACK=1),主动关闭连接,同时等待服务端的确认。

    • 序列号 seq = u,即客户端上次发送的报文的最后一个字节的序号 + 1

    • 确认号 ack = k, 即服务端上次发送的报文的最后一个字节的序号 + 1

  • 第二次挥手:服务端收到连接释放报文后,立即发出确认报文(ACK=1),序列号 seq = k,确认号 ack = u + 1。这时 TCP 连接处于半关闭状态,即客户端到服务端的连接已经释放了,但是服务端到客户端的连接还未释放。这表示客户端已经没有数据发送了,但是服务端可能还要给客户端发送数据。

  • 第三次挥手:服务端向客户端发送连接释放报文(FIN=1,ACK=1),主动关闭连接,同时等待 A 的确认。

    • 序列号 seq = w,即服务端上次发送的报文的最后一个字节的序号 + 1。

    • 确认号 ack = u + 1,与第二次挥手相同,因为这段时间客户端没有发送数据

  • 第四次挥手:客户端收到服务端的连接释放报文后,立即发出确认报文(ACK=1),序列号 seq = u + 1,确认号为 ack = w + 1。此时,客户端就进入了 TIME-WAIT 状态。注意此时客户端到 TCP 连接还没有释放,必须经过 2*MSL(最长报文段寿命)的时间后,才进入 CLOSED 状态。而服务端只要收到客户端发出的确认,就立即进入 CLOSED 状态。可以看到,服务端结束 TCP 连接的时间要比客户端早一些。

二 HTTP1.0、1.1、2.0的区别

HTTP1.0和HTTP1.1的区别:

  • 长连接:HTTP 1.1支持长连接(Persistent Connection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

  • 缓存处理:在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略,可供选择的缓存头来控制缓存策略。

  • 带宽优化及网络连接的使用:HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。

  • 错误通知的管理:在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。

  • Host头处理:在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。 

HTTP1.1和 HTTP2.0的区别:

  • 新的二进制格式:HTTP1.1的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。

  • 多路复用,即连接共享,即每一个request都是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。

  • 头部压缩,HTTP1.1的头部(header)带有大量信息,而且每次都要重复发送;HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。

  • 服务端推送:服务器除了对最初请求的响应外,服务器还可以额外的向客户端推送资源,而无需客户端明确的请求。

三 MVCC的作用以及如何实现

MVCC即多版本并发控制。MVCC 是通过保存数据在某个时间点的快照来实现的,根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。

实现原理可以概括为InnoDB每一行数据都有一个隐藏的回滚指针,用于指向该行修改前的最后一个历史版本,这个历史版本存放在 undo log 中。如果要执行更新操作,会将原记录放入 undo log 中,并通过隐藏的回滚指针指向 undo log 中的原记录。其它事务此时需要查询时,就是查询 undo log 中这行数据的最后一个历史版本。

MVCC 最大的好处是读不加锁,读写不冲突,极大地增加了 MySQL 的并发性。通过 MVCC,保证了事务 ACID 中的 I(隔离性)特性。

四 MySQL底层数据结构是什么

B+Tree。

五 InnoDB和MyISAM的区别是什么

  • InnoDB 支持事务,MyISAM 不支持

  • InnoDB 支持外键,而 MyISAM 不支持

  • InnoDB 是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高;MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针,主键索引和辅助索引是独立的。

  • Innodb 不支持全文索引,而 MyISAM 支持全文索引,查询效率上 MyISAM 要高;

  • InnoDB 不保存表的具体行数,MyISAM 用一个变量保存了整个表的行数。

  • MyISAM 采用表级锁(table-level locking);InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。

六 列举一些常用的Linux指令

1.文件和目录操作

ls:列出当前目录中的文件和子目录。

pwd:显示当前工作目录的路径。

cd:切换工作目录,例如cd /path/to/directory。

mkdir:创建新目录,如mkdir directory_name。

rmdir:删除空目录,如rmdir directory_name。

rm:删除文件或目录,如rm file_name或rm -r directory_name。

cp:复制文件或目录,支持递归复制,如cp source_file destination或cp -r source_directory destination。

mv:移动或重命名文件或目录,如mv old_name new_name。

touch:创建空文件或更新文件的时间戳,如touch file_name。

2.文本处理和编辑

cat:连接和显示文件内容,如cat file_name。

more/less:逐页显示文本文件内容,如more file_name或less file_name。

head/tail:显示文件的前几行或后几行,如head -n 10 file_name或tail -n 20 file_name。

grep:在文件中搜索指定文本,如grep search_term file_name。

sed:流编辑器,用于文本处理和替换,如sed 's/old_text/new_text/' file_name。

awk:文本处理工具,用于文本处理和数据提取,如awk '{print $1}' file_name。

3.文件查找和压缩

find:在文件系统中查找文件和目录,如find /path/to/search -name "file_pattern"。

mount/umount:挂载和卸载文件系统,如mount /dev/sdX1 /mnt和umount /mnt。

tar:用于文件归档和压缩,如tar -czvf archive_name.tar.gz directory_to_archive。

七 工厂模式的优点

解耦:工厂模式实现了创建者和调用者之间的解耦。调用者只需要知道产品的抽象类型,而不需要知道具体的实现细节,这有助于降低系统的耦合度,提高系统的可扩展性和可维护性。

封装性:工厂模式将对象的创建过程封装在工厂类中,客户端不需要知道对象创建的细节,只需要通过工厂类来获取所需的对象。这种封装性有助于隐藏复杂性和变化点,使得系统更加模块化。

灵活性:工厂模式支持增加新的产品类而无需修改现有代码,只需要扩展工厂类,增加相应的产品创建逻辑即可。这种灵活性使得系统能够轻松应对变化,符合开闭原则(对扩展开放,对修改关闭)。

易于测试:由于工厂类封装了对象的创建逻辑,因此可以轻松地通过修改工厂类的实现来切换不同的产品实现,从而方便地进行单元测试或集成测试。

符合单一职责原则:工厂模式将对象的创建职责交给专门的工厂类,这有助于遵循单一职责原则,即一个类应该只负责一项职责。

支持产品族:在工厂方法模式中,可以通过定义不同的工厂类来创建一系列相互关联或相互依赖的产品对象,这些产品对象构成了一个产品族。这有助于在系统中创建一系列相互关联的对象,而无需指定它们具体的类。

隐藏类的实例:客户端不需要知道具体的产品类,只需要知道产品接口,这有助于隐藏类的实例,使得系统更加灵活和可扩展。

八 简单聊聊消息队列

消息队列(Message Queue,简称MQ)是一种常用的中间件技术,用于在分布式系统中实现消息的异步传递和存储。它基于“先进先出”(FIFO)的数据结构,通过生产者、消息队列和消费者三个主要部分来实现消息的传递和处理。主要包括:

  • 生产者:负责产生消息,并将消息发送到消息队列中。生产者可以根据自身的处理能力来发送消息,无需考虑消费者的处理速度。
  • 消息队列:负责存储消息并管理消息的传递。它通常由消息持久化存储和消息传递两个主要组件构成,保证消息的可靠存储和有序传递。
  • 消费者:从消息队列中获取消息,并进行处理。消费者可以根据自身的处理能力来选择消费消息的速率,可以从指定队列拉取消息,或者订阅相应的队列,由MQ服务端推送消息。

消息队列降低了系统各组件之间的耦合度,且生产者发送消息后无需等待消费者处理完成,可以继续执行其他任务,提高了系统的并发处理能力,提供消息的持久化存储和重试机制,确保消息能够可靠地传递和处理。此外,消息队列可以通过增加消费者数量轻松地扩展系统的处理能力,而无需修改生产者的代码,具有很强的扩展性。广泛应用于异步处理、系统解耦、流量削峰等场景。

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值