【2024秋招】2023-9-22 金山云文档服务端开发一面

1 OS

1.1 堆和栈的区别,什么时候用到堆,什么时候用到栈呢

堆和栈是两种不同的内存分配方式,它们在计算机编程中有着各自的用途和特点。以下是它们之间的主要区别以及在何时使用它们:

1.1.1 堆(Heap):

  1. 定义:堆是一个用于动态分配内存的区域,它的大小不是在编译时确定的,而是在运行时动态分配的。
  2. 生命周期:堆上的内存分配的生命周期由程序员控制。当不再需要某块内存时,必须显式地释放它,否则可能会导致内存泄漏。
  3. 分配方式:使用如malloc()calloc()new等函数在堆上分配内存。
  4. 访问速度:相对于栈来说,访问堆上的内存通常较慢。
  5. 用途:当需要大量的内存或者不确定所需内存的大小时,通常会使用堆。例如,存储大型数据结构、动态数组等。

1.1.2 栈(Stack):

  1. 定义:栈是一个用于存储局部变量和函数调用信息的内存区域。它遵循后进先出(LIFO)的原则。
  2. 生命周期:栈上的内存分配的生命周期是自动的。当函数返回时,其局部变量会自动从栈上弹出并释放。
  3. 分配方式:当声明一个局部变量时,它会自动在栈上分配内存。
  4. 访问速度:访问栈上的内存通常比访问堆上的内存更快。
  5. 用途:用于存储函数的局部变量、函数参数和返回地址。

1.1.3 什么时候使用堆和栈?

  • 使用堆:当你需要动态分配内存,或者需要在函数调用之间保留数据时,应该使用堆。例如,创建一个动态数组或链表。
  • 使用栈:当你只在函数内部使用数据,并且不需要在函数返回后保留这些数据时,应该使用栈。例如,函数的局部变量。

总之,选择使用堆还是栈取决于你的具体需求,如数据的生命周期、内存的大小和访问速度等因素。

1.2 JAVA中有没有一些场景是强行把本身在栈里面的分配的对象放到堆里面呢?

在Java中,对象的分配始终是在堆上进行的,而不是在栈上。栈上主要存储的是基本数据类型(如intcharfloat等)的值以及对象引用(但不是对象本身)。因此,你不需要(也不能)强行将在栈上分配的对象移动到堆上,因为对象本身从一开始就是在堆上分配的。

但是,Java中有一个与此相关的概念,即"逃逸分析"。逃逸分析是JVM的一种优化技术,用于确定对象的作用范围和生命周期。如果JVM通过逃逸分析确定某个对象只在一个方法内部使用,并且不会被外部引用,那么JVM可能会选择在栈上分配这个对象,而不是在堆上。这种优化可以减少垃圾收集的开销。但这并不是程序员显式控制的,而是JVM的内部优化。

总之,Java程序员不需要担心对象是在堆上还是栈上分配的,因为这是由JVM自动管理的。但了解这些概念和背后的机制对于编写高效的Java代码是有帮助的。

1.3 TLAB对于线程的作用

TLAB(Thread-Local Allocation Buffer)是Java HotSpot虚拟机中的一个优化技术,用于提高对象分配的速度。以下是TLAB对于线程的作用和相关的详细解释:

1. 提高对象分配速度

在多线程环境中,多个线程可能同时尝试在堆上分配对象。为了确保内存分配的正确性,这些线程需要在分配对象时进行同步,这可能会导致性能开销。TLAB的引入旨在减少这种同步开销。每个线程都有自己的TLAB,这是堆内存中的一个小片段,用于该线程的对象分配。由于TLAB是线程局部的,线程在分配对象时不需要进行同步,从而大大提高了对象分配的速度。

2. 减少锁竞争

由于每个线程在其自己的TLAB中分配对象,所以减少了线程之间的锁竞争。这对于高并发应用程序来说是非常有益的,因为它可以减少线程之间的争用和上下文切换,从而提高整体性能。

3. 提高缓存局部性

由于TLAB是连续的内存区域,并且是线程局部的,所以它可以提高CPU缓存的局部性。当线程在其TLAB中分配和访问对象时,这些对象可能位于相同的CPU缓存行中,从而提高缓存命中率。

4. 动态调整

JVM会根据应用程序的行为动态调整TLAB的大小。如果一个线程频繁地分配对象,其TLAB可能会被调整得更大,从而减少溢出的可能性。相反,如果一个线程很少分配对象,其TLAB可能会被调整得更小,从而减少内存浪费。

5. 垃圾收集的影响

由于TLAB是在Young Generation(年轻代)中分配的,所以它们会受到Minor GC的影响。但是,由于TLAB的存在,对象分配和回收都变得更加高效,从而可能减少GC的开销。

总之,TLAB是Java HotSpot虚拟机中的一个重要优化技术,它可以提高对象分配的速度,减少锁竞争,提高缓存局部性,并对垃圾收集产生积极的影响。

1.4 在java的场景里,传参是值还是引用的一个传递呢

答:如果传递的是基本数据类型属于值传递;如果传递的是对象,那么就是引用;如果传递的是不可变变量比如String,Integer,Long类型的变量,传递的也是值

在Java中,方法参数的传递方式经常引起混淆。让我们详细解释一下:

  1. 基本数据类型:当你传递一个基本数据类型(如intcharfloatboolean等)给一个方法时,你传递的是该值的一个拷贝。这意味着方法内对参数的任何修改都不会影响到原始变量。这被称为值传递

  2. 对象引用:当你传递一个对象给一个方法时,你实际上传递的是对象引用的一个拷贝,而不是对象本身。这意味着你可以在方法内修改对象的状态(即其字段的值),并且这些修改会反映到原始对象上。但是,如果你让引用指向一个新的对象,原始引用不会改变。这经常被误解为“引用传递”,但实际上更准确地说,这是引用的值传递

  3. 不可变对象:像StringIntegerLong等类的实例是不可变的。这意味着一旦创建了这些对象,就不能修改它们的状态。当你传递一个不可变对象给一个方法时,你传递的是该对象引用的一个拷贝。由于对象是不可变的,所以你不能在方法内修改它的状态。但是,你可以让引用指向一个新的对象,这不会影响到原始引用。因此,尽管传递的是引用的拷贝,但由于对象的不可变性,这在实际效果上类似于值传递。

总结:在Java中,无论是基本数据类型还是对象引用,方法参数的传递方式始终是值传递。但由于对象引用的特性,这种传递方式可能会产生与传统的值传递不同的效果。

2 数据结构

2.1 用到比较多的一些数据结构有哪些呢

hasmap,list

2.2 介绍一下map的扩容和底层原理

2.3 hashMap在针对并发的场景去解决呢

答:concurrentHashMap的原理

3 redis

3.1 你应用分布式锁的实践

答:解决缓存击穿、秒杀系统的超卖问题

3.2 redis的缓存雪崩、击穿、穿透问题的解决方案

3.3 对于你说用布隆过滤器解决缓存穿透问题的方案,如果说数据的存在与否是动态变化的,这10分钟存在,后面10分钟又不存在呢?

布隆过滤器是一个概率型数据结构,用于判断一个元素是否在一个集合中。它的主要优点是空间效率和查询时间都非常高,但它存在一定的误判率,即可能会认为某个不存在的元素存在(但不会误判存在的元素为不存在)。

当使用布隆过滤器来解决缓存穿透问题时,我们通常先查询布隆过滤器来检查某个键是否可能存在。如果布隆过滤器表示该键不存在,则直接返回,不再查询数据库;如果布隆过滤器表示该键可能存在,则继续查询缓存或数据库。

但是,如果数据的存在与否是动态变化的,布隆过滤器会面临一些挑战:

  1. 数据的添加:当数据添加到数据库时,相应的键可以被添加到布隆过滤器中,这是简单的。
  2. 数据的删除:布隆过滤器本身不支持删除操作。如果数据从数据库中删除,布隆过滤器中的相应键仍然存在。这意味着即使数据已经不存在,布隆过滤器可能仍然表示它存在,导致不必要的数据库查询。

对于动态变化的数据,有以下几种策略可以考虑:

  1. 定期重建:定期(例如每10分钟、每小时)重建布隆过滤器,以确保它反映了最新的数据状态。
  2. 使用Counting Bloom Filter:这是布隆过滤器的一个变种,它支持删除操作。但它需要更多的空间,并且可能仍然存在误判。
  3. 结合TTL:对于缓存和布隆过滤器中的条目,可以设置一个TTL(生存时间)。当条目过期时,可以从缓存中删除,并在下次重建布隆过滤器时不再包括它。
  4. 双布隆过滤器:使用两个布隆过滤器,一个为当前的,另一个为上一个时间段的。当数据变化时,新数据添加到当前的布隆过滤器中。查询时,两个布隆过滤器都被检查。定期切换这两个布隆过滤器的角色,并重建旧的布隆过滤器。

总的来说,布隆过滤器是一个强大的工具,但在动态数据环境中使用时需要考虑其局限性和可能的策略。

3.4 布隆过滤器本身不支持删除操作,为什么

布隆过滤器的工作原理是基于多个哈希函数。当你想将一个元素添加到布隆过滤器中时,这个元素会被多个哈希函数处理,每个哈希函数都会生成一个位置索引,然后将这些位置的位标记为1。因此,一个元素的加入可能会影响布隆过滤器中的多个位。

当检查一个元素是否在布隆过滤器中时,同样使用这些哈希函数来获取位置索引,并检查这些位置的位是否都为1。如果都为1,那么元素可能在布隆过滤器中(注意是“可能”,因为存在误判率);如果有任何一个位不为1,那么元素肯定不在布隆过滤器中。

现在,考虑删除操作。如果你想从布隆过滤器中删除一个元素,理论上你可以使用相同的哈希函数找到位置索引,并将这些位置的位设置为0。但这样做有一个问题:由于布隆过滤器的特性,一个位置的位可能被多个元素共同设置为1。如果你简单地将一个元素的位设置为0,你可能会误删其他元素的位,从而破坏布隆过滤器的正确性。

因此,由于这种多个元素可能共同影响同一位的特性,布隆过滤器本身不支持删除操作。如果数据从数据库中删除,布隆过滤器中的相应键仍然存在,这可能导致布隆过滤器误判该数据仍然存在,从而导致不必要的数据库查询。

3.5 当数据添加到数据库时,相应的键可以被添加到布隆过滤器中,这是简单的。 如何添加

当数据添加到数据库时,如果你想将相应的键也添加到布隆过滤器中,可以按照以下步骤进行:

  1. 选择哈希函数:布隆过滤器依赖于多个哈希函数。这些哈希函数应该是独立的,并且能均匀地散列数据到布隆过滤器的位数组中。常见的哈希函数有MurmurHash、SHA-256等。

  2. 哈希处理:将要添加的键通过每一个哈希函数进行处理。每个哈希函数都会为这个键生成一个整数值,这个值对应于布隆过滤器位数组中的一个位置。

  3. 设置位:根据每个哈希函数生成的位置索引,将布隆过滤器位数组中的相应位置设置为1。如果某个位置已经是1,那么保持不变。

例如,假设我们有一个长度为10的布隆过滤器位数组(实际应用中,布隆过滤器的大小通常会更大),并且我们使用了两个哈希函数。当我们想添加一个键“key”时:

  • 哈希函数1处理“key”并返回位置2。
  • 哈希函数2处理“key”并返回位置5。
  • 我们将位数组中的位置2和位置5设置为1。

这样,“key”就被添加到了布隆过滤器中。当我们后续查询“key”是否在布隆过滤器中时,只需检查位置2和位置5是否都为1。如果都为1,那么“key”可能在布隆过滤器中;如果有任何一个位不为1,那么“key”肯定不在布隆过滤器中。

需要注意的是,由于布隆过滤器的误判率,即使位置2和位置5都为1,也不能100%确定“key”确实在布隆过滤器中,只能说“key”可能在其中。但如果有任何一个位不为1,那么可以确定“key”肯定不在布隆过滤器中。

3.6

4 计算机网络

4.1 讲讲tcp的关闭过程需要四次挥手

答:

4.2 如何改造成三次挥手关闭呢

TCP协议使用四次挥手来终止一个连接。这是为了确保双方都能独立地关闭其连接的一侧。如果要改造成三次挥手,可能会牺牲某些安全性或可靠性。但从理论上讲,如果我们确实想要三次挥手:

  1. 第一次挥手:客户端发送一个终止请求给服务器。
  2. 第二次挥手:服务器回应确认收到终止请求,并同时发送自己的终止请求。
  3. 第三次挥手:客户端确认服务器的终止请求。

这种方法的问题是,它假设在第二次和第三次挥手之间,服务器不会发送任何新的数据。在实际的TCP协议中,四次挥手确保了即使在终止过程中仍有数据在传输,连接也能被安全地关闭。

4.3 HTTP2.0 多了哪些特点和优势

HTTP/2是HTTP/1.x的直接后继者,它引入了许多改进和新特性,旨在提高性能和效率。以下是HTTP/2的主要特点和优势:

  1. 多路复用:在一个单一的TCP连接上,可以同时发送多个请求和响应消息,而不需要按照顺序一个接一个地进行。这减少了延迟并提高了加载速度。

  2. 头部压缩:HTTP/2使用HPACK压缩格式减少了请求和响应消息头的大小,从而减少了传输的数据量。

  3. 服务器推送:服务器可以“推送”资源到客户端,即在客户端明确请求之前就发送资源。这可以加速页面加载。

  4. 优先级和权重:客户端可以设置请求的优先级和权重,从而告诉服务器哪些资源更重要,应该优先发送。

  5. 二进制格式:HTTP/2消息使用二进制格式,这使得它们更易于解析,更高效,更少出错,与HTTP/1.x的文本格式相比。

  6. 流量控制:HTTP/2为每个流提供了流量控制,从而允许更细粒度的控制数据传输。

  7. 更安全:虽然HTTP/2本身并不强制使用TLS,但在实际应用中,大多数浏览器要求HTTP/2连接必须使用TLS。

  8. 减少了协议开销:由于多路复用、头部压缩等特性,HTTP/2减少了协议的开销,从而提高了性能。

总的来说,HTTP/2引入了许多新特性和改进,旨在提供更快、更高效、更可靠的Web体验。

4.3.1 http2.0有推出断点续传的功能嘛?我记得是加了一个帧字段的

是的,HTTP/2.0 对断点续传的支持得益于其引入的帧结构,特别是其中的 RST_STREAM 帧。

在 HTTP/2 中,通信是基于帧的,每个帧都属于某个特定的流。流是连接中的一个双向字节序列,可以承载一个或多个消息。RST_STREAM 帧允许对一个流进行中止,但并不关闭流。这为实现断点续传提供了可能。

当客户端或服务器需要中断某个特定的流,但不想关闭连接时,可以发送一个 RST_STREAM 帧。后续,如果需要重新开始传输,可以使用新的流 ID 重新开始,而不必重新建立连接。

但要注意,虽然 RST_STREAM 可以用于实现断点续传的某些场景,但 HTTP/2 本身并没有为断点续传定义特定的机制。实际的断点续传实现仍然依赖于如 RangeContent-Range 等 HTTP 头部字段。

总的来说,HTTP/2 的帧结构和流控制为更高效的断点续传提供了更多的可能性,但具体的实现仍然需要依赖于应用层的逻辑。

4.3.2 流量控制:HTTP/2为每个流提供了流量控制,从而允许更细粒度的控制数据传输。这里的每一个流是指http请求传输的数据量嘛还是单个tcp连接

在HTTP/2中,流量控制是基于“流”的概念实现的。这里的“流”并不是指HTTP请求传输的数据量,也不是单个TCP连接,而是HTTP/2协议中的一个抽象概念。

在HTTP/2中,一个“流”是指一个双向的字节序列,它属于一个已建立的TCP连接。一个TCP连接中可以有多个并发的流,每个流都有一个唯一的整数标识符。这些流可以用来并发地传输多个HTTP请求和响应,而不需要建立多个TCP连接。这就是HTTP/2的多路复用特性。

流量控制在HTTP/2中是为每个流实现的,而不是为整个TCP连接实现的。这意味着你可以为每个流独立地控制数据传输的速率,而不会影响到其他流。例如,你可以限制一个流的数据传输速率,而让另一个流以最大速率传输。

HTTP/2使用窗口更新机制来实现流量控制。每个流都有一个关联的窗口大小,表示允许对方发送的数据量。当数据被接收并处理后,接收方可以发送一个窗口更新帧来增加窗口大小,从而允许发送方发送更多的数据。

总的来说,HTTP/2的流量控制是基于每个流实现的,从而允许更细粒度地控制数据传输,而不仅仅是基于整个TCP连接。这为高效和灵活的数据传输提供了更多的可能性。

5 数据库

5.1 用过哪些数据库呢

答:mysql,redis,es

5.2 mongo db用过没

5.3 myisam和innodb引擎的主要区别

MyISAMInnoDB 是MySQL数据库中两种常见的存储引擎,它们在设计、特性和适用场景上有很大的不同。以下是它们之间的主要区别:

  1. 事务支持

    • InnoDB:支持事务(ACID兼容)。它有提交、回滚和崩溃恢复能力。
    • MyISAM:不支持事务。
  2. 锁定机制

    • InnoDB:使用行级锁定(行锁),这提供了更高的并发性,特别是在高负载下。
    • MyISAM:使用表级锁定(表锁)。
  3. 数据完整性和外键

    • InnoDB:支持外键和参照完整性,这有助于确保数据库的完整性。
    • MyISAM:不支持外键和参照完整性。
  4. 存储结构

    • InnoDB:存储其数据和索引在一个表空间中,可以有多个文件或一个大文件,取决于配置。
    • MyISAM:为每个表存储三个文件(.frm, .MYD, .MYI)。其中.frm为表定义文件,.MYD为数据文件,.MYI为索引文件。
  5. 崩溃恢复

    • InnoDB:由于其事务日志特性,InnoDB可以在崩溃后进行恢复。
    • MyISAM:可能需要更多的维护和修复工作,特别是在崩溃后。
  6. 全文索引

    • InnoDB:在MySQL 5.6及更高版本中支持全文索引。
    • MyISAM:支持全文搜索索引。
  7. 空间使用

    • InnoDB:通常使用更多的磁盘空间,因为它会为每个表存储数据和索引在同一个表空间中。
    • MyISAM:可能使用较少的磁盘空间,因为它将数据和索引存储在不同的文件中。
  8. 备份

    • InnoDB:可以使用热备份(即在服务器运行时备份)。
    • MyISAM:通常需要锁定表来进行备份。
  9. 使用场景

    • InnoDB:由于其事务支持和行级锁定,InnoDB更适合于需要高并发和数据完整性的应用。
    • MyISAM:由于其简单的存储机制和高效的读操作,MyISAM可能更适合于只读或大量读取的应用。

总的来说,选择哪种存储引擎取决于特定的应用需求。在许多现代应用中,InnoDB由于其事务支持和数据完整性特性而成为首选。然而,MyISAM在某些场景下,如只读应用或全文搜索,仍然可能是一个合适的选择。

5.4 说一下undo log,redo log和bin log的区别和用途

6 kafka

6.1 kafka的零拷贝机制

答:少了两次拷贝和2次系统调用,4次内核转换

7 实习

7.1 对你来说最难的一个需求

答:架构实例反向同步

8 大学社团经历

8.1 你觉得除了写代码的话,哪些东西对维护一个团队是最重要的呢

答:团队中的成员关系,各个组员的身体监控,发挥团队成员的长处

9 反问

9.1 还有几轮面试呢

答:看安排

9.2 多久出结果

答:一周面一次

9.3 base地可选嘛

答:对,珠海,广州和武汉

9.4 你们团队主要是在哪儿

答:主要是在广州这边,武汉有一个小的分组

你可能感兴趣的:(面经,服务端开发,金山)