2. Elastic Stack数据层基础

在 Elastic Stack 中,Elasticsearch 承担数据存储、检索与聚合的核心职责。要理解后续的机器学习数据平台集成,必须先弄清 Elasticsearch 如何组织数据:数据以 JSON 文档形式写入,文档归属于某个索引,索引通过映射定义字段类型,而索引又被切分为多个分片,每个分片可拥有副本。数据摄入管道则负责在写入前对文档做预处理。本节围绕这条数据链路展开。

索引、文档与映射:数据的逻辑组织

索引(Index)是 Elasticsearch 中具有相似结构的文档集合,类似关系数据库中的“表”,但更灵活。文档(Document)是 Elasticsearch 中可被索引的最小数据单元,采用 JSON 表示,每个文档有唯一标识 _id,并归属于一个索引。例如一条主机监控记录:

PUT metrics-host-2024.06/_doc/1
{
  "host": "web-01",
  "cpu_usage": 0.73,
  "mem_usage": 0.61,
  "timestamp": "2024-06-01T10:00:00Z"
}

映射(Mapping)定义索引中字段的名称、数据类型和索引方式。常见类型包括 keyword(精确值,用于过滤、聚合)、text(分词全文检索)、long、double、date、boolean 等。映射分为动态映射与显式映射:动态映射由 Elasticsearch 根据首次写入的 JSON 自动推断类型,方便但可能把本应是 keyword 的字段推断为 text,或把数值字符串推断为 text;显式映射则提前声明字段类型,是生产环境推荐做法。

PUT metrics-host-2024.06
{
  "mappings": {
    "properties": {
      "host":       { "type": "keyword" },
      "cpu_usage":  { "type": "double" },
      "mem_usage":  { "type": "double" },
      "timestamp":  { "type": "date" }
    }
  }
}

映射一旦创建,字段类型通常不可直接修改,只能通过重建索引(reindex)迁移数据。因此设计阶段就要明确哪些字段用于精确过滤与聚合(用 keyword),哪些用于全文检索(用 text),哪些是数值或时间(用 double、date)。这对后续机器学习特征提取尤为关键:特征字段若被错误映射为 text,聚合与数值计算将无法按预期进行。

分片与副本:数据的物理分布与高可用

索引在物理上被划分为若干分片(Shard),每个分片是一个独立的 Lucene 索引。分片分为主分片(Primary Shard)和副本分片(Replica Shard)。主分片数量在索引创建时确定,之后不可更改;副本数量可随时调整。分片机制带来两个好处:一是水平扩展,数据分散到多个节点并行读写;二是高可用,副本分片可在主分片所在节点故障时接管。

写入时,Elasticsearch 先根据文档 _id 做哈希路由,确定目标主分片,再写入主分片并同步到其副本分片。读取时,请求可被路由到主分片或副本分片,实现负载均衡。分片数量需权衡:分片过多会增加集群元数据与查询协调开销,分片过少则限制并行度。经验上单个分片大小控制在几十 GB 量级较为合适。

数据摄入管道 Ingest Pipeline grok / date / set 字段解析与转换 写入 文档 Document JSON + _id host / cpu / ts 按映射解析 映射 Mapping keyword / double date / text 归属 索引 Index 逻辑集合 索引的物理分布:主分片与副本分片 节点 Node-1 P0 主分片 R1 副本 P0 写入并同步 R1 R1 可承担读请求 节点 Node-2 P1 主分片 R0 副本 P1 写入并同步 R0 R0 可承担读请求 节点 Node-3 P2 主分片 R2 副本 P2 写入并同步 R2 节点故障时副本接管 文档按 _id 哈希路由到主分片,再同步到副本分片

上图中,一个索引被划分为 P0、P1、P2 三个主分片,并各有一个副本 R0、R1、R2,分布在三个节点上。写入时文档先路由到主分片,再同步到副本;读取时主副本均可响应。若 Node-1 故障,R1 可提升为新的主分片,保证数据不丢失、服务不中断。

数据摄入管道:写入前的预处理

数据摄入管道(Ingest Pipeline)允许在文档写入索引前,对文档执行一系列处理器(Processor)。常见处理器包括:grok 用正则从原始日志中提取字段;date 解析时间字符串并写入 @timestamp;set 设置固定字段;remove 删除无用字段;convert 转换字段类型。管道通过 _ingest/pipeline 定义,并在写入时通过参数 ?pipeline=名称 指定。

PUT _ingest/pipeline/host-metrics-pipeline
{
  "processors": [
    { "grok": {
        "field": "message",
        "patterns": ["%{IP:host_ip} %{NUMBER:cpu_usage:float} %{NUMBER:mem_usage:float}"]
    }},
    { "date": {
        "field": "log_time",
        "target_field": "@timestamp",
        "formats": ["ISO8601"]
    }},
    { "remove": { "field": "message" } }
  ]
}

写入时指定管道:

POST metrics-host-2024.06/_doc?pipeline=host-metrics-pipeline
{
  "message": "10.0.0.5 0.73 0.61",
  "log_time": "2024-06-01T10:00:00Z"
}

经过管道处理后,文档中会新增 host_ip、cpu_usage、mem_usage 和 @timestamp 字段,原始 message 被移除。这样写入索引的文档结构统一、字段类型明确,便于后续聚合分析与机器学习特征提取。

在机器学习数据平台集成中,摄入管道常用于把原始日志或业务数据规范化为特征友好的结构。建议在管道中完成字段类型转换与时间戳标准化,避免在索引映射阶段出现类型冲突。

关键参数与设计要点

对象关键参数作用与建议
索引settings.number_of_shards主分片数,创建后不可改,需预估数据量与并行度
索引settings.number_of_replicas副本数,可动态调整,影响高可用与存储成本
映射properties.字段.type决定字段能否聚合、排序、数值计算
文档_id决定路由到哪个主分片,影响写入分布
管道processors写入前字段解析、转换、清洗