整理-百度面经

杨大大...大约 23 分钟

1.计算机网络:七层网络、HTTPS的加密在第几层?

表示层:该层的主要任务是把所传送的数据的抽象语法变换为传送语法,即把不同计算机内部的不同表示形式转换成网络通信中的标准表示形式。此外,对传送的数据加密(或解密)、正文压缩(或还原)也是表示层的任务。

2.操作系统:内存管理、虚拟内存、缺页中断、IO了解吗、IO多路复用。BIO、AIO、NIO用过吗?

BIO是同步阻塞IO,AIO是异步IO,NIO是非阻塞IO,适用于连接数多且长连接的场景。

3.MQopen in new window:怎么确保不会出现消息丢失?

从Kafka的角度来看,确保消息不丢失主要可以通过以下几点来实现:

  1. 生产者设置参数retries,当发送失败时重试次数,防止消息丢失。

    props.put("retries", 3);
    

2.生产者设置参数acks,请求消息确认。

java

Copy code

props.put("acks", "all");

3.消费者设置参数enable.auto.commit为false,手动提交offset,失败时可以重新消费。

java

Copy code

consumer.commitSync();

4.采用至少3个副本保存消息,避免单点失败导致消息丢失。

Copy code

replication-factor=3

5.开启生产者幂等性,发送重复消息只会写入一次。

java

Copy code

producer.initTransactions();
producer.beginTransaction();

6.消费者处理完消息后发送ACK确认。

java

Copy code

consumer.commitAsync();

4.JVM:介绍常见垃圾回收、内存区域、JVM调优参数、生产环境下怎么排查内存满的问题,可以使用哪些命令排查?

  • 垃圾回收算法有标记清除、复制、标记压缩、分代回收等,还有G1、ZGC、Epsilon GC等最新收集器。
  • JVM内存区域主要有堆区、栈区、方法区、程序计数器等,不同类型的内存分配于不同区域。
  • 常用的JVM调优参数有:-Xmx、-Xms、-Xmn设置内存大小,-XX:MetaspaceSize等调整元空间、-Xss调整栈空间等。
  • 排查内存泄漏可以通过jmap、jstack、jstat、arthas等工具dump内存,分析dump文件找出suspicious的对象引用 chains。
  • Linux下可以用top命令查看进程内存占用,ps命令查看线程数,-F选项查看进程间内存共享情况。
  • 还可以采用内存分析工具如MAT、JProfile进行内存抽样分析,找出内存中的大对象引用链。
  • 排查时要综合全面分析,找到内存占用较大的对应代码位置,分析业务逻辑避免内存泄漏。

5.Spring:介绍IOC/AOP。如果被代理对象不实现接口怎么实现代理、cglib和jdk动态代理区别?

  • IOC(控制反转)是Spring核心机制,通过依赖注入管理Bean,解耦对象之间依赖。

  • AOP实现通过动态代理技术,在运行时植入切面逻辑,实现对程序功能的无侵入增强。

  • JDK动态代理通过反射生成目标对象接口的代理,目标对象必须实现接口,否则无法代理。

  • Cglib通过生成目标类的子类作为代理,不需要实现接口,是针对类代理,比JDK代理更灵活。

  • Cglib代理效率高,但需要处理final类无法代理的问题。JDK代理适用于接口代理场景,处理简单。

  • Spring使用JDK代理优先,无法代理时使用Cglib,所以Spring AOP可以面向接口编程,也可以仅通过类实现。

  • JDK动态代理和Cglib实现原理及区别如下:

  • JDK动态代理只能代理实现了接口的类,通过反射生成接口的代理类执行方法。

  • Cglib是通过生成一个被代理类的子类来实现代理,不需要实现接口,通过方法拦截实现增强。

  • Cglib基于asm框架生成字节码,执行效率比JDK代理高,但需要处理final类无法代理的问题。

  • Spring在JDK代理可用时使用JDK代理,当目标类没有接口时使用Cglib代理。

JDK动态代理和Cglib代理的代码示例如下:

JDK动态代理

  1. 定义接口:
java

Copy code

public interface IHello {
    void sayHello();
}

2.实现类:

java

Copy code

public class HelloImpl implements IHello {
    public void sayHello() {
        System.out.println("Hello JDK Proxy!");
    }
}

3.创建代理类:

java

Copy code

IHello proxy = (IHello) Proxy.newProxyInstance(
  cls.getClassLoader(), 
  new Class[]{IHello.class}, 
  new DynaProxy(new HelloImpl()));

Cglib代理

  1. 定义类:
java

Copy code

public class HelloCglib {
    public void sayHello() {
        System.out.println("Hello Cglib!");
    }
}

2.创建代理类:

java

Copy code

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(HelloCglib.class);
enhancer.setCallback(new DynaProxy());
HelloCglib proxy = (HelloCglib)enhancer.create();

可以看出JDK动态代理通过接口定义,而Cglib直接通过继承类实现代理。

6.redis:常见数据类型、分布式锁、分布式锁的过期时间怎么设置(秒杀场景下分布式锁过期时间的设置)、redis实现队列?

  • Redis常用的数据类型有String、Hash、List、Set、Sorted Set、BitMap等,丰富的数据结构使其成为高性能的缓存和存储系统。
  • Redis分布式锁可以利用SETNX命令实现,还需要考虑锁失效、阻塞锁、可重入锁等。
  • 分布式锁过期时间需要根据业务场景确定,一般不能太长,秒杀场景下可以设置1-10秒左右的过期时间。
  • 设置合理的过期时间可以防止死锁,并且过期后才会释放锁,避免未释放锁的情况。
  • Redis可通过LPUSH、BRPOP实现队列,LPUSH入队,BRPOP出队。还可通过List数据结构的LPOP、RPOP也可实现队列。

7.并发:秒杀场景、超卖一人一单问题。分布式场景下的秒杀问题(一个线程误删其他线程锁的问题)。

  • 秒杀场景的核心问题是避免超卖,即卖出的商品超过实际库存量的问题。
  • 在单机情况下,可以利用synchronized或ReentrantLock进行同步控制,保证每个商品销售请求串行执行。
  • 在分布式环境下,需要利用分布式锁,常见的有基于Redis、Zookeeper实现的分布式锁。
  • 加锁后还需要关注锁的释放,防止线程终止导致的死锁。可以设置锁超时时间,或在finally中主动释放锁。
  • 还需要注意不同线程获取同一锁的情况,这时需要加入重入机制,确保同一线程可以重复获取锁。
  • 如果不同线程可以误删对方的锁,需要通过锁的值标识锁的持有者,防止误删。
  • 除了对库存加锁外,还可以通过消息队列削峰、限流等手段进行流量控制。

8.mysql:MVCC、binlog、redolog、undolog?

  • MVCC全称是多版本并发控制,可以实现读写分离, Writers不会阻塞Readers。
  • binlog是MySQL的二进制日志,记录所有对数据库的修改操作,可以用于数据恢复和主从复制。
  • redolog是InnoDB存储引擎的物理日志文件,记录数据修改所需的日志记录。
  • undolog是InnoDB提供的回滚日志,实现事务的回滚操作。
  • binlog存储所有操作日志,redolog存储对InnoDB表的修改,undolog提供恢复支持。
  • MVCC通过undo log实现版本链和历史版本读取,优化并发性能。
  • binlog和redolog定期做fsync刷盘,提高容灾能力。

9.Linux:会不会写shell脚本、大文件统计内容(有一百万行,每行一个名字,统计名字出现次数最多的人)要怎么做?

对于统计大文件内容,可以用Linux自带的sort、uniq命令组合:

  • 首先用sort将文件排序
  • 然后用uniq统计各行出现次数
  • 最后用sort排序输出次数最多的即可

假设大文件file.txt内容格式为:

Copy code

张三
李四
王五
张三

然后我们用shell脚本处理:

对文件排序

bash

Copy code

sort file.txt -o sorted.txt

对排序后的文件去重统计

bash

Copy code

uniq -c sorted.txt > count.txt

对统计结果重新排序

bash

Copy code

sort -nr count.txt > final.txt

final.txt的结果即为每个名字的出现次数排序:

Copy code

2 张三
1 李四  
1 王五

10.进程和线程的区别?

  • 进程有独立的地址空间,线程共享进程的地址空间。
  • 进程之间通信需要IPC,线程可以直接读写进程数据段。
  • 进程切换需要保存上下文并加载新上下文,线程切换只保存和加载寄存器内容,更轻量。
  • 进程具有完整的系统资源,线程依赖于进程的系统资源。
  • 进程开销较大,线程更轻量级。

简单来说,线程是轻量级的进程,同一类线程共享资源,这是两者的主要区别。

11.i = i + 1大概执行多久?

  1. 我们假设i是一个int类型的变量,编译环境为Java Hotspot VM,处理器是目前典型的3GHz英特尔CPU。
  2. i=i+1这条语句只有一个加法和赋值操作,每个操作编译后的机器指令大概需要1-2个CPU周期。
  3. 再考虑读取和写入i变量的时间。我们假设i在L1缓存中,L1缓存读取写入大概需要3-4个CPU周期。
  4. 所以仅计算操作来看,整条语句的机器指令需要约5-8个CPU周期。
  5. 在3GHz的CPU下,每个CPU周期时间是1/3ns = 0.33ns。
  6. 那么这条语句的计算时间约为5-8个周期,也就是2-3纳秒。
  7. 如果考虑实际运行环境,可能有一定的函数调用开销,还需加上指令流水线的影响。
  8. 所以一个较为准确保守的估计,i=i+1这条语句执行的时间大概在10纳秒左右。
  9. 对于如此微小的简单操作,编译器和CPU的优化Would发挥重要作用,实际运行时间可能还更短。

13.进程间的通信方式有哪些?

  • 共享内存 - 多个进程映射同一块内存,实现数据共享。
  • 消息队列 - 进程利用队列传递消息。
  • 信号量 - 进程根据信号量进行同步和互斥。
  • 套接字 - 进程间网络通信的基础。
  • 管道 - 具有亲缘关系的进程间单向通信。

14.了解中断吗?键盘上敲一个字母是什么中断?

  • 中断是一种重要的计算机系统机制,当外部事件发生时,CPU可以暂停当前执行的程序,转而处理中断。
  • 键盘输入产生的中断通常是硬件中断。

15.查找一个字符串是否在文件中?

grep命令,格式为grep '搜索字符串' 文件名,这是最简单直接的方法。

16.查找本机一个端口号的状态?

使用lsof命令,格式:

lsof -i :端口号

17.几十个G的文件中查找一个字符串是否存在?

使用split将大文件分割成块文件

Copy code

split -b 100m bigfile.txt

这里将文件分割成100MB一块

使用grep进行片段搜索

Copy code

grep "搜索字符串" bigfile.txt.*

利用grep对每个块文件进行搜索

18.如何判断远程服务的端口有没有开启?

用telnet

19.平时在Linux上都用什么命令?

20.介绍一下OSI七层协议,各层协议都有哪些?

OSI七层协议模型概述如下:

  1. 物理层 - 定义物理设备标准,比如电缆标准、网络接口卡等。协议包括RS232,V.24等。
  2. 数据链路层 - 将网络层传下来的IP数据报组装成帧。协议包括PPP,HDLC,VLAN等。
  3. 网络层 - 确定数据包从源到目的地的传输路径。协议包括IP、ICMP、ARP等。
  4. 传输层 - 提供端到端的连接和可靠传输。协议包括TCP、UDP等。
  5. 会话层 - 建立、管理和释放会话连接。协议包括NFS、SQL、RPC等。
  6. 表示层 - 对数据进行翻译、压缩和加密。协议包括JPEG、MP3等。
  7. 应用层 - 数据从应用进程到网络的接口。协议包括HTTP、DNS、FTP等。

21.百度搜索www.baidu.com到页面出现百度,这中间发生了什么?

  1. DNS解析(Domain Name System解析):浏览器首先会执行DNS解析,将"www.baidu.com"这个域名转换成对应的IP地址,以便能够找到正确的服务器。这通常涉及到查询DNS服务器,以获取域名对应的IP地址。open in new window
  2. 建立TCP连接:浏览器使用域名对应的IP地址,通过HTTP或HTTPS协议与百度的服务器建立TCP连接。这是通过三次握手来完成的,以确保双方建立稳定的通信连接。
  3. 发送HTTP请求:浏览器向百度的服务器发送HTTP请求,请求打开百度的主页。这个请求包含了很多信息,如请求的资源、浏览器类型、支持的编码等等。
  4. 服务器处理请求:百度的服务器接收到浏览器的请求后,会进行处理。它会查找请求的资源(百度的主页),生成响应并返回给浏览器。
  5. 浏览器渲染页面:浏览器接收到来自服务器的响应后,会解析HTML、CSS和JavaScript,并渲染出最终的页面,显示给用户。
  6. 关闭连接:一旦页面被加载完毕,浏览器和服务器会关闭TCP连接,以释放资源。

22.baidu.com默认用什么端口?

443

23.两次握手可以吗?

如果不使用TCP的标准三次握手来建立连接,可能导致连接建立时的不确定性,服务器难以区分新的连接请求和之前未完成的连接。

24.如果网络情况非常好百分百不会发生拥塞,不会重传SYN,不会有历史连接的问题,可以两次握手吗?

可以

25.udp丢包会有什么现象?

导致视频质量下降,出现图像块状或失真。

26.证书是绿色的是什么意思?

绿色的证书在浏览器中通常表示安全性和信任。这意味着与网站建立的连接是加密的,数据传输是受保护的,不容易被窃听或篡改。此外,绿色的证书表示该网站的身份已通过证书颁发机构的验证,浏览器信任该网站。

27.自己随便编一个证书可以吗?需要去什么地方注册?

不应该随便编造自己的数字证书,因为这是不道德且可能是非法的行为。

数字证书颁发机构。

28.proactor和reactor模式

  1. Reactor模式
    • Reactor是一种反应器模式,也称为事件驱动模式。
    • 在Reactor模式中,通常有一个主线程(反应器),它负责监视并分发I/O事件。
    • 当发生I/O事件时,反应器会调用适当的处理程序(也称为处理器或回调函数)来处理事件。这些处理程序通常运行在不同的线程中,以处理事件的具体逻辑。
    • Reactor模式通常用于多路复用IO操作,如select、poll、epoll等。
  2. Proactor模式
    • Proactor是一种主动者模式。
    • 在Proactor模式中,通常有一个主线程(主动者)负责启动和管理I/O操作,以及监视其完成。
    • 当I/O操作完成时,主动者会通知适当的处理程序来处理已完成的操作。
    • Proactor模式通常用于异步IO操作,其中操作的启动和完成是分开的,允许应用程序继续执行其他任务,而无需等待IO操作完成。

29.五种IO模型

  1. 阻塞I/O模型(Blocking I/O)
    • 在阻塞I/O模型中,当应用程序发起I/O操作时,它会阻塞(暂停)等待操作完成,直到数据可用或操作完成为止。
    • 这种模型非常简单,但可能导致应用程序的性能受限,因为它需要等待I/O操作完成,无法执行其他任务。
  2. 非阻塞I/O模型(Non-blocking I/O)
    • 在非阻塞I/O模型中,应用程序可以继续执行其他任务而不会等待I/O操作的完成。
    • 应用程序会定期轮询I/O操作的状态,以查看它们是否已经完成,或者是否可以继续。
  3. I/O复用模型(I/O Multiplexing)
    • I/O复用模型使用一个线程来监听多个文件描述符(套接字),以确定哪些文件描述符可读或可写。
    • 常见的I/O复用技术包括select、poll和epoll。
    • 这种模型可以实现高并发,允许应用程序同时处理多个I/O操作。
  4. 信号驱动I/O模型(Signal-driven I/O)
    • 信号驱动I/O模型通过信号通知应用程序,当文件描述符可读或可写时,触发相应的信号处理程序。
    • 这允许应用程序异步地处理I/O操作,而无需轮询或阻塞等待。
  5. 异步I/O模型(Asynchronous I/O)
    • 在异步I/O模型中,应用程序发起I/O操作,然后可以继续执行其他任务,而无需等待I/O操作完成。
    • 当I/O操作完成时,应用程序会得到通知,通常通过回调函数或事件处理程序。
    • 异步I/O允许高并发且高效地处理I/O操作,适用于大规模的并发应用。

30.epoll是同步还是异步的?这个争议很大

epoll 是一个 I/O 多路复用机制,它是异步的。

31.什么是qps和tps,如何计算?

  1. QPS(Queries Per Second)
    • QPS是指每秒钟处理的查询或请求的数量。它通常用于衡量系统的查询处理性能,如数据库查询、API请求等。
    • QPS计算方式:QPS = 总请求数 / 统计时间(秒)
    • 例如,如果一个Web服务器在一分钟内处理了6000个HTTP请求,其QPS为100(6000请求 / 60秒)。
  2. TPS(Transactions Per Second)
    • TPS是指每秒钟执行的事务或操作的数量。它通常用于评估事务性系统(如金融交易、订单处理)的性能。
    • TPS计算方式:TPS = 总事务数 / 统计时间(秒)
    • 例如,如果一个银行系统在一分钟内完成了3000笔交易,其TPS为50(3000交易 / 60秒)。

32.线程池数量如何确定?

33.CPU利用率拉满的时候在线程池中增加线程是否能提高qps?

CPU已经处于满载状态,增加的线程只能等待CPU时间片,无法真正并行执行,所以无法提升系统整体处理能力。

根据CPU利用率动态设计,优化这个线程池:

  1. 监控CPU利用率,可以通过Linux top命令、JMX监控等方式。
  2. 设置一个CPU利用率的高水位线,例如80%,当超过此值则触发优化。
  3. 当超过高水位线时,记录当前线程池工作线程数量workThreads作为基准。
  4. 计算按照CPU核心数设定的最大线程数maxThreads。
  5. 计算剩余可用的线程数:maxAddThreads = maxThreads - workThreads
  6. 当CPU利用率开始下降时,每下降1%,增加线程池线程数: addThreads = maxAddThreads * 添加比例(例如10%)
  7. 当CPU利用率降至下限值时,则恢复线程数至 maxThreads。
  8. 继续监控CPU利用率波动,重复此优化循环。

34.http解析主从状态机?

HTTP协议的解析可以采用有限状态机来实现,主要包含两个状态机:

1.主状态机:用于解析HTTP请求的状态机

  • 初始状态:等待请求
  • 解析请求行:解析HTTP方法、URL、协议版本
  • 解析消息头:解析各个消息头的键值对
  • 解析消息体:如果有消息体则解析
  • 构造返回响应消息

2.从状态机:解析具体消息头的状态机

  • 初始化状态:准备解析消息头
  • 读取消息头key:解析消息头关键字
  • 读取冒号:读取冒号分隔符
  • 读取空格:读取空格分隔符
  • 读取值:读取消息头的值
  • 校验:校验消息头是否正确
  • 结束:完成当前消息头的解析

35.协程

协程(coroutine)是一种轻量级的线程,可以简单理解为用户态的线程。关于协程的一些关键特点:

  1. 协程是非抢占式的,执行流程完全由协程自己控制,可以自由切换执行。
  2. 切换开销小,不需要线程上下文切换,只需要保存和恢复程序计数器。
  3. 协程可以达到争用变合作,不需要加锁即可实现任务协作。
  4. 支持大量的协程同时运行,可以充分利用多核CPU。
  5. 编程模型简单,通过Yield让出控制权。

主要的协程调度方式有:

  1. 自调度 - 协程自己决定何时让出执行权。
  2. 预定调度 - 调度器根据时间片调度协程执行。
  3. 应用级调度 - 应用级代码可以自行调度协程。

定义一个协程任务类MyCoroutine实现Runnable接口:

java

Copy code

public class MyCoroutine implements Runnable {

  @Override
  public void run() {
    // 执行任务
    System.out.println("开始执行");
    
    Thread.yield(); // 主动让出CPU执行权
    
    // 继续执行任务 
    System.out.println("恢复执行");
  }

}

主线程中创建协程任务并启动线程:

java

Copy code

public class Main {

  public static void main(String[] args) {
    MyCoroutine coroutine1 = new MyCoroutine();
    Thread t1 = new Thread(coroutine1);
    t1.start();
    
    // 其他协程任务并启动线程
    
    // 主线程休眠以调度协程任务
    Thread.sleep(1000); 
  }

}

执行结果是各个协程任务会轮流打印输出,实现了协作调度,不需要等待线程结束就可以切换。

36.在选择任务的技术路线时如何佐证你的方案是可行的?

在选择技术路线时,我首先进行了需求和约束的分析,以确保选择的方案能够满足项目的要求。我进行了技术调研,参考了相关的最佳实践和现有解决方案。此外,我还创建了一个原型来验证所选技术的可行性,并进行了可行性分析,包括技术可行性、资源可行性和成本可行性。我还识别了潜在风险,并提供了解决方案。最重要的是,我不断进行反思和反馈,以确保项目顺利进行。

37.如果你的想法和大家的反馈有冲突怎么办?

在团队中,有时候我的想法可能与其他成员的反馈有所冲突。这是一个正常的现象,因为每个人都有自己的经验和观点。我一直致力于尊重团队的反馈,认真倾听每个人的意见,并积极地与他们讨论不同的观点。我也会提供解释,以清晰地说明我的决策基于什么。同时,我会寻求妥协,以找到最佳的解决方案,满足团队的共同目标。最重要的是,我将不断学习和改进自己的方法,以更好地为团队和项目做出贡献。

38.当你的任务有做偏了的情况在哪一步去进行挽回?

  1. 阶段一:任务分析和规划

    • 挽回机会: 在任务分析和规划阶段,你应该确保对任务的理解是准确的,同时明确了任务的目标和可衡量的成果。如果在这个阶段出现误解或不确定性,应该尽早与相关方沟通,以消除歧义。
    • 回答方式: "如果我在任务分析和规划阶段发现任务可能出现偏离,我会立即与相关方进行进一步的讨论,以确保对任务的理解是准确的,并明确任务的目标。这有助于避免后续阶段的偏离。"
  2. 阶段二:执行任务

    • 挽回机会: 如果在任务执行期间发现任务偏离了方向,你应该及早发现问题,并采取纠正措施,以确保任务按计划进行。
    • 回答方式: "如果我在任务执行过程中发现任务有可能偏离方向,我会立即与团队或负责人进行沟通,讨论问题并寻找解决方案。这可以包括重新调整任务分工、更新计划或采取其他纠正措施,以确保任务在正确的方向上前进。"
  3. 阶段三:监测和反馈

    • 挽回机会: 在任务监测和反馈阶段,你应该定期评估任务的进展并收集反馈。如果发现任务偏离了目标,应该立即采取措施纠正。
    • 回答方式: "任务监测和反馈是及时纠正任务偏离的关键阶段。如果我发现任务偏离了目标,我会立即采取纠正措施,并与团队一起制定新的计划,以确保任务按照正确的轨道前进。"
  4. 阶段四:总结和改进

    • 挽回机会: 即使任务已经完成,也可以在总结和改进阶段挽回。你可以分析任务的执行情况,识别问题,以便将这些教训应用于未来的任务。
    • 回答方式: "任务完成后,我们还可以在总结和改进阶段挽回。通过分析任务的执行情况,识别问题,并制定改进措施,以确保未来的任务更顺利。"

39.别人给你的反馈不一定是正确的,你觉得自己的思路更好,这种情况怎么处理?

当我遇到与他人反馈不一致的情况时,我首先会倾听和理解他们的观点。尊重他们的意见,因为他们可能提供了有价值的观点。然后,我会解释我的观点,提供清晰的论点和示范,以支持我的方法。我会尝试与团队探讨妥协的可能性,以找到更好的解决方案。最终,如果决策权在别人手中,我会尊重最终的决策。这个过程不仅有助于解决问题,还为我提供了学习和改进的机会,以提高团队的协作和决策质量。

40.对于更具有权威性的人提出的建议你是怎么考虑的?

当更具权威性的人提出建议时,我会非常尊重他们的观点,并认真倾听他们的建议。我会审慎评估建议的合理性,并根据实际情况决定是否采纳。同时,我不会害怕提出问题或进行探讨,以更好地理解他们的观点。如果我有不同的观点或更好的解决方案,我会提供我的观点,但这是在尊重的基础上进行的。

41.优势和不足的点