首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >干货 | Elasticsearch 索引生命周期管理 ILM 实战指南

干货 | Elasticsearch 索引生命周期管理 ILM 实战指南

作者头像
铭毅天下
发布于 2021-06-25 12:06:43
发布于 2021-06-25 12:06:43
7.6K00
代码可运行
举报
文章被收录于专栏:铭毅天下铭毅天下
运行总次数:0
代码可运行

1、什么是索引生命周期?

关于人生,有人这么说:“人,生来一个人,死去一个人,所以,人生就是一个人生老病死的简称。”

在基于日志、指标、实时时间序列的大型系统中,集群的索引也具备类似上图中相通的属性,一个索引自创建之后,不可能无限期的存在下去, 从索引产生到索引“消亡”,也会经历:“生、老、病、死”的阶段。

我们把索引的“生、老、病、死”的全过程类比称为索引的生命周期。

2、什么是索引生命周期管理?

由于自然规律,人会“不可逆转”的由小长到大,由大长到老,且理论上年龄一般不会超过 150 岁(吉尼斯世界纪录:122岁零164天)。

索引不是人,理论上:一旦创建了索引,它可以一直存活下去(假定硬件条件允许,寿命是无限的)。

索引创建后,它自身是相对静态的,没有“自然规律”牵引它变化,若放任其成长,它只会变成一个数据量极大的臃肿的“大胖子”。

这里可能就会引申出来问题:若是时序数据的索引,随着时间的推移,业务索引的数据量会越来越大。但,基于如下的因素:

  • 集群的单个分片最大文档数上限:2 的 32 次幂减去 1(20亿左右)。
  • 索引最佳实践官方建议:分片大小控制在30GB-50GB,若索引数据量无限增大,肯定会超过这个值。
  • 索引大到一定程度,当索引出现健康问题,会导致真个集群核心业务不可用。
  • 大索引恢复的时间要远比小索引恢复慢的多得多。
  • 索引大之后,检索会很慢,写入和更新也会受到不同程度的影响。
  • 某些业务场景,用户更关心最近3天、最近7天的业务数据,大索引会将全部历史数据汇集在一起,不利于这种场景的查询。

非常有必要对索引进行管理起来,不再放任其“野蛮长成体弱多病、潜在风险极大的大胖子”,而是限制其分阶段、有目标的、有规律的生长。

这种分阶段、有目标的操作和实现,我们称为索引生命周期管理。

3、索引生命周期管理的历史演变

索引生命周期管理 (ILM) 是在 Elasticsearch 6.6(公测版)首次引入,在 6.7 版本正式推出的一项功能。

ILM 是 Elasticsearch 的一部分,主要用来帮助用户管理索引。

没有 ILM 之前索引生命周期管理基于:rollover + curator 实现。

ILM 是早些年呼声非常高的功能之一,我印象中 2017 年南京的 meetup 中,就有公司说实现了类似的功能。

Kibana 7.12.0 索引生命周期管理配置界面如下图所示:

4、索引生命周期管理的前提

本文演示试用版本:Elasticesarch:7.12.0,Kibana:7.12.0。

集群规模:3节点,属性(node_roles)设置分别如下:

  • 节点 node-022:主节点+数据节点+热节点(Hot)。
  • 节点 node-023:主节点+数据节点+温节点(Warm)。
  • 节点 node-024:主节点+数据节点+冷节点(Cold)。

4.1 冷热集群架构

冷热架构也叫热暖架构,是“Hot-Warm” Architecture的中文翻译。

冷热架构本质是给节点设置不同的属性,让每个节点具备了不同的属性。

为演示 ILM,需要首先配置冷热架构,三个节点在 elasticsearch.yml 分别设置的属性如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- node.attr.box_type: hot
- node.attr.box_type: warm
- node.attr.box_type: cold

拿舆情数据举例,通俗解读如下:

  • 热节点(Hot):存放用户最关心的热数据。

比如:最近3天的数据——近期大火的“曹县牛皮666,我的宝贝”。

  • 温节点(Warm):存放前一段时间沉淀的热数据,现在不再热了。

比如:3-7天的热点事件——“特斯拉车顶事件”。

  • 冷节点(Cold):存放用户不太关心或者关心优先级低的冷数据,很久之前的热点事件。

比如:7天前或者很久前的热点事件——去年火热的“后浪视频“、”马老师不讲武德”等。

如果磁盘数量不足,冷数据是待删除优先级最高的。

如果硬件资源不足,热节点优先配置为 SSD 固态盘。

检索优先级最高的是热节点的数据,基于热节点检索数据自然比基于全量数据响应时间要快。

更多冷热架构推荐:干货 | Elasticsearch 冷热集群架构实战

4.2 rollover 滚动索引

实际Elasticsearch 5.X 之后的版本已经推出:Rollover API。Rollover API解决的是以日期作为索引名称的索引大小不均衡的问题。

Rollover API对于日志类的数据非常有用,一般我们按天来对索引进行分割(数据量更大还能进一步拆分),没有Rollover之前,需要在程序里设置一个自动生成索引的模板。

推荐阅读:干货 | Elasticsearch索引生命周期管理探索

rollover 滚动索引实践一把:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 1、创建基于日期的索引
PUT %3Cmy-index-%7Bnow%2Fd%7D-000001%3E
{
  "aliases": {
    "my-alias": {
      "is_write_index": true
    }
  }
}

# 2、批量导入数据
PUT my-alias/_bulk
{"index":{"_id":1}}
{"title":"testing 01"}
{"index":{"_id":2}}
{"title":"testing 02"}
{"index":{"_id":3}}
{"title":"testing 03"}
{"index":{"_id":4}}
{"title":"testing 04"}
{"index":{"_id":5}}
{"title":"testing 05"}

# 3、rollover 滚动索引
POST my-alias/_rollover
{
  "conditions": {
    "max_age": "7d",
    "max_docs": 5,
    "max_primary_shard_size": "50gb"
  }
}

GET my-alias/_count

# 4、在满足滚动条件的前提下滚动索引
PUT my-alias/_bulk
{"index":{"_id":6}}
{"title":"testing 06"}

# 5、检索数据,验证滚动是否生效
GET my-alias/_search

如上的验证结论是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
        "_index" : "my-index-2021.05.30-000001",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0,
        "_source" : {
          "title" : "testing 05"
        }
      },
      {
        "_index" : "my-index-2021.05.30-000002",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : 1.0,
        "_source" : {
          "title" : "testing 06"
        }
      }

_id 为 6 的数据索引名称变成了:my-index-2021.05.30-000002,实现了 后缀 id 自增。

这里要强调下,索引滚动变化的三个核心条件:

  • "max_age": "7d", 最长期限 7d,超过7天,索引会实现滚动。
  • "max_docs": 5, 最大文档数 5,超过 5个文档,索引会实现滚动(测试需要,设置的很小)。
  • "max_primary_shard_size": "50gb",主分片最大存储容量 50GB,超过50GB,索引就会滚动。

注意,三个条件是或的关系,满足其中一个,索引就会滚动。

4.3 shrink 压缩索引

压缩索引的本质:在索引只读等三个条件的前提下,减少索引的主分片数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 设置待压缩的索引,分片设置为5个。
PUT kibana_sample_data_logs_ext
{
  "settings": {
    "number_of_shards":5
  }
}

# 准备索引数据
POST _reindex
{
  "source":{
    "index":"kibana_sample_data_logs"
  },
  "dest":{
    "index":"kibana_sample_data_logs_ext"
  }
}

# shrink 压缩之前的三个必要条件
PUT kibana_sample_data_logs_ext/_settings
{
  "settings": {
    "index.number_of_replicas": 0,
    "index.routing.allocation.require._name": "node-024", 
    "index.blocks.write": true                                    
  }
}

# 实施压缩
POST kibana_sample_data_logs_ext/_shrink/kibana_sample_data_logs_shrink
{
  "settings": {
    "index.number_of_replicas": 0,
    "index.number_of_shards": 1, 
    "index.codec": "best_compression" 
  },
  "aliases": {
    "kibana_sample_data_logs_alias": {}
  }
}

有图有真相:

强调一下三个压缩前的条件,缺一不可:

  • "index.number_of_replicas": 0 副本设置为 0。
  • "index.routing.allocation.require._name": "node-024" 分片数据要求都集中到一个独立的节点。
  • "index.blocks.write": true 索引数据只读。

4.4 Frozen 冷冻索引

为高效检索,核心业务索引都会保持在内存中,意味着内存使用率会变得很高。

对于一些非业务必须、非密集访问的某些索引,可以考虑释放内存,仅磁盘存储,必要的时候再还原检索。

这时候,就会用到 Frozen 冷冻索引。除了在内存中维护其元数据,冻结索引在集群上几乎没有开销,并且冷冻索引是只读的。

具体使用如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 冷冻索引
POST kibana_sample_data_logs_shrink/_freeze

# 冷冻后,不能写入
POST kibana_sample_data_logs_shrink/_doc/1
{
  "test":"12111"
}

# 冷冻后,能检索,但不返回具体数据,只返回0POST kibana_sample_data_logs_shrink/_search

# 解除冷冻
POST kibana_sample_data_logs_shrink/_unfreeze

# 解除冷冻后,可以检索和写入了
POST kibana_sample_data_logs_shrink/_search

综合上述拆解分析可知:

有了:冷热集群架构,集群的不同节点有了明确的角色之分,冷热数据得以物理隔离,SSD 固态盘使用效率会更高。

有了:rollover 滚动索引,索引可以基于文档个数、时间、占用磁盘容量滚动升级,实现了索引的动态变化。

有了:Shrink 压缩索引、Frozen 冷冻索引,索引可以物理层面压缩、冷冻,分别释放了磁盘空间和内存空间,提高了集群的可用性。

除此之外,还有:Force merge 段合并、Delete 索引数据删除等操作,索引的“生、老、病、死”的全生命周期的更迭,已然有了助推器。

如上指令单个操作,非常麻烦和繁琐,有没有更为快捷的方法呢?

有的!

第一:命令行可以 DSL 大综合实现。

第二:可以借助 Kibana 图形化界面实现。

下面两小节会结合实例解读。

5、Elasticsearch ILM 实战

5.1 核心概念:不同阶段(Phrase)的功能点(Acitons)

注意:仅在 Hot 阶段可以设置:Rollover 滚动。

5.2 各生命周期 Actions 设定

后两节演示要用。

5.2.1 Hot 阶段

  • 基于:max_age=3天、最大文档数为5、最大size为:50gb rollover 滚动索引。
  • 设置优先级为:100(值越大,优先级越高)。

5.2.2 Warm 阶段

  • 实现段合并,max_num_segments 设置为1.
  • 副本设置为 0。
  • 数据迁移到:warm 节点。
  • 优先级设置为:50。

5.2.3 Cold 阶段

  • 冷冻索引
  • 数据迁移到冷节点

5.2.4 Delete 阶段

  • 删除索引

关于触发滚动的条件:

  • Hot 阶段的触发条件:手动创建第一个满足模板要求的索引。
  • 其余阶段触发条件:min_age,索引自创建后的时间。

时间类似:业务里面的 热节点保留 3 天,温节点保留 7 天,冷节点保留 30 天的概念。

5.3 DSL 实战索引生命周期管理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# step1: 前提:演示刷新需要
PUT _cluster/settings
{
  "persistent": {
    "indices.lifecycle.poll_interval": "1s"
  }
}

# step2:测试需要,值调的很小
PUT _ilm/policy/my_custom_policy_filter
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_age": "3d",
            "max_docs": 5,
            "max_size": "50gb"
          },
          "set_priority": {
            "priority": 100
          }
        }
      },
      "warm": {
        "min_age": "15s",
        "actions": {
          "forcemerge": {
            "max_num_segments": 1
          },
          "allocate": {
            "require": {
              "box_type": "warm"
            },
            "number_of_replicas": 0
          },
          "set_priority": {
            "priority": 50
          }
        }
      },
      "cold": {
        "min_age": "30s",
        "actions": {
          "allocate": {
            "require": {
              "box_type": "cold"
            }
          },
          "freeze": {}
        }
      },
      "delete": {
        "min_age": "45s",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

# step3:创建模板,关联配置的ilm_policy
PUT _index_template/timeseries_template
{
  "index_patterns": ["timeseries-*"],                 
  "template": {
    "settings": {
      "number_of_shards": 1,
      "number_of_replicas": 0,
      "index.lifecycle.name": "my_custom_policy_filter",      
      "index.lifecycle.rollover_alias": "timeseries",
      "index.routing.allocation.require.box_type": "hot"
    }
  }
}

# step4:创建起始索引(便于滚动)
PUT timeseries-000001
{
  "aliases": {
    "timeseries": {
      "is_write_index": true
    }
  }
}

# step5:插入数据
PUT timeseries/_bulk
{"index":{"_id":1}}
{"title":"testing 01"}
{"index":{"_id":2}}
{"title":"testing 02"}
{"index":{"_id":3}}
{"title":"testing 03"}
{"index":{"_id":4}}
{"title":"testing 04"}

# step6:临界值(会滚动)
PUT timeseries/_bulk
{"index":{"_id":5}}
{"title":"testing 05"}

# 下一个索引数据写入
PUT timeseries/_bulk
{"index":{"_id":6}}
{"title":"testing 06"}

核心步骤总结如下:

  • 第一步:创建生周期 policy。
  • 第二步:创建索引模板,模板中关联 policy 和别名。
  • 第三步:创建符合模板的起始索引,并插入数据。
  • 第四步: 索引基于配置的 ilm 滚动。

实现效果如下GIF动画(请耐心看完)

5.4、Kibana 图形化界面实现索引生命周期管理

步骤 1:配置 policy。

步骤 2:关联模板。

前提条件:

模板要自己 DSL 创建,以便关联。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PUT _index_template/timebase_template 
{ "index_patterns": ["time_base-*"] }

创建起始索引,指定别名和写入。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PUT time_base-000001 { "aliases": { "timebase_alias": { "is_write_index": true } } }

6、小结

索引生命周期管理需要加强对三个概念的认知:

  • 横向——Phrase 阶段:Hot、Warm、Cold、Delete 等对应索引的生、老、病、死。
  • 纵向——Actions 阶段:各个阶段的动作。
  • 横向纵向整合的Policy:实际是阶段和动作的综合体。

配置完毕Policy,关联好模板 template,整个核心工作就完成了80%。

剩下就是各个阶段 Actions 的调整和优化了。

实战表明:用 DSL 实现ILM 比图形化界面更可控、更便于问题排查。

ILM 你实际生产环境使用了吗?效果如何?欢迎留言讨论。

参考

https://www.elastic.co/guide/en/elasticsearch/reference/current/example-using-index-lifecycle-policy.html

https://ptran32.github.io/2020-08-08-hot-warm-cold-elasticsearch/

https://www.elastic.co/cn/blog/implementing-hot-warm-cold-in-elasticsearch-with-index-lifecycle-management

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 铭毅天下Elasticsearch 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
JVM常见面试题(四):垃圾回收
当需要排查各种内存溢出问题、当垃圾收集成为系统达到更高并发的瓶颈时,我们就需要对这些“自动化"的技术实施必要的监控和调节。
寻求出路的程序媛
2024/11/24
2840
JVM常见面试题(四):垃圾回收
深入理解Java中的Garbage Collection
最近由于系统业务量比较大,从生产的GC日志(结合Pinpoint)来看,需要对部分系统进行GC调优。但是鉴于以往不是专门做这一块,但是一直都有零散的积累,这里做一个相对全面的总结。本文只针对HotSpot VM也就是Oracle Hotspot VM或者OpenJDK Hotspot VM,版本为Java8,其他VM不一定适用。
Throwable
2020/06/23
7990
深入理解Java中的Garbage Collection
JVM内存模型和垃圾回收机制
有的博客称方法区是永久代,那是因为前者是JVM的规范,而后者则是JVM规范的一种实现,并且只有HotSpot才有永久代,
全菜工程师小辉
2019/08/16
7710
JVM内存管理
Java内存管理是一项持续的挑战,同时也是锻造出可拓展应用的必备技能。本质上,Java内存管理就是一个为新对象分配内存和释放无用对象内存的过程。
码代码的陈同学
2018/06/03
2.3K0
JVM内存管理
java(9)-深入浅出GC垃圾回收机制
1、本文了解GC垃圾回收机制,深入理解GC后才明白,为啥FGC会导致stop-the-world。 2、了解GC算法。
黄规速
2022/04/14
1.1K0
java(9)-深入浅出GC垃圾回收机制
Java虚拟机
程序计数器不会产生StackOverflowError和OutOfMemoryError.
知识浅谈
2022/01/01
1K0
面试官:说说JVM内存整体结构?
Java 虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程一一对应的数据区域会随着线程开始和结束而创建和销毁。
鲁大猿
2024/01/04
2940
面试官:说说JVM内存整体结构?
自动的内存管理系统实操手册——Java垃圾回收篇
导语 | 现代高级编程语言管理内存的方式分自动和手动两种。手动管理内存的典型代表是C和C++,编写代码过程中需要主动申请或者释放内存;而PHP、Java 和Go等语言使用自动的内存管理系统,由内存分配器和垃圾收集器来代为分配和回收内存,其中垃圾收集器就是我们常说的GC。本文中,腾讯后台开发工程师汪汇从原理出发,介绍 Java 和Golang垃圾回收算法,并从原理上对他们做一个对比。今天先向大家分享 Java 垃圾回收算法。 一、 垃圾回收区域及划分 在介绍 Java 垃圾回收之前,我们需要了解 Jav
腾讯云开发者
2021/08/04
5810
Java基础知识:JVM内存结构
jvm将虚拟机分为 5大区域 ,程序计数器、虚拟机栈、本地方法栈、java堆、方法区;
DioxideCN
2022/08/05
8060
Java基础知识:JVM内存结构
JVM 内存模型面试总结
就是 JAVA 虚拟机, 它只识别 .class 类型文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。
Tim在路上
2020/08/04
5850
2万字长文包教包会 JVM 内存结构
内存是非常重要的系统资源,是硬盘和 CPU 的中间仓库及桥梁,承载着操作系统和应用程序的实时运行。JVM 内存布局规定了 Java 在运行过程中内存申请、分配、管理的策略,保证了 JVM 的高效稳定运行。不同的 JVM 对于内存的划分方式和管理机制存在着部分差异。
Java3y
2020/07/09
5390
2万字长文包教包会 JVM 内存结构
JVM-01Java内存区域与内存溢出异常(上)【运行时区域数据】
在内存管理领域 ,C/C++内存管理由开发人员管理,既拥有每一个对象的所有权,还必须负责维护每一个对象生命从开始到终结的责任
小小工匠
2021/08/16
4250
JVM的内存管理(堆内存)
也称heap堆区。堆是jvm内存中占用空间最大的一个区域。主要分为新生代、老年代、永久代(jdk1.8以后叫元空间,到1.9以后又被移除)
用户7410760
2024/12/14
3220
JVM的内存管理(堆内存)
Java内存区域和GC机制
  Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。概括地说,该机制对 JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息(Nerver Stop)的保证JVM中的内存空间,放置出现内存泄露和溢出问题。
Java团长
2018/08/06
5540
JVM基础
参考链接:https://www.cnblogs.com/yrxing/p/14464799.html
橘子又加强了么
2023/09/25
3170
面霸篇:JVM 21 问与答
jvm将虚拟机分为5大区域,程序计数器、虚拟机栈、本地方法栈、java堆、方法区;
码哥字节
2021/08/23
5190
面霸篇:JVM 21 问与答
「周一电台 x 训练营」从三道题开始,认识Java内存
几乎所有的对象实例以及数组在堆里分配内存。Java堆还是垃圾收集器(Garbage Collection,GC)管理的主要区域,因此我们也可以叫它GC堆,请勿叫做垃圾堆!
翊君
2022/03/15
3220
「周一电台 x 训练营」从三道题开始,认识Java内存
面试:精通Java;面试官:来讲一下JVM虚拟机内存模型的最底层原理,必须说详细说清楚,知其所以然。看完后,你还敢在简历上写精通Java吗?
精通Java?来看看下面这些底层中的底层原理你是否知道吧。 提到JVM必不可少的就得谈到它的内存模型,根据 JVM 规范,JVM 内存共分为虚拟机栈VM stack、堆heap、方法区Method Area、程序计数器Program Counter Register、本地方法栈Native Method Stack五个部分。如下图,咋们分别对这五个区域进行详细的原理讲解。(为节省读者的时间,方便大家理解记忆,笔者把全部知识点分层分段,用较短的语言去描述,言简意赅,句句都是重点。)
全栈程序员站长
2022/08/26
4150
面试:精通Java;面试官:来讲一下JVM虚拟机内存模型的最底层原理,必须说详细说清楚,知其所以然。看完后,你还敢在简历上写精通Java吗?
醒酒菜:动画图解核心内存区--堆
端午佳节一下子就过完了,大家是不是还沉迷在假期的欢乐气氛中无法自拔?今天阿Q为大家准备了上好的“醒酒菜”——JVM运行时数据区的核心内存区——堆。
阿Q说代码
2021/06/22
4730
醒酒菜:动画图解核心内存区--堆
基于JDK8的JVM内存模型详解与GC策略
在JDK 8中,永久代被删除,类元数据在本机内存中分配。默认情况下,可用于类元数据的本机内存量是无限制的。使用该选项MaxMetaspaceSize可以为用于类元数据的本机内存量设置上限。
yingzi_code
2019/08/31
2.8K0
相关推荐
JVM常见面试题(四):垃圾回收
更多 >
LV.0
这个人很懒,什么都没有留下~
作者相关精选
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验