10. Elasticsearch 搜索引擎

Elasticsearch 核心原理:倒排索引、分词与 Mapping、查询优化、集群架构与调优实践

Elasticsearch 是全球最流行的分布式搜索引擎之一,它基于开源的全文检索库 Apache Lucene 构建,天然支持水平扩展与近实时搜索能力。通过倒排索引、分词器以及丰富的聚合分析框架,Elasticsearch 能够以毫秒级延迟在海量数据中完成全文检索、结构化过滤与统计分析。无论是日志分析、站内搜索、商品推荐还是安全审计场景,Elasticsearch 都提供了成熟可靠的解决方案。

1. 核心概念

掌握 Elasticsearch 的前提是先理解其与关系型数据库之间的概念映射,这有助于我们在设计数据模型时避免范式误区。

概念类比 RDBMS说明
IndexDatabase索引,逻辑命名空间,包含一组具有相似特征的文档
TypeTable7.x 已废弃,8.x 正式移除,一个索引仅含单一类型
DocumentRow一条 JSON 格式的数据记录,是 Lucene 文档的封装
FieldColumn字段,分为 text(全文索引)、keyword(精确匹配)等类型
MappingSchema字段类型定义,可以动态推断也可以显式声明
ShardPartition分片,索引数据在物理上的横向切分单元
ReplicaReplica副本分片,提供读扩展能力与故障冗余保护

每个 Elasticsearch 索引实际上由多个 Lucene 索引组成。当写入一条文档时,数据首先进入内存缓冲区并写入 translog,随后经过 refresh 变成近实时可搜索的段(segment),最终经 flush 持久化到磁盘。查询请求则由协调节点(Coordinating Node )接收,广播到相关分片执行本地搜索后再汇聚结果。

2. 倒排索引

倒排索引(Inverted Index)是全文检索的基石。与正排索引(按文档编号存储内容)不同,倒排索引以词项(Term)为核心,记录每个词项在哪些文档中出现以及出现的具体位置。

文档集合:
  Doc1: "Elasticsearch is a search engine"
  Doc2: "Lucene is the core of Elasticsearch"

倒排索引结构:
  "elasticsearch" → [Doc1: TF=1, Positions=[0]], [Doc2: TF=1, Positions=[5]]
  "search"        → [Doc1: TF=1, Positions=[3]]
  "engine"        → [Doc1: TF=1, Positions=[4]]
  "lucene"        → [Doc2: TF=1, Positions=[0]]
  "core"          → [Doc2: TF=1, Positions=[3]]

除了词项到文档的映射,ES 的每个 posting list 还携带了以下四种关键元数据:

  • Term Frequency (TF):词项在当前文档中出现的次数,越高代表相关性越强。
  • Document Frequency (DF):包含该词项的文档总数,用于计算 IDF(逆文档频率)。
  • Norms:字段长度归一化因子,短字段中的词比长字段中的词权重更高。
  • Positions:词项在文档中的位置序号,用于短语匹配(match_phrase)和邻近查询(span query)。
  • Offsets:字节级别的字符偏移量,响应阶段用于高亮(highlight)渲染匹配片段。

理解倒排索引的结构有助于我们后续的查询优化与字段映射设计。

3. 分词与分析器

分析器(Analyzer)由三个组件构成:字符过滤器(Char Filter)、分词器(Tokenizer)和词项过滤器(Token Filter)。中文全文检索通常选用 IK 分词器,在索引阶段使用 ik_max_word 进行最细粒切分以提升召回率,在查询阶段使用 ik_smart 进行智能切分以避免无意义组合。

以下示例展示如何为一个商品索引配置 IK 分词器叠加拼音过滤器,从而实现「中文 + 拼音首字母」的双路检索:

PUT /products
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1,
    "analysis": {
      "analyzer": {
        "ik_pinyin": {
          "tokenizer": "ik_max_word",
          "filter": ["pinyin_filter"]
        }
      },
      "filter": {
        "pinyin_filter": {
          "type": "pinyin",
          "keep_separate_first_letter": false,
          "keep_full_pinyin": true,
          "keep_original": true,
          "limit_first_letter_length": 16,
          "lowercase": true
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart",
        "fields": {
          "pinyin": {
            "type": "text",
            "analyzer": "ik_pinyin"
          }
        }
      },
      "description": { "type": "text", "analyzer": "ik_max_word" },
      "price": { "type": "float" },
      "category": { "type": "keyword" },
      "tags": { "type": "keyword" },
      "create_time": { "type": "date" },
      "sales": { "type": "integer" }
    }
  }
}

字段映射中使用了 fields(多字段)特性,title 同时支持 IK 全文索引与拼音索引,category 与 tags 使用 keyword 类型以保证聚合与排序时不需要额外的 text 转换开销。

4. 索引设计与映射

索引设计阶段的选择将直接影响后期的搜索质量与查询性能。首先需要在动态映射与显式映射之间做出选择:

  • 动态映射(Dynamic Mapping):新字段首次出现时由 Elasticsearch 自动推断类型,适合快速原型与日志场景。
  • 显式映射(Explicit Mapping):开发者在创建索引时完整定义所有字段类型,适合生产环境的稳定索引。

显式映射可以避免动态映射带来的两个经典问题:字符串被同时推断为 text 与 keyword 多字段、数值被错误推断为 long 导致存储膨胀。建议生产环境始终使用显式映射。

字段类型的选择同样关键:text 字段会被分析并入库到倒排索引,支持全文检索但不支持聚合与排序;keyword 字段保持原始字符串,适合精确匹配、范围过滤、聚合统计与排序操作。如果需要同时支持全文搜索与精确聚合,应使用多字段特性同时定义 text 与 keyword 子字段。

PUT /articles
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart",
        "norms": false,
        "fields": {
          "keyword": { "type": "keyword", "ignore_above": 256 }
        }
      },
      "content": {
        "type": "text",
        "analyzer": "ik_max_word",
        "index_options": "offsets"
      },
      "author": {
        "type": "keyword",
        "ignore_above": 128
      },
      "tags": {
        "type": "keyword",
        "ignore_above": 64
      },
      "publish_time": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      },
      "views": { "type": "integer" },
      "rating": { "type": "float" }
    }
  }
}

上述映射中,“dynamic”: “strict” 禁止未知字段写入,防止脏数据污染索引结构。norms: false 禁用了 TF-IDF 评分中的长度归一化,适用于不需要相关性排序的纯文本字段,能有效降低磁盘占用。ignore_above 限制字符串长度,超过该值的字符串将被忽略且不索引,避免超长异常数据导致内存压力。index_options: offsets 仅存储偏移量用于高亮,在不需要位置信息时可比默认的 positions 节省空间。

5. 查询 DSL 进阶

Elasticsearch 的 Query DSL 是一套基于 JSON 的请求体查询语言,分为叶子查询(如 term、match、range)与复合查询(如 bool、function_score)。

5.1 Bool 复合查询

bool 查询通过 must、should、filter、must_not 四个子句组合多个查询条件。关键区别在于 must 子句参与相关性评分计算并影响最终得分,而 filter 子句仅做包含与否判定且不参与打分,同时 filter 结果会被缓存以加速重复过滤条件。

GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "智能手机",
            "fields": ["title^3", "description^1"],
            "type": "best_fields",
            "fuzziness": "AUTO"
          }
        }
      ],
      "filter": [
        { "range": { "price": { "gte": 1000, "lte": 5000 } } },
        { "term": { "category": "电子产品" } },
        { "term": { "tags": "5G" } }
      ],
      "must_not": [
        { "exists": { "field": "deleted_time" } }
      ],
      "should": [
        { "term": { "tags": "新品" } }
      ],
      "minimum_should_match": 0
    }
  },
  "sort": [
    { "_score": "desc" },
    { "sales": "desc" }
  ],
  "from": 0,
  "size": 20,
  "highlight": {
    "pre_tags": ["<strong>"],
    "post_tags": ["</strong>"],
    "fields": {
      "title": {
        "number_of_fragments": 1,
        "fragment_size": 200
      },
      "description": {
        "number_of_fragments": 2,
        "fragment_size": 150
      }
    }
  },
  "aggs": {
    "by_category": {
      "terms": { "field": "category" }
    },
    "price_stats": {
      "stats": { "field": "price" }
    }
  }
}

5.2 Function Score 自定义排序

当默认的 TF-IDF 评分无法满足业务需求时,可以通过 function_score 引入自定义权重。常见场景包括:热销商品加权、新上架商品提权、高评分内容优先。

GET /products/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": { "title": "无线耳机" }
      },
      "functions": [
        {
          "filter": { "term": { "tags": "新品" } },
          "weight": 1.5
        },
        {
          "field_value_factor": {
            "field": "sales",
            "factor": 0.001,
            "modifier": "log1p",
            "missing": 1.0
          }
        },
        {
          "gauss": {
            "create_time": {
              "origin": "now",
              "scale": "7d",
              "offset": "1d",
              "decay": 0.5
            }
          }
        }
      ],
      "score_mode": "sum",
      "boost_mode": "multiply"
    }
  }
}

5.3 Search After 深度分页

from + size 深分页在超过一万条时性能急剧下降,因为协调节点需要为每个分片获取大量文档再全局排序。search_after 基于排序值进行翻页,能够安全地处理百万甚至千万级分页请求。

GET /orders/_search
{
  "size": 100,
  "sort": [
    { "order_time": "desc" },
    { "order_id": "asc" }
  ],
  "search_after": [1692009600000, "ORD-20230814-000927"]
}

5.4 Collapse 字段折叠

在搜索结果中按某个字段去重时,如果业务要求每组仅展示一条代表文档,可使用 collapse 功能替代聚合后手动去重的开销。

GET /news/_search
{
  "query": {
    "match": { "title": "区块链" }
  },
  "collapse": {
    "field": "source_site",
    "inner_hits": {
      "name": "latest_articles",
      "size": 3,
      "sort": [{ "publish_time": "desc" }]
    }
  },
  "sort": [{ "publish_time": "desc" }]
}

6. 聚合分析

聚合(Aggregations)是 Elasticsearch 最具特色的分析功能之一,分为桶聚合(Bucket)、指标聚合(Metric)与管道聚合(Pipeline)三大类。

6.1 桶聚合与指标聚合

桶聚合用于将文档分组到各个桶中,指标聚合则在每个桶内计算统计数据。

POST /sales/_search
{
  "size": 0,
  "aggs": {
    "sales_over_time": {
      "date_histogram": {
        "field": "order_time",
        "calendar_interval": "day",
        "min_doc_count": 1,
        "format": "yyyy-MM-dd"
      },
      "aggs": {
        "revenue": {
          "sum": { "field": "amount" }
        },
        "avg_order_value": {
          "avg": { "field": "amount" }
        },
        "percentiles_latency": {
          "percentiles": {
            "field": "delivery_time_hours",
            "percents": [50, 90, 99]
          }
        },
        "unique_customers": {
          "cardinality": { "field": "customer_id" }
        }
      }
    },
    "top_categories": {
      "terms": {
        "field": "category",
        "size": 10,
        "order": { "total_revenue": "desc" }
      },
      "aggs": {
        "total_revenue": {
          "sum": { "field": "amount" }
        }
      }
    }
  }
}

6.2 管道聚合

管道聚合不直接操作原始文档,而是基于其他聚合的结果进行二次计算。典型场景包括计算环比增长率与移动平均值。

POST /metrics/_search
{
  "size": 0,
  "aggs": {
    "daily_cpu": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "hour"
      },
      "aggs": {
        "avg_cpu": {
          "avg": { "field": "cpu_percent" }
        },
        "cpu_derivative": {
          "derivative": {
            "buckets_path": "avg_cpu"
          }
        },
        "cpu_moving_avg": {
          "moving_avg": {
            "buckets_path": "avg_cpu",
            "window": 24,
            "model": "linear"
          }
        }
      }
    }
  }
}

6.3 聚合性能优化

聚合查询会消耗大量堆内存与 CPU 资源。生产环境应遵循以下原则:

  • 时间范围聚合尽量使用索引模式与 time_zone 参数对齐业务时区。
  • 高基数字段(如 UUID、IP)使用 cardinality 时注意 precision_threshold 的内存开销,必要时改用 HyperLogLog++ 预聚合。
  • 嵌套聚合(sub-aggregation)深度不超过两层,否则查询延迟会呈指数级增长。
  • 聚合请求中设置 "size": 0,避免在返回聚合结果时附带原始命中文档。

7. 集群运维

7.1 节点角色与架构

Elasticsearch 集群中的节点可按职责划分为多种角色:

  • Master:负责集群状态管理、索引元数据变更与分片分配决策。生产环境应部署至少三个符合主节点条件的节点并设置 discovery.seed_hosts。
  • Data:存储实际数据分片并承担查询与写入的执行任务。可按性能需求细分为 Hot、Warm、Cold、Frozen 四种数据层。
  • Ingest:运行预处理管道(Pipeline),对写入文档执行富化、转换或结构化操作。
  • Coordinating:仅负责接收、路由与聚合请求,不存储数据也不成为主节点。适合部署在大型集群前端分担协调压力。
  • ML:专门用于运行机器学习异常检测与预测作业。

7.2 分片分配策略

分片是 Elasticsearch 实现分布式存储与并行查询的核心单元,但分片数量并非越多越好。单分片推荐保持在 10 到 50GB 之间,单节点承载分片数不宜超过 20 个,否则会导致堆内存与文件描述符压力剧增。JVM 堆内存应设置为不超过 30GB,因为在 32GB 以上会丧失压缩指针优化。

PUT /logs-2024-01
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1,
    "refresh_interval": "30s",
    "index.routing.allocation.include.temperature": "hot"
  }
}

7.3 ILM 索引生命周期管理

ILM 通过在 Hot、Warm、Cold、Frozen、Delete 五个阶段配置自动化策略,实现日志类时序数据的自动滚动、压缩、迁移与删除。

PUT _ilm/policy/logs_policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_size": "50GB",
            "max_age": "30d",
            "max_docs": 500000000
          },
          "set_priority": {
            "priority": 100
          }
        }
      },
      "warm": {
        "min_age": "7d",
        "actions": {
          "shrink": { "number_of_shards": 1 },
          "forcemerge": { "max_num_segments": 1 },
          "allocate": {
            "require": { "data": "warm" }
          },
          "set_priority": { "priority": 50 }
        }
      },
      "cold": {
        "min_age": "30d",
        "actions": {
          "allocate": { "require": { "data": "cold" } },
          "freeze": {},
          "set_priority": { "priority": 0 }
        }
      },
      "delete": {
        "min_age": "90d",
        "actions": { "delete": {} }
      }
    }
  }
}

7.4 集群备份与快照

快照(Snapshot)是 Elasticsearch 进行物理级别备份的重要手段,它将索引数据写入外部仓库(如 S3、HDFS、共享文件系统)并支持增量备份与单索引恢复。

# 1. 注册快照仓库
PUT _snapshot/my_backup
{
  "type": "fs",
  "settings": {
    "location": "/mount/backups",
    "compress": true,
    "chunk_size": "1gb",
    "max_snapshot_bytes_per_sec": "100mb",
    "max_restore_bytes_per_sec": "100mb"
  }
}

# 2. 执行快照
PUT _snapshot/my_backup/snapshot_2024_01_15?wait_for_completion=true
{
  "indices": "logs-2024-*",
  "ignore_unavailable": true,
  "include_global_state": false
}

# 3. 查看快照状态
GET _snapshot/my_backup/snapshot_2024_01_15/_status

# 4. 恢复索引
POST _snapshot/my_backup/snapshot_2024_01_15/_restore
{
  "indices": "logs-2024-01-01",
  "ignore_unavailable": true,
  "include_aliases": false
}

快照仓库的配置中,chunk_size 控制每次上传的分片大小,max_snapshot_bytes_per_sec 限制备份与恢复带宽,避免网络或 IO 资源被长期占满。

8. 性能调优

Elasticsearch 的性能优化需要从写入吞吐、查询延迟与存储空间三个维度同时进行。

8.1 Refresh Interval 权衡

默认的 refresh_interval 为 1 秒,意味着每秒钟会将内存缓冲区中的数据刷新为新的段并使其可搜索。高吞吐写入场景下,增大刷新间隔可显著减少段文件数量与 refresh 开销。日志索引通常设置为 30 秒甚至更大。

PUT /logs/_settings
{
  "index": {
    "refresh_interval": "30s",
    "number_of_replicas": 0
  }
}

8.2 Bulk API 批量写入

单条写入每次都会触发网络往返、写 translog 与刷新检查。生产环境写入应始终使用 _bulk API,将多条文档合并到一个请求中。最优批量大小通常在 5MB 到 15MB 之间,可通过调整并发线程数进一步压榨写入吞吐。

curl -X POST "localhost:9200/_bulk?refresh=false" -H 'Content-Type: application/json' -d'
{ "index" : { "_index" : "products", "_id" : "1" } }
{ "title" : "无线降噪耳机", "price" : 1299.00, "category" : "电子产品", "tags" : ["蓝牙", "降噪"], "sales" : 5000 }
{ "index" : { "_index" : "products", "_id" : "2" } }
{ "title" : "机械键盘", "price" : 599.00, "category" : "电脑配件", "tags" : ["RGB", "热插拔"], "sales" : 3200 }
{ "index" : { "_index" : "products", "_id" : "3" } }
{ "title" : "4K 显示器", "price" : 2499.00, "category" : "电子产品", "tags" : ["4K", "HDR"], "sales" : 1800 }
'

8.3 Translog 持久化策略

Translog 是写入数据的第一份保障,记录了尚未 flush 到磁盘的操作日志。index.translog.durability 控制 translog 的 fsync 策略,async 模式可以降低写入延迟但需要容忍少量数据丢失风险,关键业务索引建议保持 request 同步策略。

PUT /critical_orders/_settings
{
  "index": {
    "translog": {
      "durability": "request",
      "sync_interval": "5s"
    }
  }
}

8.4 段合并与查询缓存

随着写入持续进行,小段(segment)文件会大量累积,既占用文件描述符又拖慢查询速度。forcemerge API 可以将段数量强制合并到指定值,但执行期间会产生显著磁盘 IO,应在业务低峰期操作。

POST /old_logs/_forcemerge?max_num_segments=1

查询缓存(Query Cache)默认将 filter 子句的位集结果缓存在节点级别的堆内存中。合理设计 filter 组合可以显著提升热点查询的响应速度。此外,ES 还维护请求缓存(Request Cache)用于缓存聚合结果与命中总数,在数据不频繁变更的索引上尤其有效。

PUT /reports/_settings
{
  "index": {
    "requests.cache.enable": true
  }
}

9. 与 Spring Boot 及 Elastic Stack 集成

9.1 Spring Data Elasticsearch

Spring Data Elasticsearch 提供 Repository 模式与 ElasticsearchRestTemplate 两种编程方式,能够像操作 JPA 一样操作搜索索引。

// 1. Maven 依赖
// <dependency>
//   <groupId>org.springframework.boot</groupId>
//   <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
// </dependency>

// 2. 实体类
@Document(indexName = "products")
public class Product {
    @Id
    private String id;

    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
    private String title;

    @Field(type = FieldType.Float)
    private BigDecimal price;

    @Field(type = FieldType.Keyword)
    private String category;

    @Field(type = FieldType.Keyword)
    private List<String> tags;

    @Field(type = FieldType.Date, format = DateFormat.date_time)
    private LocalDateTime createTime;

    @Field(type = FieldType.Integer)
    private Integer sales;

    // getters and setters
}

// 3. Repository 接口
public interface ProductRepository extends ElasticsearchRepository<Product, String> {
    List<Product> findByCategory(String category);

    @Query("{ \"bool\": { \"must\": [ { \"match\": { \"title\": \"?0\" } } ], \"filter\": [ { \"term\": { \"category\": \"?1\" } } ] } }")
    List<Product> searchByTitleAndCategory(String title, String category);
}

ElasticsearchRestTemplate 则适合执行更复杂的查询与聚合操作,支持直接拼 DSL 并通过 NativeSearchQuery 执行。

9.2 Filebeat 与 Logstash Pipeline

Elastic Stack 中,Filebeat 负责轻量级日志采集,通过 prospector 监控日志文件的变化并将增量内容发送到 Elasticsearch 或 Logstash。

# filebeat.yml
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /var/log/nginx/access.log
    fields:
      service: nginx
      env: production
    fields_under_root: true

output.elasticsearch:
  hosts: ["http://es-node1:9200", "http://es-node2:9200"]
  index: "%{[fields.service]}-%{[agent.version]}-%{+yyyy.MM.dd}"
  pipeline: "nginx_access_pipeline"

processors:
  - add_host_metadata:
      when.not.contains.tags: forwarded
  - add_cloud_metadata: ~

Logstash 则作为更强大的数据处理中间件,支持 grok 解析、geoip enrich、mutate 转换等多阶段 Pipeline 处理。

input {
  beats { port => 5044 }
}

filter {
  grok {
    match => { "message" => "%{IPORHOST:client_ip} - %{USER:auth} \[%{HTTPDATE:timestamp}\] \"%{WORD:method} %{URIPATHPARAM:request} HTTP/%{NUMBER:http_version}\" %{INT:status} %{INT:bytes} \"%{DATA:referrer}\" \"%{DATA:user_agent}\"" }
  }
  geoip {
    source => "client_ip"
    target => "geoip"
  }
  date {
    match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
    target => "@timestamp"
  }
  mutate {
    add_field => { "service" => "nginx" }
    remove_field => [ "message", "timestamp", "beat", "input", "host" ]
  }
}

output {
  elasticsearch {
    hosts => ["http://es-node1:9200"]
    index => "nginx-access-%{+yyyy.MM.dd}"
    template_name => "nginx_template"
  }
}

10. 集群架构与节点规划

Node 类型:
  - Master:         管理集群状态与索引元数据(至少 3 个候选)
  - Data Hot:       承载高频读写热数据(SSD 存储)
  - Data Warm:      承载低频访问温数据(SATA 存储,段合并后只读)
  - Data Cold:      承载归档冷数据(压缩存储,查询需解冻)
  - Ingest:         执行文档预处理 Pipeline(过滤、富化、结构化)
  - Coordinating:   仅路由请求与聚合结果(大集群前端专用)
  - ML:             运行机器学习作业(异常检测、预测分析)

10.1 分片规划黄金法则

# 分片大小范围: 10 - 50 GB
# 单节点分片数上限: < 20 个
# JVM 堆内存上限: ≤ 30 GB(用于启用压缩指针)
# 总分片数估算: 数据总量(GB) / 30
#
# 创建索引时显式指定分片与副本
PUT /logs-2024-01
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1,
    "refresh_interval": "30s",
    "index.lifecycle.name": "logs_policy",
    "index.lifecycle.rollover_alias": "logs"
  }
}

总结

  • 分词策略:中文搜索优先选用 IK 分词器,索引阶段使用 ik_max_word 提升召回率,查询阶段使用 ik_smart 保证结果精确度。
  • 映射设计:能用 keyword 的场景不要滥用 text,聚合、排序与精确匹配均应依赖 keyword。多字段特性(fields)可以在同一字段上同时支持两种能力。
  • 查询优化:must 与 filter 分离使用,filter 子句不参与评分且结果会被缓存,是提升查询效率的关键手段。深分页使用 search_after,去重展示使用 collapse。
  • 聚合分析:桶聚合负责分组,指标聚合负责统计,管道聚合负责二次计算。控制嵌套深度并在聚合请求中禁用文档回传(size: 0)。
  • 集群规划:Master 节点与数据节点必须分离,热温冷分层降低存储成本,ILM 自动管理索引生命周期,定期快照保障数据安全。
  • 性能调优:写入端使用 _bulk 批量提交并适当增大 refresh_interval,查询端善用 filter 缓存与请求缓存,存储端按需执行段合并与冷热迁移。
  • 生态集成:Spring Data Elasticsearch 让 Java 开发者能够以声明式方式操作搜索索引,Filebeat 与 Logstash 则构成了日志采集与处理的标准数据通路。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「distributed-systems」更多文章

  1. 边缘计算架构与就近接入
  2. 分布式系统成本优化与容量治理
  3. 单体到分布式:遗留系统迁移与绞杀者模式