新的一周又来了,今天分享的是上海某公司的一面面经,内容主要就是go、mysql和项目,职位要求如下:
发现一个很有意思的点—有php转go项目经验者优先。想不到还有这种好事,本人就是php转go,跟我有相同经历的朋友可以加我微信,我们一起聊聊。
面试问题
Go 相关
往已关闭的channel里读写数据会发生什么?
- 写操作:向已关闭的channel写入数据会导致运行时panic。
- 读操作:从已关闭的channel读取数据会立即返回,如果channel中还有值,则按顺序返回剩余值;当channel为空后,读操作将返回channel类型的零值。
Channel的底层原理
Go语言中的channel是通过一个结构体实现的,这个结构体包含了一个队列来存储发送到channel的数据元素。当一个goroutine向channel发送数据时,数据会被添加到这个队列中;另一个goroutine从channel接收数据时,它会从队列中移除数据。channel可以是带缓冲或无缓冲的,无缓冲channel在发送方和接收方同步时直接传递数据,而带缓冲channel则允许在没有接收方的情况下暂存数据。
GMP调度
Go的并发模型基于Goroutines(G)、M(Machine)和P(Processor)。每个程序开始时都会创建一个运行时,运行时负责管理所有的Goroutines。P代表逻辑处理器,用于执行任务;M是一个操作系统线程,可以执行用户代码或运行时代码;G是用户定义的goroutine。运行时使用工作窃取算法来平衡各个P上的负载,确保高效利用多核处理器。
Go的协程之间要如何通信?
Go推荐使用channel进行协程间的通信。通过channel,协程可以安全地交换数据而无需担心竞态条件。此外,也可以使用互斥锁等同步原语来保护共享资源。
MySQL 相关
Explain里哪些指标需要关注?
在MySQL的EXPLAIN输出中,应该关注以下指标:
type
:连接类型,显示了表之间的连接方式,如全表扫描、索引扫描等。key
:实际使用的索引。rows
:查询优化器估计为了找到所需行必须检查的行数。Extra
:提供了关于MySQL如何解析查询的额外信息,例如是否使用临时表、排序等。
这些指标对SQL性能从低到高分别有哪些?
- 全表扫描(ALL)通常是最慢的,因为它需要扫描整个表。
- 索引范围扫描(range)比全表扫描快,但仍可能涉及大量行。
- 使用索引(ref, eq_ref, const)可以显著提高查询速度,因为它们限制了需要访问的行数。
- 索引覆盖(index)是指查询可以在索引树中完成,而不需要回表查找数据,这通常是最快的。
MySQL的事务了解吗?什么是事务的ACID?
事务是一系列操作,作为一个整体一起成功或者一起失败。ACID是事务的四个基本特性:
- 原子性(Atomicity):事务的所有操作要么全部完成,要么完全不发生。
- 一致性(Consistency):事务前后数据库保持一致状态。
- 隔离性(Isolation):并发事务的执行结果与串行执行的结果相同。
- 持久性(Durability):一旦事务提交,其效果就是永久性的,即使系统发生故障也不会改变。
事务的ACID分别是怎么保证的?
- 原子性:通过事务日志记录事务的操作,如果事务失败,可以根据日志回滚到事务开始前的状态。
- 一致性:通过约束机制确保事务执行前后数据的一致性。
- 隔离性:通过锁定机制或其他并发控制策略来实现,比如MVCC(多版本并发控制)。
- 持久性:事务提交后,确保数据已经写入到持久存储中,即使系统崩溃也能恢复。
Redo Log、Undo Log、BinLog有哪些区别?
- Redo Log:重做日志,用于记录事务对数据页所做的修改,以便在实例恢复时能够重做这些修改,保证数据的持久性和一致性。
- Undo Log:撤销日志,用于支持事务的回滚操作,并且在MVCC中用于提供事务开始时的数据快照。
- BinLog:二进制日志,记录了所有更改数据库的数据事件,用于数据恢复、复制和审计。
BinLog文件有几种格式类型?分别有哪些优劣?
- Statement:记录的是SQL语句,适用于大多数情况,但不能处理某些非确定性操作,如
UUID()
函数。 - Row:记录的是每行数据的变化,可以准确地反映数据变化,但日志量较大。
- Mixed:结合了前两种格式的优点,自动选择合适的格式来记录日志。
主从复制的原理是什么?复制的类型有几种?
主从复制的基本原理是主服务器将更改操作记录到二进制日志中,从服务器通过I/O线程读取这些日志并保存到本地的中继日志,然后通过SQL线程执行这些日志中的操作来保持与主服务器数据的一致性。
复制类型主要有:
- 异步复制:最常用的复制方式,主服务器不等待从服务器确认即可继续处理新的请求。
- 半同步复制:主服务器在收到至少一个从服务器的确认后才会认为事务已提交。
- 同步复制:所有从服务器都确认后主服务器才提交事务,这种方式延迟较高。
数据写入redo log是不是一定不会丢失?
不是绝对的。虽然redo log是设计用来防止数据丢失的,但如果在数据写入redo log后但在数据真正持久化之前系统发生故障,仍然可能导致数据丢失。但是,一旦事务提交并且redo log条目已经被写入磁盘,那么即使系统崩溃,恢复过程中也可以根据这些日志恢复未完成的事务。
Buffer Pool是什么?有什么作用?Buffer Pool满了之后会发生什么?
- Buffer Pool:是InnoDB存储引擎中的内存区域,用于缓存表的数据和索引页面,目的是减少磁盘I/O操作,提高查询性能。
- 作用:加快数据检索速度,减少磁盘读写次数。
- 满了之后:当Buffer Pool满时,InnoDB会使用LRU(最近最少使用)算法来替换旧的数据页,为新读取的数据页腾出空间。如果数据页被频繁访问,可能会导致频繁的页面替换,从而影响性能。
项目
- 为什么要重构?
- 项目中的业务流程问题你是怎么梳理的?用哪些工具梳理?
- 为什么通过canal与binlog来校验和修复数据?你还有其他方案吗?
- 是采用批量校验吗?
- 重构的周期大概多久?
- 分片计算肯定要消耗大量资源,这里你一共部署来几台实例呢?
- 项目中你是如何进行深度分页优化的?除了用lastId,有没有其他方案?
- 谈谈你对DDD的理解