头图

继续分享最新的面经,前面发的两篇大家也可以看看:

今天分享的是golang开发岗面经,要求是3年以上golang开发经验,薪资为15~30K,整体面下来的感受就是,面的比较广,细节拷打不多,来看看难度如何:

面试题详解

1. GMP调度

GMP调度模型是Go语言运行时的核心调度机制,用于实现高效的并发执行。G代表Goroutine(协程),M代表Machine(操作系统线程),P代表Processor(处理器)。

  • Goroutine 是用户态的轻量级线程,由Go运行时管理,创建和销毁成本低。
  • Machine 是操作系统线程,负责真正执行代码,每个M可以绑定一个或多个G。
  • Processor 是逻辑处理器,用于分配任务给M,并维护本地队列中的G。

调度过程:

  1. 每个P维护一个本地队列,存放待执行的G。如果本地队列为空,会从全局队列或其他P的队列中偷取任务(Work Stealing)。
  2. 当一个G阻塞时(如I/O操作),M会释放当前P并寻找其他可执行的G,从而避免浪费资源。
  3. 如果所有M都在忙,而有新的G需要执行,运行时会动态创建新的M来满足需求。

这种调度方式的优点是高效利用多核CPU,减少了上下文切换的开销,同时支持大量并发任务。


2. 协作式调度和抢占式调度有什么区别

协作式调度抢占式调度 是两种不同的任务调度方式,主要区别在于任务的执行控制权归属:

  • 协作式调度

    • 任务主动让出CPU,只有当前任务完成或显式调用让出函数时,调度器才能切换到其他任务。
    • 缺点是如果某个任务长时间占用CPU而不让出,会导致其他任务“饿死”。
    • 优点是实现简单,上下文切换开销小,适合任务间信任度高的场景。
  • 抢占式调度

    • 调度器通过定时器中断等方式强制剥夺当前任务的CPU使用权,确保公平性。
    • 优点是可以防止某个任务独占CPU,保证系统的响应性和公平性。
    • 缺点是上下文切换频繁可能导致性能开销增大。

在现代操作系统中,抢占式调度更为常见,因为它能更好地应对复杂任务环境。而协作式调度更多用于嵌入式系统或特定领域。


3. 垃圾回收讲一下,三色标记和混合写屏障

垃圾回收(GC)是一种自动内存管理机制,用于回收不再使用的对象,避免内存泄漏。常见的GC算法包括引用计数、标记清除、分代回收等。

三色标记 是一种经典的GC算法,其核心思想是将对象分为三种状态:

  • 白色:尚未被访问的对象,表示可能需要回收。
  • 灰色:已被访问但其引用的对象尚未完全扫描,表示正在处理中。
  • 黑色:已被访问且其引用的对象也已扫描完毕,表示安全存活。

GC过程:

  1. 初始时,所有对象为白色。
  2. 从根对象(如全局变量、栈变量)开始,将可达对象标记为灰色。
  3. 不断从灰色对象集合中取出对象,将其引用的对象标记为灰色,自身标记为黑色。
  4. 当灰色集合为空时,剩余的白色对象即为不可达对象,可被回收。

混合写屏障 是一种优化技术,用于解决三色标记中的并发问题。当GC与程序并发运行时,可能会出现新引用导致对象状态不一致的情况。混合写屏障通过记录修改过的引用,确保GC能够正确识别对象状态,从而提高效率和安全性。


4. 事务执行中,mysql如果宕机了,重新恢复会发生什么?

MySQL使用事务日志(Redo Log和Undo Log)来保证数据一致性。如果在事务执行过程中发生宕机,重启后会通过以下步骤恢复:

  1. 检查Redo Log:Redo Log记录了事务对数据页的物理修改,即使事务未提交,修改也会先写入日志。重启后,MySQL会重放Redo Log,将未持久化的修改应用到数据页上。
  2. 检查Undo Log:Undo Log记录了事务的回滚信息。对于未提交的事务,MySQL会使用Undo Log撤销已完成的部分操作,确保事务原子性。
  3. 崩溃恢复:MySQL的InnoDB引擎会在启动时执行崩溃恢复流程,将未完成的事务标记为回滚状态,并清理相关的日志文件。

通过这种方式,MySQL能够在宕机后恢复到一致状态,保证事务的ACID特性。


5. 讲一下两阶段提交的过程,两阶段提交解决什么问题?

两阶段提交(2PC, Two-Phase Commit)是一种分布式事务协议,用于协调多个节点之间的事务提交,确保分布式系统中的一致性。

过程

  1. 准备阶段

    • 协调者向所有参与者发送Prepare请求,询问是否可以提交事务。
    • 参与者执行事务操作,并将结果写入日志,然后回复Yes或No。
  2. 提交阶段

    • 如果所有参与者都回复Yes,协调者发送Commit请求,参与者正式提交事务。
    • 如果有任何参与者回复No,协调者发送Abort请求,参与者回滚事务。

解决的问题

  • 2PC解决了分布式系统中事务的原子性问题,即要么所有节点都提交事务,要么全部回滚。
  • 它适用于强一致性要求的场景,但存在单点故障(协调者故障)和性能瓶颈等问题。

6. 讲一下MVCC,它解决了幻读问题吗?

MVCC(多版本并发控制)是一种数据库并发控制机制,通过保存数据的多个版本来实现高并发读写。

原理

  • 每次更新数据时,都会生成一个新的版本,旧版本保留供读取。
  • 读操作只访问符合当前事务隔离级别的版本,避免了读写冲突。

解决的问题

  • MVCC有效解决了读写冲突问题,提高了并发性能。
  • 在可重复读(Repeatable Read)隔离级别下,MVCC通过版本控制避免了不可重复读问题。
  • 对于幻读问题,MVCC在某些情况下可以通过间隙锁(Gap Lock)结合版本控制部分解决,但在串行化(Serializable)级别下,仍需依赖锁机制来完全避免幻读。

7. redis的跳表了解吗?

跳表(Skip List)是一种基于链表的数据结构,通过多层索引加速查找操作,时间复杂度接近O(log n)。

Redis中的跳表主要用于实现有序集合(Sorted Set)。

  • 跳表的每一层是一个有序链表,越高层的链表包含的节点越少。
  • 查找时从最高层开始,快速缩小范围,然后逐层向下定位目标节点。
  • 插入和删除操作也通过多层索引进行维护,保证整体效率。

跳表的优点是实现简单,性能稳定,适合Redis这种高性能场景。


8. Redis大key会有什么问题?怎么解决?

问题

  • 大key指的是存储大量数据的单个键,可能导致Redis性能下降。
  • 内存占用过高,增加GC压力,甚至引发OOM(内存溢出)。
  • 操作大key可能导致阻塞,影响其他请求的响应时间。

解决方案

  • 拆分大key:将大key拆分为多个小key,分散存储。
  • 使用合适的数据结构:例如,将Hash、List等结构改为分片存储。
  • 渐进式删除:通过脚本逐步删除大key,避免一次性操作引发阻塞。
  • 监控和优化:定期分析Redis内存使用情况,及时发现和处理大key。

9. kafka如何解决消息有序问题?

Kafka通过分区(Partition)机制保证消息的有序性。

  • 每个分区内的消息是严格有序的,按照写入顺序存储和消费。
  • 生产者可以指定消息的分区键(Key),相同Key的消息会被路由到同一分区,从而保证局部有序。

消费者组内的消费者按分区消费,每个分区只能被一个消费者消费,进一步确保顺序性。

需要注意的是,跨分区的消息无法保证全局有序,若需要全局有序,需将所有消息写入同一个分区。


10. 如何保障kafka消息不丢失?

保障Kafka消息不丢失需要从生产者、Broker和消费者三个层面入手:

  1. 生产者

    • 设置acks=all,确保消息写入所有副本后才返回成功。
    • 启用重试机制,处理网络异常等情况。
  2. Broker

    • 配置副本数大于1,启用ISR(同步副本集)机制,确保数据冗余。
    • 定期备份数据,防止磁盘损坏导致丢失。
  3. 消费者

    • 手动提交偏移量,在业务逻辑处理完成后提交,避免重复消费或丢失。
    • 设置合理的消费超时时间,防止消费者挂起导致消息堆积。

通过以上措施,可以在绝大多数情况下保障消息不丢失。


11. 链上操作了解吗?

链上操作通常指区块链上的交易或智能合约执行。

  • 交易:用户发起的操作,如转账、调用智能合约等,需要经过共识机制验证后写入区块链。
  • 智能合约:部署在链上的代码,通过交易触发执行,具有自动化和不可篡改的特性。

链上操作的特点:

  • 透明性:所有操作记录公开可查。
  • 不可篡改:一旦写入区块链,无法修改。
  • 去中心化:无需信任第三方,由共识机制保证安全。

链上操作的挑战包括性能瓶颈、Gas费用高昂等问题,因此在实际应用中需权衡成本与效率。

欢迎关注 ❤

我们搞了一个免费的面试真题共享群,互通有无,一起刷题进步。

没准能让你能刷到自己意向公司的最新面试题呢。

感兴趣的朋友们可以加我微信:wangzhongyang1993,备注:面试群。


王中阳讲编程
836 声望324 粉丝