---
url: /notes/面试/真实面经/武汉中交希迪科技/index.md
---
## ES查数据为什么快？它是模糊搜索，为什么可以实现很快的模糊检索出来？

**倒排索引**，基于Lucene，与传统结构化数据库按行存储不同，倒排索引将文档中的每个词项映射到包含改词项的文档id列表

## Term    | Document IDs

"apple" | \[1, 3, 5]
"banana"| \[2, 4]

高效查找：搜索时直接定位词项对应的文档列表，避免全表扫描

预处理与分词：在索引阶段，文本会经过分词（Tokenization）、小写转换、去除停用词等处理。

模糊搜索优化：

* **前缀查询（Prefix Query）**：使用倒排索引直接匹配词项前缀，例如`app*`会匹配`apple`、`application`等。
* **通配符与正则表达式**：
  * **Wildcard Query**：对`*`和`?`通配符，ES使用自动机理论优化模式匹配。
  * **正则表达式**：转换为有限状态机（FSM）进行高效匹配。
* **编辑距离模糊查询（Fuzzy Query）**：
  * 使用**Levenshtein自动机**生成所有可能的候选词（如`apple`的编辑距离为1的词：`appl`、`apples`等），再与倒排索引中的词项匹配。
  * 通过限制最大编辑距离（默认2）避免组合爆炸。
* **N-gram分词**：
  * 通过自定义分词器（如`edge_ngram`），将词拆分为更小的片段（例如`apple` → `a`, `ap`, `app`, `appl`, `apple`）。
  * 模糊查询（如`app*`）可直接匹配这些片段，无需遍历所有词项。

**分片**，数据被分割成多个分片（Shard），分布在集群节点上。查询时，ES并行搜索所有相关分片，合并结果后返回。

## es匹配模式

精确匹配（Exact Match）

```json
 term   查询：用于精确匹配单个值，不会对查询词进行分词。
{
  "query": {
    "term": {
      "age": 18
    }
  }
}
 terms   查询：用于精确匹配多个值。
{
  "query": {
    "terms": {
      "age": [18, 19]
    }
  }
}
 ids   查询：根据文档ID进行精确匹配。
{
  "query": {
    "ids": {
      "values": ["doc1", "doc2"]
    }
  }
}
```

全文匹配（Full-Text Match）

```json
 match   查询：对字段进行全文搜索，查询词会被分词处理，然后匹配包含这些词的文档。
{
  "query": {
    "match": {
      "content": "Elasticsearch search engine"
    }
  }
}
•   match_phrase   查询：要求匹配的词条必须按照原始文本顺序相邻出现。
{
  "query": {
    "match_phrase": {
      "content": "Elasticsearch search engine"
    }
  }
}
•   multi_match   查询：在多个字段上执行  match  或  match_phrase  查询。
{
  "query": {
    "multi_match": {
      "query": "Elasticsearch search engine",
      "fields": ["title", "content"]
    }
  }
}
```

模糊匹配（Fuzzy Match）

前缀匹配（Prefix Match）

区间匹配（Range Match）

组合查询（Composite Query）

## es和数据库数据同步

删除数据，每个查询时，比对数据库和es，不存在的数据就从es删除

## kafka保证消息消费

生产者，设置确保消息写入所有副本 acks = all

```
acks=0  ：发送后不等待确认（Fire-and-Forget 模式）
适用场景：适用于对数据可靠性要求不高，但对性能要求极高的场景，例如日志收集或监控数据。
 
acks=1  ：等待 Leader 确认
适用场景：适用于对数据可靠性有一定要求，但可以容忍偶尔数据丢失的场景，例如事件流系统。

acks=all  （或   -1  ）：等待所有 In-Sync 副本确认
适用场景：适用于对数据可靠性要求极高的场景，例如金融系统或订单管理系统。
```

发送失败重试

消费者，手动提交offset

重试

## 服务器出现out of memory问题时，你会如何监控和处理？

linux系统使用top查询内存占用情况

监控工具，报警信息推送

定期清理无用文件

## apache poi复杂报表场景

合并表格，图表

## 多数据源实现

使用ThreadLocal存储当前线程中正在使用的数据源key

继承AbstractRoutingDataSource，重写determineCurrentLookupKey，从ThreadLocal中获取当前数据源的key

定义切面使用自定义注解自动切换

## 常用设计模式

单例：确保一个类在整个程序运行过程中只有一个实例，并提供全局访问；资源管理，全局配置，日志记录

工厂：根据传入的参数创建并返回不同类型的对象实例

建造者：将复杂对象的构建过程与其表示分离。

门面（外观）：提供统一的接口，简化客户端与多个子系统之间的交互

## 数据新增或修改时，如何保证创建人、创建时间、修改人、修改时间等基础字段的填充？

数据库触发器：适用于对数据完整性要求极高的场景，但需要维护触发器逻辑。

ORM框架：适合大多数现代开发场景，逻辑集中，便于维护。

中间件/拦截器：适用于需要全局处理的场景，减少重复代码。

## sql优化

尽量避免select \*

基于有序主键，避免大偏移量分页

避免全表扫描，合理设计索引，对于经常查询的字段

尽量避免使用函数，比如日期函数

联合索引满足，最左匹配

**索引失效场景**

左like无法利用索引

or条件两侧字段未全部索引，可能导致全表扫描

范围查询后的列：联合索引中，范围查询（`>`、`<`、`BETWEEN`）之后的字段无法使用索引。

> 范围查询会“破坏”索引的有序性，使得数据库引擎无法继续利用后续字段的索引。
>
> 例如，在联合索引   (A, B, C)   中：
>
> • 当   A   是范围查询时，数据库会扫描所有满足   A   范围的数据，而无法利用   B   和   C   的索引。
>
> • 当   B   是范围查询时，数据库会扫描所有满足   A   和   B   范围的数据，而无法利用   C   的索引。
>
> 这是因为范围查询导致数据库引擎无法继续按照索引的顺序快速定位数据，而是需要逐行扫描满足范围条件的数据。

## dubbo、fegin常用注解

@DubboService：标记服务提供方的接口实现类

@DubboReference：标记服务提供方的接口实现类

@DubboComponentScan：用于指定 Dubbo 服务的扫描包路径

@DubboConfiguration：用于定义 Dubbo 的配置类

@FeignClient(value = "xxx")：标记一个接口，表示该接口是一个 Feign 客户端，用于调用远程服务。

@GetMapping、@PostMapping、@PutMapping、@DeleteMapping ：用于定义 HTTP 请求的类型和路径
