头图

时间过的真快,转眼间国庆已经过去一周了,又到了新的一周,继续分享最新的面经。

今天分享的是粉丝在阿里巴巴的一面,考察了数据库、redis、kafka、ES和项目,数据库和redis不用多说,项目必用面试必考,其他内容也都挺常见的,感兴趣的朋友可以接着往下看。

可惜这位粉丝面试完后,面试流程上就已经显示挂了,挂了是小事,但是挂了之后不去复习和查漏补缺才是大事。

数据库

1. 分别介绍一下MySQL、ES、Mongo数据库各自的特点以及适合的使用场景是什么?

  • MySQL :是一种成熟的关系型数据库管理系统,支持SQL查询和复杂的事务处理,具有良好的数据一致性和安全性。它适合需要执行复杂查询、对数据一致性要求高的应用,例如企业级系统(如CRM、ERP)、财务软件以及任何需要严格ACID特性的场景。
  • Elasticsearch (ES) :是一个基于Lucene的分布式搜索和分析引擎,支持近实时的数据检索和全文搜索。它能够轻松处理大规模数据集,并提供强大的聚合和分析功能。适用于日志分析、网站或应用内搜索、实时数据分析、商业智能报告生成等场景,尤其在需要快速响应和高可扩展性的情况下表现优异。
  • MongoDB :是一种文档型NoSQL数据库,使用灵活的JSON风格文档存储数据,不需要固定的表结构,非常适合数据模型多变或不确定的应用。它提供了丰富的查询表达能力和内置的水平扩展机制,适用于内容管理系统(如博客、新闻站点)、社交网络平台、移动端后端服务、游戏开发以及物联网数据管理等领域。

ES

2. 倒排索引了解吗?

倒排索引是Elasticsearch中非常核心的概念,它使得全文搜索变得高效。

  • 定义:倒排索引是一种数据结构,用于存储文档集合中的单词到文档映射关系。简单来说,就是将每个词和包含这个词的所有文档关联起来。
  • 工作原理

    • 在正向索引中,系统会记录每篇文档的内容及其位置信息。
    • 而在倒排索引中,系统则会创建一个词汇表,并为每个词建立一个列表,列出所有包含该词的文档ID以及词在文档中的位置信息。

3. ES的分页功能有什么特性?

在Elasticsearch中,处理大量搜索结果时有几种常见的分页方法,每种方法都有其特点和适用场景:

  1. fromsize 分页

这是最基本的分页方式,类似于传统的SQL分页。你通过设置from参数来指定从哪条记录开始,用size参数来指定返回多少条记录。这种方式简单直观,但不适合大数据集的深分页。随着from值的增大,性能会显著下降,而且默认情况下最多只能返回10000条记录(可以通过配置调整这个限制)。

  1. scroll API

当你需要处理非常大的数据集时,可以使用scroll API。它创建一个快照,并允许你逐步滚动浏览所有数据。这种方式非常适合批量导出或数据分析,因为它不受10000条记录的限制。不过,scroll的数据不是实时更新的,且长时间保持打开的scroll可能会占用较多资源。

  1. search_after

search_after是一种高效的分页方式,特别适合需要高性能和实时数据更新的应用。它利用前一页的结果中的排序值作为下一次查询的起点,从而实现连续翻页。这种方式避免了from + size带来的性能问题,但不能直接跳到任意页,必须按顺序逐页翻阅。

4. ES的分词检索?

简单来说分词检索就是将文本拆分成一个个词汇(或称为“词项”),然后基于这些词汇进行搜索的过程:

  1. 文本输入:用户输入一段文本进行搜索。
  2. 分词:Elasticsearch使用分析器将这段文本分解成单独的词汇。例如,句子 "The quick brown fox" 会被分解成 ["The", "quick", "brown", "fox"]。
  3. 匹配:Elasticsearch在索引中查找包含这些词汇的文档。如果某个文档中的内容包含了这些词汇,那么这个文档就会被作为搜索结果返回。

通过这种方式,Elasticsearch能够快速找到与查询相关的文档,实现高效的全文搜索。

kafka

5. Kafka与Zookeeper是什么关系?

简单来说,Zookeeper就像是Kafka的协调员和管理员,帮助Kafka管理集群的状态和配置信息。

在Kafka集群中,每个Broker启动时都会在Zookeeper中注册自己的信息。这样一来,其他组件就可以通过Zookeeper找到这些Broker,从而进行消息的发送和接收。Zookeeper还负责管理和协调整个Kafka集群的状态。例如,当某个Broker宕机时,Zookeeper会帮助选举一个新的Controller节点来接管管理工作,确保集群的正常运行。

还有就是Kafka会将一些重要的元数据信息,比如主题的分区、副本等,存储在Zookeeper中。这些信息对于Kafka集群的正常运行至关重要。Zookeeper还帮助Kafka管理消费者组的状态,包括成员管理和偏移量提交。当消费者组发生变化时,Zookeeper会帮助实现再平衡,确保负载均衡。

6. 多个同样的消息被发送到Kafka如何控制他们只消费一个?

可以通过以下几种方法来确保即使有多个相同的消息被发送,也只消费其中一个:

  1. 幂等性生产者
    Kafka 0.11.0.0 版本引入了幂等性生产者。通过设置 enable.idempotence=true,生产者可以确保每条消息的唯一性。即使消息被多次发送,Kafka 也会保证每个分区中每条消息只会被写入一次。这样可以避免重复消息的产生。
  2. 事务性生产者
    如果你需要更复杂的逻辑,比如在多个主题或分区之间保持一致性和原子性,可以使用事务性生产者。事务性生产者允许你将一组消息作为一个事务提交,确保这些消息要么全部成功,要么全部失败。这可以在一定程度上防止重复消息的产生。
  3. 消费者端去重
    在消费者端,你可以实现一些逻辑来去重。常见的方法包括:

    • 使用外部存储:例如,可以使用Redis、数据库或其他存储系统来记录已经处理过的消息ID或内容。每次消费消息时,先检查这条消息是否已经被处理过。
    • 基于状态的去重:如果你的应用程序有某种状态管理机制,可以在状态中记录已处理的消息,并在处理新消息时进行检查。
  4. 业务逻辑去重
    在某些情况下,可以通过业务逻辑来确保消息的唯一性。例如,如果你的消息包含一个唯一的标识符(如订单ID),可以在消费消息时检查这个标识符是否已经存在。如果存在,则跳过该消息的处理。

7. 什么是Kafka的羊群效应?

Kafka的羊群效应是指在使用ZooKeeper作为协调服务时,当ZooKeeper中的某个被监控的znode(节点)发生变化时,所有监听该节点的客户端都会收到通知,并且可能会同时采取行动。这种现象可能导致短时间内大量的客户端请求涌向系统,从而引起网络拥塞、服务器负载激增,甚至导致服务不可用。

在Kafka中,消费者组通常会通过ZooKeeper来管理成员关系和分区分配。如果一个消费者加入或离开消费者组,或者某个Topic的分区重新分配,ZooKeeper上的相关znode会发生变化,这将触发所有相关的消费者去更新它们的状态以保持一致性。如果这个过程中有大量的消费者同时尝试重新平衡,那么就可能出现羊群效应。

redis

8. Redis相比Memcached有哪些优势?

Redis 和 Memcached 都是内存数据库,但 Redis 在功能和灵活性上要强大得多:

Redis 支持多种数据结构,比如字符串、列表、集合、哈希表等,而 Memcached 主要只支持简单的键值对存储。这就意味着在 Redis 里,你可以用更丰富的数据结构来处理复杂的数据操作,而在 Memcached 里就相对单一一些。

Redis 可以把数据持久化到磁盘上,这样即使服务器重启了,数据也不会丢失。这对于需要长期保存数据的应用来说非常重要。相比之下,Memcached 的数据只存储在内存中,一旦重启,数据就会消失。

Redis 支持主从复制,也就是说你可以配置多个从节点来提高读取性能和实现高可用性。这在大规模分布式系统中非常有用。而 Memcached 没有内置的主从复制功能,需要通过外部工具或应用层来实现。

Redis 支持发布/订阅模式,可以方便地进行消息传递。这对于实时通信或者事件驱动的应用来说非常方便。Memcached 就没有这个功能。

Redis 还支持事务,可以在一个命令序列中执行多个操作,并保证这些操作的原子性。这对于需要保证数据一致性的场景非常有用。Memcached 则不支持事务。

Redis 支持在服务器端执行 Lua 脚本,可以处理复杂的业务逻辑。这样可以减少网络开销,提高效率。Memcached 就没有这样的脚本支持。

9. 阐述缓存穿透?怎么解决?

缓存穿透其实是一个常见的问题,特别是在使用缓存系统时。简单来说,缓存穿透是指当用户请求一个不存在的数据时,缓存中没有这个数据,于是请求会直接打到后端数据库。如果这种请求频繁发生,就会导致大量的无效请求直接到达数据库,增加数据库的负载,甚至可能导致数据库崩溃。

举个例子,假设有一个电商网站,用户在搜索一个根本不存在的商品时,缓存里没有这个商品的信息,所以每次搜索都会直接去查数据库。如果有人恶意地大量请求这些不存在的商品,数据库就会承受很大的压力。

有几种常用的方法可以解决这个问题

  1. 布隆过滤器(Bloom Filter)

    • 你可以使用布隆过滤器来预先判断某个请求的数据是否可能存在于数据库中。布隆过滤器是一种高效的空间节省型概率数据结构,它可以告诉你某个元素“肯定不在集合中”或“可能在集合中”。如果布隆过滤器判断某个请求的数据肯定不在数据库中,那么就可以直接返回空结果,而不需要再去查询数据库。
  2. 缓存空值

    • 当你从数据库中查询到一个不存在的数据时,可以把这个空结果也缓存起来,并设置一个较短的过期时间(比如几分钟)。这样,下次再有相同的请求时,可以直接从缓存中返回空结果,而不是每次都去查询数据库。
  3. 接口层限流

    • 你可以在应用层或API网关上设置一些限流策略,限制对某些特定接口的访问频率。这样即使有恶意请求,也不会对数据库造成太大的影响。
  4. 业务逻辑优化

    • 有时候可以通过业务逻辑来避免一些不必要的查询。例如,在前端输入验证时,可以提前过滤掉一些明显无效的请求。

10. 什么是bigkey?会有什么影响?

BigKey其实是指在Redis或其他键值存储系统中,那些占用大量内存空间的键。比如说,一个键关联了一个非常大的字符串、列表、集合或哈希表等数据结构。这些键因为数据量大,所以被称为BigKey。

BigKey的影响:

BigKey可能会带来一些问题,主要有以下几点:

  1. 性能下降

    • 当你操作BigKey时,比如读取或写入,Redis需要处理大量的数据,这会导致单次操作的时间变长。如果这些操作频繁发生,整个系统的响应时间就会变慢,用户体验也会受到影响。
  2. 阻塞其他请求

    • Redis是单线程的,这意味着在同一时间只能处理一个请求。如果有一个BigKey的操作正在进行,那么其他所有的请求都得排队等待。这样一来,一个小的操作就可能阻塞整个系统,导致其他请求被延迟。
  3. 内存碎片

    • 大型的数据结构可能会导致内存碎片化,尤其是在数据频繁更新的情况下。内存碎片多了,Redis的整体性能和内存利用率都会受到影响。
  4. 持久化和复制问题

    • 如果你在使用Redis的持久化功能(如RDB快照或AOF日志),BigKey会增加持久化文件的大小,延长持久化的时间。同样,在主从复制过程中,BigKey也会增加网络传输的负担,影响复制的速度和效率。

欢迎关注 ❤

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

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

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


王中阳Go
805 声望297 粉丝