4/8 美团实习转正面试···过了!
- 作者
- Name
- 青玉白露
- Github
- @white0dew
- Modified on
- Reading time
- 12 分钟
阅读:.. 评论:..
https://www.nowcoder.com/feed/main/detail/a98f1d0b65894e4999478282ca2fc3df
下面我将分享一位同学在美团转正实习到店平台技术部的一面面试经历,他的评价是,面试官很友好,问题全面,充分考察了对Kafka和MySQL的理解。如果你对后端开发感兴趣,这次面试的内容绝对值得一读。
【提醒】通过这次面试经验,你将可以复习到以下知识点:
- ZooKeeper节点持久化方式
- Kafka的存储单元和存储过程
- Kafka消息索引和消费模式
- Kafka事务和一致性保证
- MySQL索引类型和存储引擎
- 事务的实现和数据库锁机制
面试官: 你好,欢迎来到美团的面试。我先介绍一下我们部门的业务和实习具体事项。然后我们直接进入技术面试环节。首先,请你告诉我ZooKeeper节点的持久化方式。
求职者: ZooKeeper中的节点(ZNode)有两种类型:持久化节点和临时节点。持久化节点会一直存储在ZooKeeper中,直到显式删除。节点的数据存储在硬盘上,并且会在集群中的所有服务器间进行复制,以保证数据的持久性和一致性。
面试官: 很好。那么,你知道Kafka的最小存储单元是什么吗?
求职者: Kafka的最小存储单元是Message。在Kafka内部,Messages被组织成Topic和Partition。Topic是消息的类别或者说是消息的发布订阅的频道,Partition则是物理上的分组,每个Partition内部消息是有序的。
面试官: 接下来,谈谈Kafka数据存储过程。
求职者: 当Kafka的生产者发布消息时,消息首先被写入到内存中的一个缓冲区。然后,这些消息会被追加到对应Partition的日志文件中。为了提高性能,Kafka会批量地将缓冲区中的消息写入磁盘,并且使用索引文件来记录每个消息在日志文件中的位置,以便快速查找。
面试官: Kafka的Topic的每个分区是否独立?请说明。
求职者: 是的,Kafka中Topic的每个分区是独立的。每个Partition可以被不同的Broker所管理,而且每个Partition都有自己的日志文件。这种设计可以支持数据的水平扩展和并行处理。
面试官: 那么,生产者或消费者是如何根据索引找到消息的?
求职者: Kafka的索引机制是通过一个简洁的索引文件,记录了每个Message的offset和对应的物理位置。当需要找到特定消息时,消费者可以通过offset来查找索引文件,快速定位到消息在日志文件中的位置,并读取消息。
面试官: 那么,在Kafka的索引文件中,key和value分别存储的是什么?
求职者: 在Kafka的索引文件中,key存储的是消息的offset,value存储的是这个offset对应的消息在日志文件中的物理位置。
面试官: Kafka是使用推模式还是拉模式来进行消息消费的?
求职者: Kafka使用拉模式(pull-based)来进行消息消费。消费者主动从Broker拉取数据,而Broker不会主动推送。
面试官: 为什么要使用拉模式而不是推模式?
求职者: 拉模式可以让消费者根据自己的处理能力来获取数据,避免了推模式中的数据洪泛问题,即消费者可能因为处理不过来而导致数据丢失。拉模式还可以让消费者更灵活地控制数据读取的位置,比如可以重读之前的数据。
面试官: 那么,消费者是如何记录消费位置的,这个位置信息存在哪里?
求职者: 消费者使用一个叫做offset的值来记录每个分区中已经消费到的位置。这些offset信息通常会被存储在Kafka的一个内部Topic中名为__consumer_offsets
,消费者可以从这个Topic中读取或更新自己的offset。
面试官: 在消费者组里面,每个消费者是独立的吗?
求职者: 在消费者组中,每个消费者负责消费不同的Partition。消费者之间是协同工作的,它们共同完成Topic中所有Partition的消息消费。同时,每个消费者也是独立的,因为它们各自有自己的offset。
面试官: 一个分区能被同一消费者组中的几个消费者消费吗?为什么?
求职者: 在同一个消费者组中,一个分区在同一时刻只能被一个消费者消费。这是为了保证Partition内消息的顺序消费不被打乱,如果多个消费者并行消费同一个Partition,消息的顺序就无法保证了。
面试官: Kafka为什么能顺序消费?
求职者: Kafka能够顺序消费的原因是它在每个Partition内部是按照消息写入的顺序来存储的,并且消费者在消费时也是按照这个顺序来读取消息。
面试官: Kafka支持事务吗?
求职者: 是的,从0.11版本开始,Kafka开始支持事务。生产者可以发送事务性的消息,保证消息要么都成功写入到目标Partition,要么都不写入。
面试官: Kafka能保证一致性吗?为什么?
求职者: Kafka可以在一定程度上保证一致性,尤其是在使用事务时。Kafka保证在一个Partition内,消息的顺序是一致的。通过配置和使用事务,Kafka也能保证跨多个Partition的写操作要么全部成功,要么全部失败。不过,在分布式系统中,完全的一致性是很难保证的,因为可能会有网络延迟、服务器故障等因素。
面试官: 生产者将消息生产到Kafka后,消息是怎么写到磁盘上的?
求职者: Kafka的生产者将消息发送到Broker后,Broker首先会将消息写入到操作系统的页缓存(page cache)。然后通过后台的I/O线程异步地将页缓存中的数据刷新到磁盘上。
面试官: 那么,如何保证消息不被重复消费?
求职者: 为了保证消息不被重复消费,可以在消费端实现幂等性,也可以在业务逻辑中对消息进行去重处理。同时,Kafka 0.11版本之后引入了幂等生产者和事务生产者,可以防止生产者发送重复的消息。
面试官: Kafka的数据存储是基于磁盘还是内存的?
求职者: Kafka的数据存储基于磁盘,但它大量利用了操作系统的页缓存。由于Kafka的顺序写操作特性,它能够高效利用磁盘带宽,同时也能够通过页缓存来提供近似内存的读取速度。
面试官: 那为什么Kafka的性能这么高?
求职者: Kafka的高性能主要来自于它的设计上对顺序读写的优化,包括零拷贝技术和页缓存的使用。顺序读写比随机读写在磁盘上有更高的速度和更低的查找成本。同时,零拷贝技术减少了数据在用户态和内核态之间的传输,进一步提高了性能。
面试官: 说说顺序写和非顺序写有什么区别?
求职者: 顺序写操作是指数据被连续写入存储介质,这样的操作通常会有很高的写入效率并且减少磁盘寻址的时间。而非顺序写则是随机的写入过程,会导致存储介质寻址时间增加,从而降低写入效率。
面试官: 解释一下**零拷贝(Zero-Copy)**技术。
求职者: 零拷贝技术是指在数据传输过程中,减少或消除数据在用户空间和内核空间之间的拷贝次数,直接从内核空间传输到Socket缓冲区。这样做可以减少CPU的拷贝操作,降低上下文切换的成本,从而提高数据传输的效率。
面试官: 很好,现在我们转到MySQL。你知道MySQL的索引有哪几种?
求职者: MySQL主要有B-Tree索引和哈希索引,还有全文索引和空间索引等。
面试官: 那么,B+树和B树有什么区别?
求职者: B树的节点中既存储数据也存储键,而B+树的所有数据都在叶子节点中,并且叶子节点之间有链表连接。B+树的非叶子节点只存储键,不存储数据,这使得B+树能够有更多的分支,降低树的高度,提高查询效率。
面试官: 好的,那你能介绍一下MySQL的存储结构吗?
求职者: MySQL的存储结构主要包括表空间、数据文件和索引文件。InnoDB存储引擎将数据存储在表空间中,表空间由多个数据文件组成。数据和索引都存储在这些文件中,而且InnoDB使用B+树作为其索引结构。
面试官: 谈谈InnoDB与MyISAM的区别。
求职者: InnoDB支持事务处理和行级锁,提供了ACID事务支持,有更强的并发处理能力,同时支持外键。MyISAM不支持事务和行级锁,它的查询速度快,但是在写操作和并发读写时性能不如InnoDB。
面试官: B+树的叶子节点是单向链表还是双向链表,为什么?
求职者: B+树的叶子节点是通过双向链表连接的。这样可以支持范围查询操作,因为可以顺序地访问叶子节点中的数据。双向链表还允许在范围查询中向前或向后遍历。
面试官: 叶子节点存储的数据是固定的吗?
求职者: 不是固定的。叶子节点中存储的数据量取决于数据的大小和B+树页面的大小。MySQL会尽量充分利用每个叶子节点的空间,但叶子节点的数据量会因为数据的不同而变化。
面试官: 那么,一个叶子节点能存多条数据吗?
求职者: 能的。一个叶子节点可以存储多条数据记录,具体数量取决于记录的大小和叶子节点的大小。 面试官: 在MySQL中,支持哪些事务?
求职者: MySQL支持ACID事务,包括原子性、一致性、隔离性和持久性。InnoDB存储引擎提供了对这些事务的全面支持。
面试官: 你了解MySQL是如何实现事务的吗?
求职者: MySQL中,事务是通过InnoDB存储引擎实现的。InnoDB使用了一系列技术来实现事务,包括多版本并发控制(MVCC)、redo log和undo log。
面试官: 那为什么要有redo log?
求职者: redo log是InnoDB实现持久性的关键。当事务提交时,先写redo log而不是直接写磁盘,这可以确保即使发生系统崩溃,事务也不会丢失,因为事务可以通过redo log恢复。
面试官: undo log和redo log里面记录的是物理数据还是逻辑数据?
求职者: redo log记录的是物理数据,也就是说它记录了数据页改变的具体字节。而undo log记录的是逻辑数据,它保存了事务开始前数据的状态,用于在事务失败时进行回滚。
面试官: MySQL锁一行有哪些方式?
求职者: MySQL可以使用行级锁来锁定一行数据。InnoDB存储引擎主要提供了两种类型的行级锁:共享锁(S锁)和排他锁(X锁)。共享锁允许事务读取一行数据,排他锁允许事务更新或删除一行数据。
面试官: 单纯的select对表加锁了吗?
求职者: 通常情况下,单纯的select操作不会加锁,因为InnoDB默认的隔离级别是可重复读,它使用了MVCC来避免加锁。但如果使用了select ... for update这种语句,那么会加上排他锁。
面试官: update,delete,insert会加锁吗?加什么锁?
求职者: 是的,update、delete和insert操作会加锁。这些操作通常会加上排他锁,因为它们需要修改表中的数据。
面试官: MySQL的自增ID能回滚吗?
求职者: 自增ID在事务回滚时不会回滚。如果事务失败,自增ID生成的值不会被重用。
面试官: 最后一个问题,假设你拿到一个字符串,你需要删除尽可能少的字符,使得剩下的字符串中不含有最长偶数长度的回文子串,你会怎么做?
求职者: 这是一个动态规划问题,我会先写一个函数来判断一个字符串是否是偶数长度的回文串,然后我会尝试删除每一个字符,用递归的方式来查找删除最少字符的情况。
面试官: 好,你有什么想问的吗?
求职者: 是的,我想问一下,美团到店平台技术部在日常开发中主要使用哪些技术栈?并且实习生在这里能得到什么样的成长机会?
面试官: 我们技术部主要使用Java、Spring Boot等技术栈进行后端开发。对于实习生,我们提供了完善的培训机制,你将有机会参与到真实项目中,通过项目经验的积累,快速提升自己的技术能力和业务理解。
求职者: 非常感谢您的解答,我对于美团到店平台技术部的实习岗位充满期待。
面试官: 很好,我们也希望你能加入我们。今天的面试就到这里,我们会尽快给你反馈。祝你今天过得愉快!