4. 日志存储与索引:Elasticsearch集群搭建、ILM、冷热分离与分片策略

做高频交易日志分析,说白了就是跟海量数据打交道。我最早接手这个系统时,一天就能产生几个TB的日志。你想想看,几万笔订单、几十万次行情快照、再加上各种系统心跳——如果没有一个靠谱的存储方案,光查一条日志就能让你等到怀疑人生。

今天我们就来聊聊Elasticsearch这套方案。我个人习惯把它当作高频交易日志的“数据湖”。但光有湖不行,你得会挖渠、会分池子、还得知道什么时候该放水。嗯,这就是ILM、冷热分离和分片策略要做的事。

4.1 Elasticsearch集群搭建:别小看这一步

很多人觉得ES集群搭建就是装个包、改个配置、启动就完事了。我在项目中踩过这个坑——第一次搭建时,节点配置没调好,结果上线第一天就OOM了。

这里我建议你至少准备3个节点。为什么是3?因为ES的选举机制需要多数派。2个节点挂一个就废了,3个节点还能扛住一个故障。

节点角色要分清楚:

  • Master节点:负责集群管理,别让它存数据。我一般用3台小规格机器专门做Master。
  • Data节点:真正存日志的地方。高频交易日志写入量大,建议用SSD。
  • Ingest节点:做数据预处理。比如解析日志格式、过滤字段。

核心配置示例(elasticsearch.yml):

# 节点角色配置
node.roles: [ master, data, ingest ]

# 内存配置 - 这是最关键的
bootstrap.memory_lock: true
ES_JAVA_OPTS="-Xms32g -Xmx32g"

# 防止脑裂
discovery.seed_hosts: ["node1:9300", "node2:9300", "node3:9300"]
cluster.initial_master_nodes: ["node1", "node2", "node3"]

我的经验:堆内存不要超过32GB。超过这个值,JVM的压缩指针就失效了,性能反而下降。我见过有人给128GB,结果GC时间比查询时间还长。

4.2 索引生命周期管理(ILM):让数据自动流转

高频交易日志有个特点:越新的数据越有价值。昨天的日志可能还要查,上周的日志基本就归档了。手动去删索引?别傻了,一天几百个索引,手会断的。

ILM就是干这个的。它定义了索引从生到死的完整流程。我习惯分四个阶段:

阶段 时间 动作 存储介质
Hot 当前-1小时 写入+高频查询 SSD
Warm 1小时-1天 只读+偶尔查询 SSD
Cold 1天-7天 只读+极少查询 HDD
Delete 7天后 删除 -

ILM策略怎么写?看这个例子:

PUT _ilm/policy/hft_logs_policy
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_size": "50GB",
            "max_age": "1h"
          },
          "set_priority": {
            "priority": 100
          }
        }
      },
      "warm": {
        "min_age": "1h",
        "actions": {
          "allocate": {
            "require": {
              "data_type": "warm"
            }
          },
          "forcemerge": {
            "max_num_segments": 1
          },
          "shrink": {
            "number_of_shards": 1
          }
        }
      },
      "cold": {
        "min_age": "1d",
        "actions": {
          "allocate": {
            "require": {
              "data_type": "cold"
            }
          }
        }
      },
      "delete": {
        "min_age": "7d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

注意:rollover的条件要设合理。我曾经设了max_docs=1000万,结果日志量暴增时,一个索引还没rollover就撑爆了磁盘。建议用max_size做主条件,max_age做兜底。

4.3 冷热数据分离:把钱花在刀刃上

SSD贵啊。高频交易日志一天几个TB,全放SSD?老板会杀了你的。冷热分离的核心思想就是:热数据放SSD,冷数据放HDD。

实现方式其实很简单——给节点打标签:

# 热节点配置
node.attr.data_type: hot

# 冷节点配置  
node.attr.data_type: cold

然后在ILM策略里,通过allocate动作把数据路由到对应节点。就像上面代码里写的,warm阶段要求data_type=warm,cold阶段要求data_type=cold。

这里有个细节:热节点和冷节点的硬件配置要差异化。热节点CPU核数多、内存大、SSD快;冷节点CPU可以弱一些,内存给个16GB就够了,磁盘用大容量HDD。

我的做法:热节点用NVMe SSD,冷节点用SATA SSD或者7200转的HDD。成本能降60%以上,但查询冷数据的延迟也就多个几十毫秒——对于历史复盘来说完全可以接受。

4.4 分片与副本策略:多一分则肥,少一分则瘦

分片是ES的并行单元。分片太多,管理开销大;分片太少,写入瓶颈明显。我见过最夸张的一个索引分了200个分片,结果查询时光合并结果就花了半分钟。

高频交易日志的写入特点是:持续高吞吐、单条数据小。基于这个特点,我建议:

  • 分片数:每个分片20-40GB。比如一天产生500GB日志,分15-25个分片比较合适。
  • 副本数:1个就够了。高频交易日志丢了可以重放,不需要像业务数据那样搞3副本。
  • 分片大小:控制在50GB以内。超过50GB,查询和恢复都会变慢。

举个例子,假设你一天产生300GB日志:

PUT _template/hft_logs_template
{
  "index_patterns": ["hft-logs-*"],
  "settings": {
    "number_of_shards": 10,
    "number_of_replicas": 1,
    "routing.allocation.require.data_type": "hot"
  }
}

避坑指南:我曾经把副本数设成2,结果集群总数据量变成了3倍。磁盘报警器响了一整夜。后来我改成1副本,写入性能反而提升了——因为副本同步的开销小了。

4.5 整体架构图

说了这么多,画张图帮你理清思路。这是我在项目中实际使用的架构:

高频交易日志ES集群架构 交易系统日志 行情数据流 系统监控指标 Ingest节点 数据解析/过滤/转换 Master节点 x3 集群管理/选举 Hot节点 x5 SSD / 高频写入 Warm节点 x3 SSD / 只读查询 Cold节点 x2 HDD / 归档存储 ILM策略 Hot→Warm→Cold→Delete 图例说明: 数据源 Ingest节点(预处理) Master节点(管理) Hot节点(SSD热数据) Warm节点(SSD温数据) Cold节点(HDD冷数据) ILM策略控制数据流转

这张图里,数据从左边流入,经过Ingest节点清洗,然后路由到Hot节点。ILM策略像一只无形的手,把数据从Hot推到Warm,再推到Cold,最后删除。整个过程全自动,你只需要在Kibana上看看监控面板就行。

4.6 性能调优的几个关键点

最后分享几个我在实战中总结的调优经验:

  1. 写入调优:把refresh_interval设成30秒甚至更久。高频交易日志不需要实时可见,延迟30秒完全能接受。这样能大幅减少segment合并的开销。
  2. 批量写入:用bulk API,每批5000-10000条。我测试过,批量比单条写入快10倍以上。
  3. 禁用不需要的特性:如果不需要全文搜索,把_all字段关掉。不需要聚合分析,把doc_values关掉。每关一个特性,写入性能都能提升20%。
  4. 监控关键指标:重点关注GC次数、磁盘I/O等待、segment数量。这三个指标能反映集群的健康状况。

曾经踩过的坑:有一次我发现写入越来越慢,查了半天发现是磁盘I/O被打满了。原因是某个同事在Cold节点上跑了大量聚合查询。从那以后,我强制把Cold节点的查询线程数限制到2个——历史数据查询慢点就慢点,别影响写入就行。

好了,ES这块的内容就聊到这儿。记住一句话:架构设计决定了上限,细节调优决定了下限。ILM和冷热分离是架构层面的设计,分片和副本是细节层面的调优。两者缺一不可。


公众号:蓝海资料掘金营,微信deep3321