通过索引生命周期管理实现冷热数据分离

更新时间:
复制为 MD 格式

Elasticsearch 6.6.0及以上版本提供了索引生命周期管理(ILM,Index Lifecycle Management)功能,将索引生命周期分为hot、warm、cold、delete四个阶段,结合冷热集群架构实现数据自动流转和存储成本优化。

阶段

描述

hot

热数据阶段。处理时序数据的实时写入,可根据索引的文档数、大小、时长决定是否调用rollover API滚动更新索引。

warm

温数据阶段。索引不再写入,主要提供查询。

cold

冷数据阶段。索引不再更新,查询频率低,查询速度较慢。

delete

删除阶段。索引将被删除。

为索引添加生命周期管理策略有两种方式:

  • 为索引模板添加策略:策略应用到别名覆盖的所有索引,本文以此为例。

  • 为单个索引添加策略:只覆盖当前索引,新滚动的索引不受该策略影响。

本文以冷热数据场景为例,演示以下配置流程:

  1. 将索引数据实时写入Elasticsearch,当数据增加到一定量时自动写入新索引。

  2. 旧索引在hot阶段停留30分钟后进入warm阶段。

  3. warm阶段完成MergeShrink操作后,索引在1小时(从滚动更新时算起)后进入cold阶段。

  4. cold阶段将数据迁移到冷数据节点,索引在2小时(从滚动更新时算起)后被删除。

操作流程

  1. 步骤一:创建冷热集群并查看节点的冷热属性

    在创建集群时设置节点的冷热属性。

  2. 步骤二:为索引配置生命周期管理策略

    定义ILM策略,并将该策略应用到别名覆盖的所有索引下。

  3. 步骤三:验证数据分布

    验证cold阶段索引的shard是否分布在冷数据节点上。

  4. 步骤四:更新ILM策略

    更新已有策略。

  5. 步骤五:切换ILM策略

    在不同策略间实现滚动切换。

步骤一:创建冷热集群并查看节点的冷热属性

冷热集群包含冷、热两种属性的节点,热节点处理实时写入,冷节点存储历史数据,两者区别如下。

节点类型

存储数据要求

读写性能要求

规格要求

存储要求

热节点(hot)

近期数据,例如最近2天的日志数据。

高,例如3264 GB

建议使用SSD云盘。

冷节点(warm)

历史数据,例如2天之前的日志数据。

低,例如832 GB

建议使用高效云盘,或使用OpenStore实现海量冷数据Serverless存储。

阿里云Elasticsearch中,冷数据节点的box_type值为warm(非cold),这是因为冷数据节点在Elasticsearch原生架构中对应warm tier。
  1. 创建阿里云Elasticsearch实例时,启用冷数据节点,即可创建冷热集群。

  2. 启用冷数据节点并购买后,系统会在节点启动参数中加入-Enode.attr.box_type参数:

    • 热数据节点:-Enode.attr.box_type=hot

    • 冷数据节点:-Enode.attr.box_type=warm

    只有启用冷数据节点后,数据节点才会变成热节点。
  3. 登录该集群的Kibana控制台,具体操作请参见通过Kibana连接集群

  4. 在左侧导航栏,单击Dev Tools

  5. Console 中,执行如下命令,查看集群冷热节点属性。

    GET _cat/nodeattrs?v&h=host,attr,value

    返回结果中包含hotwarm节点,表示集群已支持冷热架构。

步骤二:为索引配置生命周期管理策略

  1. Kibana控制台中,执行如下命令,定义ILM策略。

    PUT /_ilm/policy/game-policy
    {
      "policy": {
        "phases": {
          "hot": {
            "actions": {
              "rollover": {
                "max_size": "1GB",
                "max_age": "1d",
                "max_docs": 1000
              }
            }
          },
          "warm": {
            "min_age": "30m",
            "actions": {
              "forcemerge": {
                    "max_num_segments":1
                  },
              "shrink": {
                    "number_of_shards":1
                  }
            }
          },
          "cold": {
            "min_age": "1h",
            "actions": {
              "allocate": {
                "require": {
                  "box_type": "warm"
                }
              }
            }
          },
          "delete": {
            "min_age": "2h",
            "actions": {
              "delete": {}
            }
          }
        }
      }
    }

    参数

    说明

    hot

    索引满足任一条件(数据达到1 GB、使用超过1天、文档数超过1000)时触发滚动更新。旧索引在滚动更新后等待30分钟进入warm阶段。rollover支持max_docs、max_size、max_age三种条件,满足任一即触发。

    warm

    将索引收缩到1个分片,强制合并为1个段。完成后,索引在1小时(从滚动更新时算起)后进入cold阶段。

    cold

    将索引从hot节点迁移到warm(冷数据)节点。完成后,索引在2小时后进入delete阶段。

    delete

    索引被删除。

    策略名创建后无法更改。通过Kibana控制台也可以创建策略,但Kibanamax_age最小单位为小时,API方式最小单位为秒。
  2. 创建索引模板,在settings中指定冷热属性,数据写入后存储在hot节点上。

    PUT _template/gamestabes_template
    {
      "index_patterns" : ["gamestabes-*"],
      "settings": {
        "index.number_of_shards": 5,
        "index.number_of_replicas": 1,
        "index.routing.allocation.require.box_type":"hot",
        "index.lifecycle.name": "game-policy",
        "index.lifecycle.rollover_alias": "gamestabes"
      }
    }

    参数

    说明

    index.routing.allocation.require.box_type

    指定索引新建时分配的节点类型。

    index.lifecycle.name

    指定生命周期策略名称。

    index.lifecycle.rollover_alias

    指定rollover别名。

  3. 基于序号创建初始索引。

    PUT gamestabes-000001
    {
    "aliases": {
        "gamestabes":{
           "is_write_index": true
            }
          }
    }

    也可以基于时间创建索引,详情请参见using date math

  4. 通过别名写入数据。当数据达到rollover条件并触发ILM检测周期后,索引将进行滚动更新。

    PUT gamestabes/_doc/1
    {
        "EU_Sales" : 3.58,
        "Genre" : "Platform",
        "Global_Sales" : 40.24,
        "JP_Sales" : 6.81,
        "Name" : "Super Mario Bros.",
        "Other_Sales" : 0.77,
        "Platform" : "NES",
        "Publisher" : "Nintendo",
        "Year_of_Release" : "1985",
        "na_Sales" : 29.08
    }
    ILM默认10分钟检测一次符合策略标准的索引。可通过indices.lifecycle.poll_interval参数修改检测周期
  5. (可选)在Kibana中查看索引生命周期状态。

    1. 在左侧导航栏,单击 Management

    2. Elasticsearch 区域中,单击 Index Management

    3. 单击 Lifecycle phase 下拉列表,选择生命周期阶段过滤索引。

    4. 单击过滤后的索引名称,查看索引详细配置。

步骤三:验证数据分布

当索引进入cold阶段后,验证其shard是否已分布在冷数据节点上。

  1. Kibana控制台中,查询进入cold阶段的索引名称。

  2. 执行以下命令,查询该索引的shard分布情况。将shrink-gamestables-000012替换为实际的索引名称。

    GET _cat/shards/shrink-gamestables-000012

    返回结果中,如果shard所在节点的box_typewarm,表示cold阶段的索引数据已分布在冷数据节点上。

步骤四:更新ILM策略

  1. 执行以下命令更新已有的ILM策略。以修改game-policydelete阶段时间为例:

    PUT /_ilm/policy/game-policy
    {
      "policy": {
        "phases": {
          "hot": {
            "actions": {
              "rollover": {
                "max_size": "1GB",
                "max_age": "1d",
                "max_docs": 1000
              }
            }
          },
          "warm": {
            "min_age": "30m",
            "actions": {
              "forcemerge": {
                    "max_num_segments":1
                  },
              "shrink": {
                    "number_of_shards":1
                  }
            }
          },
          "cold": {
            "min_age": "1h",
            "actions": {
              "allocate": {
                "require": {
                  "box_type": "warm"
                }
              }
            }
          },
          "delete": {
            "min_age": "3h",
            "actions": {
              "delete": {}
            }
          }
        }
      }
    }
  2. 查看更新后的策略版本。

    1. 在左侧导航栏,单击 Management

    2. Elasticsearch 区域中,单击 Index Lifecycle Policies

    3. 查看策略版本号。更新后版本号增加1,当前正在滚动写入的索引仍使用旧版本策略,新策略在下次滚动更新时生效。

步骤五:切换ILM策略

  1. 创建新策略。

    PUT /_ilm/policy/game-new
    {
      "policy": {
        "phases": {
          "hot": {
            "actions": {
              "rollover": {
                "max_size": "3GB",
                "max_age": "1d",
                "max_docs": 1000
              }
            }
          },
          "warm": {
            "min_age": "30m",
            "actions": {
              "forcemerge": {
                    "max_num_segments":1
                  },
              "shrink": {
                    "number_of_shards":1
                  }
            }
          },
          "cold": {
            "min_age": "1h",
            "actions": {
              "allocate": {
                "require": {
                  "box_type": "warm"
                }
              }
            }
          },
          "delete": {
            "min_age": "2h",
            "actions": {
              "delete": {}
            }
          }
        }
      }
    }
  2. 为模板绑定新策略。

    PUT _template/gamestabes_template
    {
      "index_patterns" : ["gamestabes-*"],
      "settings": {
        "index.number_of_shards": 5,
        "index.number_of_replicas": 1,
        "index.routing.allocation.require.box_type":"hot",
        "index.lifecycle.name": "game-new",
        "index.lifecycle.rollover_alias": "gamestabes"
      }
    }

常见问题

如何调整ILM策略检查频率?

ILM默认每10分钟检查一次符合策略的索引,在此期间数据量可能超出设定阈值。例如设置max_docs1000,实际文档数可能在超过1000后才触发滚动更新。

通过修改indices.lifecycle.poll_interval参数可控制检查频率:

重要

检查频率过高会增加节点负载,建议根据业务需求谨慎设置。

PUT _cluster/settings
{
  "transient": {
    "indices.lifecycle.poll_interval":"1m"
  }
}