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 量级较为合适。
上图中,一个索引被划分为 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 | 写入前字段解析、转换、清洗 |