第4章:日志存储引擎——Elasticsearch基础概念与实战优化

日志系统建好了,数据也收上来了。接下来要面对一个很现实的问题:这些海量日志往哪存?怎么存才不崩?

我见过不少团队,前期选型时觉得Elasticsearch就是“开箱即用”,结果上线三个月后,集群频频告警,查询慢得像蜗牛。说白了,ES不是银弹,用不好就是定时炸弹

这一章,我就带你从实战角度,把ES的核心概念、写入优化、冷热分层、生命周期管理这些硬骨头啃下来。嗯,都是我在生产环境里踩过的坑和总结的经验。

4.1 核心概念:索引、分片、映射

先过一遍基础,但我会用“人话”来讲。

4.1.1 索引(Index)

索引就是一张“表”,只不过在ES里,它存的是文档(JSON格式)。每个索引都有一个名字,比如 nginx-access-log-2025-01。我个人习惯按时间+业务来命名,这样后续管理起来一目了然。

关键点:索引不是无限大的。一个索引建议控制在50GB以内,超过这个量,查询和写入都会开始吃力。

4.1.2 分片(Shard)

分片是ES实现分布式存储的核心。一个索引会被拆成多个分片,分散到不同节点上。

  • 主分片(Primary Shard):负责写入和查询。数量在索引创建时固定,之后不能改。
  • 副本分片(Replica Shard):主分片的备份,负责读请求。数量可以动态调整。

我在项目中遇到过一个问题:主分片数设得太多。当时为了追求写入速度,把分片数设成了30个。结果每个分片都很小,查询时需要合并大量结果,反而变慢了。后来我总结了一个经验公式:

分片数 ≈ 节点数 × 2。比如你有5个节点,分片数设为10左右比较合理。当然,还要结合数据量来微调。

4.1.3 映射(Mapping)

映射就是定义字段的类型和规则。比如时间字段要设为 date 类型,IP字段要设为 ip 类型。如果不设置,ES会动态推断,但经常推断错。

举个例子:

{
  "mappings": {
    "properties": {
      "@timestamp": { "type": "date" },
      "client_ip": { "type": "ip" },
      "status_code": { "type": "integer" },
      "message": { 
        "type": "text",
        "fields": {
          "keyword": { "type": "keyword" }
        }
      }
    }
  }
}

你想想看,如果不把 status_code 设为 integer,ES可能会把它当成字符串。到时候你想做范围查询(比如找所有4xx错误),就麻烦了。

注意:映射一旦创建,字段类型就不能改了。除非你重建索引。所以上线前一定要规划好。

4.2 写入优化:让ES飞起来

日志场景下,写入是最大的挑战。每秒几万条甚至几十万条的写入,ES扛得住吗?

答案是:扛得住,但要调优

4.2.1 批量写入

千万别一条一条地写。用 _bulk API,一次批量提交几千条。我习惯每批5000条左右,太大容易超时,太小又浪费网络开销。

POST _bulk
{ "index" : { "_index" : "logs-2025-01" } }
{ "@timestamp": "2025-01-15T10:00:00Z", "message": "request started" }
{ "index" : { "_index" : "logs-2025-01" } }
{ "@timestamp": "2025-01-15T10:00:01Z", "message": "request completed" }

4.2.2 调整刷新间隔

ES默认每秒刷新一次(refresh_interval=1s),这样写入后1秒就能查到。但日志场景下,我们通常不要求实时可见。把刷新间隔改成30秒甚至60秒,写入性能能提升好几倍。

PUT logs-2025-01/_settings
{
  "index": {
    "refresh_interval": "30s"
  }
}

4.2.3 禁用副本

写入时,副本分片也会同步数据,这会拖慢写入速度。我建议在写入高峰期,先把副本数设为0,等写入完了再恢复。

PUT logs-2025-01/_settings
{
  "index": {
    "number_of_replicas": 0
  }
}

实战经验:我曾经在双11大促时,把副本数临时设为0,写入速度提升了40%。等数据写完后,再恢复副本数,让ES自动同步。这个操作很安全,放心用。

4.3 冷热数据分层

日志数据有个特点:越新的数据越热,越旧的数据越冷。热数据需要快速写入和查询,冷数据只需要偶尔访问。

ES的冷热分层架构,就是让不同节点承担不同角色:

节点角色 硬件配置 存储的数据 典型用途
Hot节点 SSD、高IOPS 最近7天的数据 实时写入、高频查询
Warm节点 HDD、大容量 7-30天的数据 低频查询、报表
Cold节点 HDD、超大容量 30天以上的数据 归档、极少查询

怎么实现?通过索引的 routingallocation 规则。比如:

PUT _template/hot_logs
{
  "index_patterns": ["logs-*"],
  "settings": {
    "index.routing.allocation.require.box_type": "hot"
  }
}

这样,所有以 logs- 开头的索引,都会自动分配到Hot节点上。等数据变冷后,再手动迁移到Warm或Cold节点。

小技巧:用ILM(索引生命周期管理)来自动化这个迁移过程。后面会讲到。

4.4 生命周期管理(ILM)

手动管理索引太累了。ILM就是ES自带的“自动管家”,帮你完成索引的创建、滚动、迁移、删除。

4.4.1 ILM的四个阶段

  • Hot:活跃写入阶段。索引在Hot节点上,支持读写。
  • Warm:只读阶段。索引迁移到Warm节点,不再写入。
  • Cold:归档阶段。索引迁移到Cold节点,偶尔查询。
  • Delete:删除阶段。索引被自动删除,释放空间。

4.4.2 实战配置

下面是一个完整的ILM策略示例:

PUT _ilm/policy/logs_policy
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_size": "50GB",
            "max_age": "7d"
          },
          "set_priority": {
            "priority": 100
          }
        }
      },
      "warm": {
        "min_age": "7d",
        "actions": {
          "allocate": {
            "require": {
              "box_type": "warm"
            }
          },
          "set_priority": {
            "priority": 50
          }
        }
      },
      "cold": {
        "min_age": "30d",
        "actions": {
          "allocate": {
            "require": {
              "box_type": "cold"
            }
          },
          "set_priority": {
            "priority": 0
          }
        }
      },
      "delete": {
        "min_age": "90d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

这个策略的意思是:

  • 索引在Hot阶段,当大小超过50GB或时间超过7天时,自动滚动(创建新索引)。
  • 7天后进入Warm阶段,迁移到Warm节点。
  • 30天后进入Cold阶段,迁移到Cold节点。
  • 90天后自动删除。

避坑指南:我曾经把 rollovermax_age 设得太短(比如1天),结果索引滚动太频繁,产生了大量小索引,管理起来很头疼。建议至少7天以上。

4.5 总结

这一章的内容,说白了就是三件事:

  1. 理解ES的核心概念:索引、分片、映射,这是基础。
  2. 优化写入性能:批量写入、调整刷新间隔、禁用副本,这些技巧能让你在日志场景下跑得更稳。
  3. 做好冷热分层和生命周期管理:用ILM自动化管理索引,省心省力。

嗯,ES这块内容其实很深,但作为SaaS运维,掌握这些已经能应对90%的场景了。下一章,我们会聊到日志查询与分析,到时候你会用到今天学的这些索引和映射知识。

记住:ES不是万能的,但用好了,它就是日志系统的定海神针