7天八股速记之C++后端——Day 3

坚持7天,短期内快速完成C++后端面试突击。每天10题,弥补后端八股知识缺漏,熟练掌握后端的高频考点,后端面试更有把握。

1. 加问:TCP 在四次挥手的过程中为什么客户端最后还要等待 2MSL(Maximum Segment Lifetime)

在TCP的四次挥手过程中,客户端最后要等待2MSL(Maximum Segment Lifetime,最大报文生存时间)的时间主要是为了确保客户端发送的最后一个ACK报文段能够在网络中被正确接收,以防止可能导致连接异常关闭或者重复连接的情况发生

  1. 保证网络中的所有报文段被丢弃

    • 等待2MSL的时间可以确保在网络中的所有旧的数据报文段都被丢弃,避免这些旧的数据报文段对新连接产生干扰或者混淆。
  2. 防止旧连接的报文段对新连接的影响

    • 如果客户端立即关闭连接并重新启动新连接,而网络中仍有旧连接的报文段残留,可能会导致这些旧报文段被误认为是新连接的报文段,从而引发连接异常或者数据混淆的情况。
  3. 防止重复连接

    • 等待2MSL的时间可以确保之前的连接已经完全关闭,并且网络中的所有相关状态已经被清理,以避免客户端尝试重新建立与同一服务器的连接时发生重复连接的情况。

2. TCP 长连接和短连接有什么区别?

  1. 长连接(长连接)

    • 长连接是指在客户端和服务器之间建立的TCP连接在一段时间内保持打开状态,可以被多次复用。
    • 在长连接模式下,客户端和服务器之间的TCP连接不会立即关闭,而是在一定的时间段内保持打开状态,可以用于多次请求和响应的通信。
    • 长连接适用于频繁的、持续性的通信场景,可以减少连接建立和断开的开销,提高通信效率。
  2. 短连接(短连接)

    • 短连接是指客户端和服务器之间的TCP连接在一次请求和响应之后立即关闭,不保持连接状态。
    • 在短连接模式下,每次请求都需要建立一个新的TCP连接,并在请求处理完成后立即关闭连接。
    • 短连接适用于偶发性的、临时性的通信场景,可以避免长时间保持连接而导致的资源浪费和连接数量过多的问题。

3. TCP 通过哪些方式来保证数据的可靠性?

  1. 确认和重传机制

    • TCP使用确认和重传机制来确保数据的可靠传输。接收方收到数据后,会发送确认(ACK)报文段给发送方,表示已经成功接收到数据。如果发送方在一定的时间内未收到确认,就会重新发送相同的数据,直到收到确认为止。
  2. 序号和确认号

    • TCP报文段中包含序号和确认号,用于标识数据的顺序和确认已接收的数据。通过序号和确认号,TCP可以识别和处理乱序到达的数据报文段,并确保所有的数据都能够按顺序传输和接收。
  3. 流量控制

    • TCP使用流量控制机制来确保发送方和接收方之间的数据传输速度适应网络的处理能力。接收方通过TCP窗口大小来告知发送方自己的接收能力,从而控制发送方的发送速率,防止发送过快导致数据丢失或者网络拥塞。
  4. 拥塞控制

    • TCP使用拥塞控制机制来避免网络拥塞和过载。发送方通过维护一个拥塞窗口来控制发送速率,根据网络拥塞的情况动态调整拥塞窗口的大小,以避免过多的数据包在网络中积压导致网络拥塞。
  5. 超时重传

    • 如果发送方在一定的时间内未收到接收方的确认,就会认为数据丢失或者网络发生了故障,触发超时重传机制,重新发送数据报文段。

4. Redis 怎么统计在线用户

要统计在线用户数量,你可以使用Redis的一些数据结构和命令来实现。以下是一种可能的实现方法:

  1. 使用Redis的Set数据结构

    • 可以使用Redis的Set数据结构来存储在线用户的ID。每当用户登录时,将其ID添加到一个特定的Set中,表示用户在线;用户注销时,将其ID从Set中移除,表示用户下线。
    • 例如,使用Redis的SADD命令添加用户ID到在线用户集合,使用SREM命令从在线用户集合中移除用户ID。
  2. 统计在线用户数量

    • 使用Redis的SCARD命令统计在线用户集合的数量,即可得到当前在线用户的数量。

下面是一个简单的示例代码(使用Python的redis-py库):

import redis

# 连接Redis
redis_client = redis.Redis(host='localhost', port=6379, db=0)

# 用户登录时,将用户ID添加到在线用户集合
def user_login(user_id):
    redis_client.sadd('online_users', user_id)

# 用户注销时,从在线用户集合中移除用户ID
def user_logout(user_id):
    redis_client.srem('online_users', user_id)

# 统计在线用户数量
def count_online_users():
    return redis_client.scard('online_users')

# 示例:模拟用户登录和注销
user_login(1)
user_login(2)
user_login(3)
print("当前在线用户数量:", count_online_users())  # 输出:3

user_logout(2)
print("当前在线用户数量:", count_online_users())  # 输出:2

5. 所有排序方法,分析复杂度

  1. 冒泡排序(Bubble Sort)

    • 时间复杂度:平均情况和最坏情况下都为O(n^2)。
    • 空间复杂度:O(1)。
  2. 选择排序(Selection Sort)

    • 时间复杂度:平均情况和最坏情况下都为O(n^2)。
    • 空间复杂度:O(1)。
  3. 插入排序(Insertion Sort)

    • 时间复杂度:平均情况和最坏情况下都为O(n^2)。
    • 空间复杂度:O(1)。
  4. 快速排序(Quick Sort)

    • 时间复杂度:平均情况下为O(n*log(n)),最坏情况下为O(n^2)(当每次划分都是最大或最小元素时)。
    • 空间复杂度:O(log(n))。
  5. 归并排序(Merge Sort)

    • 时间复杂度:平均情况和最坏情况下都为O(n*log(n))。
    • 空间复杂度:O(n)。
  6. 堆排序(Heap Sort)

    • 时间复杂度:平均情况和最坏情况下都为O(n*log(n))。
    • 空间复杂度:O(1)。

6. 请简单说明一下 DNS 负载均衡的优点

  1. 高可用性:DNS负载均衡可以将客户端请求分发到多个服务器上,当其中一个服务器不可用时,DNS服务会将请求重定向到其他可用的服务器,从而提高了系统的可用性。

  2. 性能提升:DNS负载均衡可以根据服务器的负载情况和地理位置等因素,选择最合适的服务器来处理客户端请求,从而实现负载均衡,减轻了单个服务器的压力,提高了系统的性能和响应速度。

  3. 灵活性:DNS负载均衡可以根据实际需求灵活调整服务器的权重和优先级,实现灵活的负载均衡策略。同时,可以根据服务器的性能和地理位置等因素,选择最合适的服务器来处理请求。

  4. 简单易用:DNS负载均衡无需额外的硬件设备或者复杂的配置,只需要通过DNS服务配置域名解析记录即可实现负载均衡,使用方便简单。

7. 请写出进程间通信主要有哪些方法

  1. 管道(Pipe)

    • 管道是一种半双工的通信方式,通常用于具有亲缘关系的父子进程间通信。
    • 包括无名管道(使用pipe()系统调用)和有名管道(使用mkfifo()系统调用)两种。
  2. 命名管道(Named Pipe)

    • 命名管道也是一种半双工的通信方式,不同之处在于命名管道是有名字的,可以在文件系统中看到,任意进程都可以通过文件名来打开它。
    • 通过mkfifo()系统调用创建。
  3. 消息队列(Message Queue)

    • 消息队列是一种消息传递机制,允许一个进程向另一个进程发送数据,发送的数据被存放在一个队列中。
    • 使用msgget()msgsnd()msgrcv()等系统调用进行操作。
  4. 共享内存(Shared Memory)

    • 共享内存是一种高效的进程间通信方式,允许多个进程共享同一块物理内存区域,进程可以直接读写这块内存区域。
    • 通过shmget()shmat()shmdt()等系统调用进行操作。
  5. 信号量(Semaphores)

    • 信号量是一种计数器,用于进程间的同步和互斥操作,常用于控制对共享资源的访问。
    • 使用semget()semop()semctl()等系统调用进行操作。
  6. 套接字(Socket)

    • 套接字是一种网络编程接口,也可以用于进程间通信,通过网络传输数据。
    • 包括流式套接字(TCP)和数据报套接字(UDP)两种类型。
  7. 信号(Signal)

    • 信号是一种异步通信机制,用于通知进程发生了某个事件,如中断、错误等。
    • 使用signal()或者sigaction()等系统调用进行信号处理。

8. 请简述 epoll 中 ET 和 LT 的区别

在epoll中,ET(Edge Triggered)和LT(Level Triggered)是两种不同的事件触发模式,它们之间的主要区别在于事件的触发方式和处理方式:

  1. LT(Level Triggered)模式

    • LT模式是epoll的默认模式。
    • 在LT模式下,当某个文件描述符上有事件发生时,epoll_wait函数会立即返回,并且会告知应用程序哪些文件描述符上发生了事件,然后应用程序需要对这些文件描述符进行处理。
    • LT模式是一种水平触发模式,即只要文件描述符上的事件还未被处理,epoll_wait函数就会不断地返回该文件描述符上的事件。
  2. ET(Edge Triggered)模式

    • 在ET模式下,epoll使用边缘触发模式。
    • 当某个文件描述符上有事件发生时,epoll_wait函数会返回并告知应用程序哪些文件描述符上发生了事件,然后应用程序需要尽可能快地对这些文件描述符进行处理。如果应用程序没有对该文件描述符进行处理,epoll_wait函数将不会再次返回该文件描述符上的事件,直到有新的事件发生。
    • ET模式是一种更为高效的触发模式,可以减少不必要的事件通知,提高了系统的性能。

9. 请简述设计模式 6 大原则分别是?

设计模式的六大原则,通常被称为SOLID原则,分别是:

  1. 单一职责原则(Single Responsibility Principle,SRP)

    • 一个类应该只有一个引起变化的原因。换句话说,一个类应该只有一个责任。如果一个类具有多个职责,那么对其中一个职责的改变可能会影响其他职责,导致代码的不稳定性和可维护性降低。
  2. 开放封闭原则(Open Closed Principle,OCP)

    • 软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着在不修改现有代码的情况下,可以通过添加新的代码来扩展系统的功能。通过抽象和多态的方式实现。
  3. 里氏替换原则(Liskov Substitution Principle,LSP)

    • 所有引用基类(父类)的地方必须能够透明地使用其子类的对象。换句话说,子类对象可以替换父类对象并且不会影响程序的正确性。这一原则强调了继承的正确使用,子类应该保留父类的行为,但可以扩展和修改父类的行为。
  4. 接口隔离原则(Interface Segregation Principle,ISP)

    • 客户端不应该被迫依赖它不使用的接口。接口应该是小而专一的,而不是大而全的。一个类不应该依赖于它不需要的接口,如果一个接口过于庞大,应该将其分割成多个更小的接口。
  5. 依赖倒置原则(Dependency Inversion Principle,DIP)

    • 高层模块不应该依赖于低层模块,两者都应该依赖于抽象。抽象不应该依赖于具体实现细节,具体实现细节应该依赖于抽象。这一原则强调了面向接口编程,而不是面向实现编程。
  6. 迪米特法则(Law of Demeter,LoD)

    • 也称为最少知识原则。一个对象应该对其他对象有最少的了解。换句话说,一个对象应该尽可能少地与其他对象进行交互,只与直接的朋友进行通信。这一原则有助于减少类之间的耦合,提高系统的灵活性和可维护性。

10. 请说下你对 MySQL 架构的了解?

MySQL 是一种开源的关系型数据库管理系统,其架构主要包括以下几个组件:

  1. 连接处理器(Connection Handler)

    • 连接处理器负责接受客户端的连接请求,并将连接请求分配给后端的线程池进行处理。每个客户端连接都会对应一个线程或者一个线程池中的一个线程。
  2. 查询处理器(Query Processor)

    • 查询处理器负责解析客户端发送的SQL查询语句,并进行语法分析、语义分析、优化查询执行计划等操作,生成可执行的查询计划。
  3. 优化器(Optimizer)

    • 优化器负责对查询进行优化,选择合适的执行计划以提高查询性能。优化器根据查询的复杂度、表的大小、索引情况等因素来选择最优的执行计划。
  4. 存储引擎(Storage Engine)

    • MySQL的存储引擎是一种插件式的架构,支持多种存储引擎,例如InnoDB、MyISAM、Memory等。存储引擎负责数据的存储和检索,不同的存储引擎具有不同的特性和适用场景。
  5. 缓存管理器(Cache Manager)

    • MySQL通过缓存管理器来管理查询结果的缓存,提高重复查询的性能。MySQL的查询缓存功能可以缓存查询结果,避免重复执行相同的查询,提高查询性能。
  6. 日志系统(Logging System)

    • MySQL的日志系统记录了数据库的所有变更操作,包括事务日志、错误日志、查询日志等。日志系统对于数据库的可恢复性和可靠性至关重要。
  7. 锁管理器(Lock Manager)

    • 锁管理器负责管理数据库中的锁机制,包括行级锁、表级锁、事务级锁等。锁管理器保证了并发访问时的数据一致性和事务的隔离性。
  8. 存储层(Storage Layer)

    • 存储层负责将数据持久化到物理存储介质中,包括磁盘、固态硬盘等。存储层还负责数据的读写操作,以及数据的索引管理等。

MySQL的架构是一个多层次的、模块化的架构,每个组件都承担着不同的功能,共同协作完成数据库管理系统的各项任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SmiledrinkCat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值