本文介绍在阿里云Elasticsearch集群上,通过生命周期管理ILM(Index Lifecycle Management)功能,实现冷热数据分离的实践流程。通过本实践,您既可以实现在保证集群读写性能的基础上,自动维护集群上的冷热数据,又能通过优化集群架构,降低企业生产成本。

背景信息

当今大数据时代,数据时刻在更新变化。尤其是随着时间的积累,存储在阿里云Elasticsearch中的数据会越来越多,当数据达到一定量时,必然会造成服务的内存、CPU、IO等指标上涨,影响Elasticsearch的全文检索能力。为此Elasticsearch 6.6.0及以上版本提供了索引生命周期管理ILM功能,将索引生命周期分为4个阶段:hot、warm、cold、delete。其中hot阶段主要负责对索引进行滚动更新操作,warm、cold、delete阶段主要负责进一步处理索引数据,详细说明如下。
阶段 描述
hot 热数据阶段。主要处理时序数据的实时写入,可根据索引的文档数、大小、时长决定是否调用rollover API来滚动更新索引。
warm warm阶段。索引不再写入,主要用来提供查询。
cold 冷数据阶段。索引不再更新,查询很少,查询速度会变慢。
delete 删除数据阶段。索引将被删除。
您可以通过两种方式为索引添加生命周期管理策略:
  • 为索引模板添加生命周期管理策略:将策略应用到整个别名覆盖的索引下,本文以此为例。
  • 为单个索引添加生命周期管理策略:只能覆盖当前索引,新滚动的索引不再受策略影响。
在时序和冷热数据场景上应用ILM,可以大幅度节约存储成本。本文以冷热数据场景为例,介绍如何使用ILM功能。配置场景如下:
  1. 将索引数据实时写入Elasticsearch。当索引数据增加到一定量时,数据自动写入新索引。
  2. 旧索引在hot阶段停留30分钟,进入warm阶段。
  3. warm阶段完成Merge及Shrink操作后,索引等待1小时(从滚动更新时算起),进入cold阶段。
  4. cold阶段将热节点数据迁移到冷节点,实现冷热数据分离后,索引会在2个小时(从滚动更新时算起)后被删除。

注意事项

  • Elasticsearch索引生命周期策略需密切贴近业务模型。例如,对多个不同结构的索引进行生命周期管理,建议各个索引配置独立的别名和生命周期策略,以便于管理。
  • 使用rollover滚动索引,初始索引应以自增数字结尾(-000001),否则策略不生效,长度要求为6。例如,定义初始索引为myindex-000001,则rollover后的索引是myindex-000002,以此类推进行递增。如果集群中索引名不符合规范,建议进行索引重建。
  • hot阶段主要处理数据写入。业务中需保证数据是按照时间顺序写入的,处于warm和cold阶段的索引不建议进行数据写入。例如,在warm阶段配置actionsshrinkread only,那么索引进入warm阶段后将处于只读状态,数据无法写入。

操作流程

  1. 步骤一:创建冷热集群并查看节点的冷热属性
    在创建集群时设置节点的冷热属性。
  2. 步骤二:为索引配置生命周期管理策略
    定义ILM策略,并将该策略应用到别名覆盖的所有索引下。
  3. 步骤三:验证数据分布
    验证cold阶段索引的shard是否分布在冷数据节点上。
  4. 步骤四:更新ILM策略
    更新已有策略。
  5. 步骤五:切换ILM策略
    在不同策略间实现滚动切换。

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

冷热集群是指在集群中包含冷、热两种属性的节点,可以提高Elasticsearch的处理性能和服务稳定性。两者区别如下。
节点类型 存储数据要求 读写性能要求 规格要求 存储要求
热节点(hot) 近期数据,例如最近2天的日志数据。 高,例如32核64 GB 建议使用SSD云盘存储数据,存储空间大小需根据数据大小进行设置。
冷节点(warm) 历史数据,例如2天之前的日志数据。 低,例如8核32 GB
  • 建议使用高效云盘存储数据,存储空间大小需根据数据大小进行设置。
  • 建议使用阿里云自研OpenStore存储功能,实现海量冷数据Serverless存储,详细信息请参见通过OpenStore实现海量数据存储
  1. 购买阿里云Elasticsearch实例时,启用冷数据节点,即可创建冷热集群。
    当您启用了冷数据节点并购买后,系统会在节点启动参数中加入-Enode.attr.box_type参数。
    • 热数据节点:-Enode.attr.box_type=hot
    • 冷数据节点:-Enode.attr.box_type=warm
    说明
    • 购买实例时,只有当启用了冷数据节点后,数据节点才会变成热节点。
    • 本文以阿里云Elasticsearch 6.7.0版本为例,所涉及的操作及图片仅适用于该版本,其他版本以实际界面为准。
  2. 登录该集群的Kibana控制台,在左侧导航栏,单击Dev Tools
    登录Kibana控制台的具体操作请参见登录Kibana控制台
  3. Console中,执行如下命令,查看集群冷热节点属性。
    GET _cat/nodeattrs?v&h=host,attr,value
    结果显示集群中包含3个hot节点,2个warm节点,支持冷热架构。冷热架构集群

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

  1. 在Kibana控制台中,执行如下命令,通过API方式定义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天、doc数超过1000,就会触发索引滚动更新。此时系统将创建一个新索引,该索引将重新启动策略,而旧索引将在滚动更新后等待30分钟进入warm阶段。
    注意 目前Elasticsearch支持在rollover中配置三种归档策略:max_docs、max_size、max_age,满足其中任何一个条件都会触发索引归档操作。
    warm 索引进入warm阶段后,ILM会将索引收缩到1个分片,强制合并为1个段。完成该操作后,索引将在1小时(从滚动更新时算起)后进入cold阶段。
    cold 索引进入cold阶段后,ILM将索引从hot节点移动到warm(冷数据)节点。完成操作后,索引将在2小时后进入delete阶段。
    delete 索引进入delete阶段后被删除。
    说明
    • 策略名创建后将无法更改。
    • 您也可以在Kibana控制台上创建策略,但是Kibana上指定的max_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分钟检测一次符合策略标准的索引,当达到rollover条件后,索引将滚动到下一阶段,同时配置indices.lifecycle.poll_interval参数,修改检测周期
  5. 根据生命周期阶段过滤索引,并查看索引详细配置。
    1. 在左侧导航栏,单击Management
    2. Elasticsearch区域中,单击Index Management
    3. Index management中,单击Lifecycle status右侧的Lifecycle phase,从下拉列表中选择生命周期阶段进行过滤。
      根据生命周期过滤索引
    4. 单击过滤后的索引,查看索引详细信息。
      查看索引详细信息

步骤三:验证数据分布

  1. 查询进入cold阶段的索引,并查看其配置信息。
    查询进入cold阶段的索引
  2. 查询处于cold阶段索引的shard分布。
    GET _cat/shards?shrink-gamestables-000012
    返回结果如下。根据返回结果可知,cold阶段的索引数据主要分布在冷数据节点上。返回结果

步骤四:更新ILM策略

  1. 更新正在运行的ILM策略。
    更新ILM策略
  2. 查看更新后的策略版本。
    1. 在左侧导航栏,单击Management
    2. Elasticsearch区域中,单击Index Lifecycle Policies
    3. Index lifecycle policies中,查看更新后的策略版本。
      更新后策略的版本号增加1,此时正在滚动写入的索引依旧使用旧策略,新策略将在下次滚动更新时生效。查看更新后的ILM策略版本

步骤五:切换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"
      }
    }
    注意
    • 切换策略后,新策略不会立即生效。当前正在滚动写入的索引依旧使用旧策略,直到当前索引rollover生成新索引,新策略才会生效。
    • 应用旧策略创建的索引,依旧绑定旧策略。如果您需要为这些索引绑定新策略,可执行PUT gamestabes-*/_settings命令,详情请参见switching policies for an index

常见问题

Q:如何设置ILM策略周期?

A:由于索引生命周期策略默认是10分钟检查一次符合策略的索引,因此在这10分钟内索引中的数据可能会超出指定的阈值。例如在步骤二:为索引配置生命周期管理策略时,设置max_docs为1000,但doc数量在超过1000后才触发索引滚动更新,此时可通过修改indices.lifecycle.poll_interval参数来控制检查频率,使索引在阈值范围内滚动更新。
注意 请慎重修改该参数值,避免时间间隔太短给节点增加不必要的负载,本测试中将其改成了1m
PUT _cluster/settings
{
  "transient": {
    "indices.lifecycle.poll_interval":"1m"
  }
}