最新活动

包含文章发布时段最新活动,前往ES产品介绍页,可查找ES当前活动统一入口

Elasticsearch Service自建迁移特惠政策>>

Elasticsearch Service 新用户特惠狂欢,最低4折首购优惠 >>

Elasticsearch Service 企业首购特惠,助力企业复工复产>>

Elasticsearch是目前大数据领域最热门的技术栈之一,腾讯云 Elasticsearch Service(ES)是基于开源搜索引擎 Elasticsearch 打造的高可用、可伸缩的云端全托管 Elasticsearch 服务,完善的高可用解决方案,让业务可以放心的把重要数据存储到腾讯云 ES 中。了解 ES 的索引管理方法有助于扬长避短,更好的利用 ES 的强大功能,特别是当遇到性能问题时,原因通常都可回溯至数据的索引方式以及集群中的分片数量。如果未能在一开始做出最佳选择,随着数据量越来越大,便有可能会引发性能问题。集群中的数据越多,要纠正这一问题就越难,本文旨在帮助大家了解 ES 容量管理的方法,在一开始就管理好索引的容量,避免给后面留坑。

1. 为什么要做索引容量管理

  • 在生产环境使用 ES 要面对的第一个问题通常是索引容量的规划,不合理的分片数,副本数和分片大小会对索引的性能产生直接的影响;

  • Elasticsearch 中的每个索引都由一个或多个分片组成的,每个分片都是一个 Lucene 索引实例,您可以将其视作一个独立的搜索引擎,它能够对 Elasticsearch 集群中的数据子集进行索引并处理相关查询;

  • 查询和写入的性能与索引的大小是正相关的,所以要保证高性能,一定要限制索引的大小,具体来说是限制分片数量和单个分片的大小;

  • 关于分片数量,索引大小的问题这里不再赘述,可以参考 ES 官方 blog 《我在 Elasticsearch 集群内应该设置多少个分片?》(https://www.elastic.co/cn/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster)

  • 直接说结论:ES 官方推荐分片的大小是 20G - 40G,最大不能超过 50G;

本文介绍 3种管理索引容量的方法,从这3种方法可以了解到 ES 管理索引容量的演进过程。

2. 方法1: 使用在索引名称上带上时间的方法管理索引

2.1 创建索引

索引名上带日期的写法:

<static_name{date_math_expr{date_format|time_zone}}>

例如

<logs-{now{yyyyMMddHH|+08:00}}-000001>

参考官方文档:Date math support in index names(https://www.elastic.co/guide/en/elasticsearch/reference/7.x/date-math-index-names.html)

在使用的时候,索引名要 urlencode 后再使用

PUT /%3Cmylogs-%7Bnow%7ByyyyMMddHH%7C%2B08%3A00%7D%7D-000001%3E
{"aliases": {"mylogs-read-alias": {}
}
}

执行结果:

{"acknowledged" : true,"shards_acknowledged" : true,"index" : "mylogs-2020061518-000001"
}

2.2 写入数据

写入数据的时候也要带上日期

POST /%3Cmylogs-%7Bnow%7ByyyyMMddHH%7C%2B08%3A00%7D%7D-000001%3E/_doc
{"name":"xxx"}

执行结果:

{"_index" : "mylogs-2020061518-000001","_type" : "_doc","_id" : "VNZut3IBgpLCCHbxDzDB","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 2,"failed" : 0
},"_seq_no" : 0,"_primary_term" : 1
}

2.3 查询数据

由于数据分布在多个索引里,查询的时候要在符合条件的所有索引查询,可以使用下面的方法查询

2.3.1 使用逗号分割指定多个索引

GET /mylogs-2020061518-000001,mylogs-2020061519-000001/_search
{"query":{"match_all":{}}}

2.3.2 使用通配符查询

GET /mylogs-*/_search
{"query": {"match_all": {}
}
}

执行结果:

{"took" : 0,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0
},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "mylogs-2020061518-000001","_type" : "_doc","_id" : "VNZut3IBgpLCCHbxDzDB","_score" : 1.0,"_source" : {"name" : "xxx"}}]
}
}

2.3.3 使用别名查询

GET /mylogs-read-alias/_search
{"query": {"match_all": {}
}
}

执行结果同上

2.4 使用带日期的索引名称的缺陷

这个方法的优点是比较直观能够通过索引名称直接分辨出数据的新旧,缺点是:

  • 不是所有数据都适合使用时间分割,对于写入之后还有修改的数据不适合

  • 直接使用时间分割也可能存在某段时间数据量集中,导致索引分片超过设计容量的问题,从而影响性能

  • 为了解决上述问题还需要配合 rollover 策略使用,索引的维护比较复杂

3. 方法2: 使用 Rollover 管理索引

Rollover 的原理是使用一个别名指向真正的索引,当指向的索引满足一定条件(文档数或时间或索引大小)更新实际指向的索引。

3.1 创建索引并且设置别名

注意: 索引名称的格式为 {.*}-d 这种格式的,数字默认是 6位

PUT myro-000001
{"aliases": {"myro_write_alias":{}
}
}

3.2 通过别名写数据

使用 bulk 一次写入了 3条记录

POST /myro_write_alias/_bulk?refresh=true
{"create":{}}
{"name":"xxx"}
{"create":{}}
{"name":"xxx"}
{"create":{}}
{"name":"xxx"}

执行结果:

{"took" : 37,"errors" : false,"items" : [{"create" : {"_index" : "myro-000001","_type" : "_doc","_id" : "wVvFtnIBUTVfQxRWwXyM","_version" : 1,"result" : "created","forced_refresh" : true,"_shards" : {"total" : 2,"successful" : 2,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1,"status" : 201}},{"create" : {"_index" : "myro-000001","_type" : "_doc","_id" : "wlvFtnIBUTVfQxRWwXyM","_version" : 1,"result" : "created","forced_refresh" : true,"_shards" : {"total" : 2,"successful" : 2,"failed" : 0},"_seq_no" : 1,"_primary_term" : 1,"status" : 201}},{"create" : {"_index" : "myro-000001","_type" : "_doc","_id" : "w1vFtnIBUTVfQxRWwXyM","_version" : 1,"result" : "created","forced_refresh" : true,"_shards" : {"total" : 2,"successful" : 2,"failed" : 0},"_seq_no" : 2,"_primary_term" : 1,"status" : 201}}
]
}

记录都写到了 myro-000001 索引下

3.3 执行 rollover 操作

rollover 的3个条件是并列关系,任意一个条件满足就会发生 rollover

POST /myro_write_alias/_rollover
{"conditions": {"max_age":   "7d","max_docs":  3,"max_size": "5gb"
}
}

执行结果:

{"acknowledged" : true,"shards_acknowledged" : true,"old_index" : "myro-000001","new_index" : "myro-000002","rolled_over" : true,"dry_run" : false,"conditions" : {"[max_docs: 3]" : true,"[max_size: 5gb]" : false,"[max_age: 7d]" : false
}
}

分析一下执行结果:

"new_index" : "myro-000002"
"[max_docs: 3]" : true,

从结果看出满足了条件("[max_docs: 3]" : true)发生了 rollover,新的索引指向了 myro-000002

再写入一条记录:

POST /myro_write_alias/_doc
{"name":"xxx"}

已经写入了新的索引,结果符合预期

{"_index" : "myro-000002","_type" : "_doc","_id" : "BdbMtnIBgpLCCHbxhihi","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 2,"failed" : 0
},"_seq_no" : 0,"_primary_term" : 1
}

3.4 使用 Rollover 的缺点

  • 必须明确执行了 rollover 指令才会更新 rollover 的别名对应的索引

  • 通常可以在写入数据之后 再执行一下 rollover 命令,或者采用配置系统 cron 脚本的方式

  • 增加了使用的 rollover 的成本,对于开发者来说不够自动化

4. 方法3: 使用 ILM(Index Lifecycle Management ) 管理索引

ES 一直在索引管理这块进行优化迭代,从6.7版本推出了索引生命周期管理(Index Lifecycle Management ,简称ILM)机制,是目前官方提供的比较完善的索引管理方法。所谓 Lifecycle(生命周期)是把索引定义了四个阶段:

  • Hot:索引可写入,也可查询,也就是我们通常说的热数据,为保证性能数据通常都是在内存中的

  • Warm:索引不可写入,但可查询,介于热和冷之间,数据可以是全内存的,也可以是在 SSD 的硬盘上的

  • Cold:索引不可写入,但很少被查询,查询的慢点也可接受,基本不再使用的数据,数据通常在大容量的磁盘上

  • Delete:索引可被安全的删除

这 4个阶段是 ES 定义的一个索引从生到死的过程, Hot -> Warm -> Cold -> Delete 4个阶段只有 Hot 阶段是必须的,其他3个阶段根据业务的需求可选。

使用方法通常是下面几个步骤:

4.1 建立 Lifecycle 策略

这一步通常在 Kibana 上操作,需要的时候再导出 ES 语句

例如下面这个策略

  • 暂时只配置了 Hot 阶段

  • 为了方便验证,最大文档数(max_docs) 超过 2个时就 rollover

导出的语句如下

PUT _ilm/policy/myes-lifecycle
{"policy": {"phases": {"hot": {"min_age": "0ms","actions": {"rollover": {"max_age": "30d","max_size": "50gb","max_docs": 2},"set_priority": {"priority": 100}}}}
}
}

4.2 建立索引模版

ES 语句如下:

PUT /_template/myes_template
{"index_patterns": ["myes-*"
],"aliases": {"myes_reade_alias": {}
},"settings": {"index": {"lifecycle": {"name": "myes-lifecycle","rollover_alias": "myes_write_alias"},"refresh_interval": "30s","number_of_shards": "12","number_of_replicas": "1"}
},"mappings": {"properties": {"name": {"type": "keyword"}}
}
}

⚠注意:

  • 模版匹配以索引名称 myes- 开头的索引

  • 所有使用此模版创建的索引都有一个别名 myes_reade_alias 用于方便查询数据

  • 模版绑定了上面创建的 Lifecycle 策略,并且用于 rollover 的别名是 myes_write_alias

4.3 创建索引

ES 语句:

PUT /myes-testindex-000001
{"aliases": {"myes_write_alias":{}
}
}

⚠注意:

  • 索引的名称是 .*-d 的形式

  • 索引的别名用于 lifecycle 做 rollover

4.4 查看索引配置

GET /myes-testindex-000001
{}

执行结果:

{"myes-testindex-000001" : {"aliases" : {"myes_reade_alias" : { },"myes_write_alias" : { }},"mappings" : {"dynamic_templates" : [{"message_full" : {"match" : "message_full","mapping" : {"fields" : {"keyword" : {"ignore_above" : 2048,"type" : "keyword"}},"type" : "text"}}},{"message" : {"match" : "message","mapping" : {"type" : "text"}}},{"strings" : {"match_mapping_type" : "string","mapping" : {"type" : "keyword"}}}],"properties" : {"name" : {"type" : "keyword"}}},"settings" : {"index" : {"lifecycle" : {"name" : "myes-lifecycle","rollover_alias" : "myes_write_alias"},"refresh_interval" : "30s","number_of_shards" : "12","translog" : {"sync_interval" : "5s","durability" : "async"},"provided_name" : "myes-testindex-000001","max_result_window" : "65536","creation_date" : "1592222799955","unassigned" : {"node_left" : {"delayed_timeout" : "5m"}},"priority" : "100","number_of_replicas" : "1","uuid" : "tPwDbkuvRjKtRHiL4fKcPA","version" : {"created" : "7050199"}}}
}
}

⚠注意:

  • 索引使用了之前建立的索引模版

  • 索引绑定了 lifecycle 策略并且写入别名是 myes_write_alias

4.5 写入数据

POST /myes_write_alias/_bulk?refresh=true
{"create":{}}
{"name":"xxx"}
{"create":{}}
{"name":"xxx"}
{"create":{}}
{"name":"xxx"}

执行结果:

{"took" : 18,"errors" : false,"items" : [{"create" : {"_index" : "myes-testindex-000001","_type" : "_doc","_id" : "jF3it3IBUTVfQxRW1Xys","_version" : 1,"result" : "created","forced_refresh" : true,"_shards" : {"total" : 2,"successful" : 2,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1,"status" : 201}},{"create" : {"_index" : "myes-testindex-000001","_type" : "_doc","_id" : "jV3it3IBUTVfQxRW1Xys","_version" : 1,"result" : "created","forced_refresh" : true,"_shards" : {"total" : 2,"successful" : 2,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1,"status" : 201}},{"create" : {"_index" : "myes-testindex-000001","_type" : "_doc","_id" : "jl3it3IBUTVfQxRW1Xys","_version" : 1,"result" : "created","forced_refresh" : true,"_shards" : {"total" : 2,"successful" : 2,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1,"status" : 201}}
]
}

⚠注意:

  • 3 条记录都写到了 myes-testindex-000001 中, Lifecycle 策略明明设置的是 2条记录就 rollover 为什么会三条都写到同一个索引了呢?

再次执行上面的语句,写入 3条记录发现新的数据都写到了 myes-testindex-000002 中, 结果符合预期。

{"took" : 17,"errors" : false,"items" : [{"create" : {"_index" : "myes-testindex-000002","_type" : "_doc","_id" : "yl0JuHIBUTVfQxRWvsv5","_version" : 1,"result" : "created","forced_refresh" : true,"_shards" : {"total" : 2,"successful" : 2,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1,"status" : 201}},{"create" : {"_index" : "myes-testindex-000002","_type" : "_doc","_id" : "y10JuHIBUTVfQxRWvsv5","_version" : 1,"result" : "created","forced_refresh" : true,"_shards" : {"total" : 2,"successful" : 2,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1,"status" : 201}},{"create" : {"_index" : "myes-testindex-000002","_type" : "_doc","_id" : "zF0JuHIBUTVfQxRWvsv5","_version" : 1,"result" : "created","forced_refresh" : true,"_shards" : {"total" : 2,"successful" : 2,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1,"status" : 201}}
]
}

⚠注意:

  • 如果按照这个步骤没有发生自动 rollover 数据仍然写到了 myes-testindex-000001 中,需要 配置 Lifecycle 自动 Rollover的时间间隔, 参考下文

4.6 配置 Lifecycle 自动 Rollover的时间间隔

  • 由于 ES 是一个准实时系统,很多操作都不能实时生效

  • Lifecycle 的 rollover 之所以不用每次手动执行 rollover 操作是因为 ES 会隔一段时间判断一次索引是否满足 rollover 的条件

  • ES检测 ILM 策略的时间默认为10min

修改 Lifecycle 配置:

PUT _cluster/settings
{"transient": {"indices.lifecycle.poll_interval": "3s"
}
}

5. ES 在 QQ 家校群作业统计功能上的实践

疫情期间线上教学需求爆发,QQ的家校群功能也迎来了一批发展红利,家校群的作业功能可以轻松在 QQ 群里实现作业布置,提交,批改等功能,深受师生们的喜爱。

5.1 使用场景简介

近期推出的作业统计功能,可以指定时间段+指定科目动态给出排名,有效提高了学生答题的积极性。在功能的实现上如果用传统的 SQL + KV 的方式实现成本比较高,要做到高性能也需要花不少精力,借助 ES 强大的统计聚合能力大大降低了开发成本,实现了需求的快速上线。

5.2 实际耗时情况

  • 插入:~25ms

  • 更新:~15ms

  • 聚合:200ms 以内

参考链接(可复制链接至浏览器打开)

  • 我在 Elasticsearch 集群内应该设置多少个分片?

    (https://www.elastic.co/cn/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster)

  • 使用索引生命周期管理实现热温冷架构

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

  • Index lifecycle management settings in Elasticsearchedit

    (https://www.elastic.co/guide/en/elasticsearch/reference/current/ilm-settings.html)


关注“腾讯云大数据”公众号,技术交流、最新活动、服务专享一站Get~

Elasticsearch索引容量管理实践相关推荐

  1. Elasticsearch 索引容量管理实践

    作者:gavinyao,腾讯 PCG 后台开发工程师 Elasticsearch 是目前大数据领域最热门的技术栈之一,腾讯云 Elasticsearch Service(ES)是基于开源搜索引擎 El ...

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

    1.什么是索引生命周期? 关于人生,有人这么说:"人,生来一个人,死去一个人,所以,人生就是一个人生老病死的简称." 在基于日志.指标.实时时间序列的大型系统中,集群的索引也具备类 ...

  3. Elasticsearch索引生命周期管理方案

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 一.前言 在 Elasticsearch 的日常中,有很多 ...

  4. elasticsearch 索引_Elasticsearch系列---索引管理

    概要 Elasticsearch让索引创建变得非常简单,只要索引一条新的数据,索引会自动创建出来,但随着数据量的增加,我们开始有了索引优化和搜索优化的需求之后,就会发现自动创建的索引在某些方面不能非常 ...

  5. 【Elasticsearch】Elasticsearch 索引生命周期管理

    文章目录 1.概述 1.1 为什么要对elasticsearch进行生命周期管理? 1.2 什么是索引周期管理 1.3 各个阶段允许的action 1.3 如何对elasticsearch进行生命周期 ...

  6. Elasticsearch 索引生命周期管理方案

    Elasticsearch索引生命周期管理方案 文章目录 Elasticsearch索引生命周期管理方案 1.生命周期 1.1 阶段介绍 2.模拟过程(基础) 2.1 创建索引生命周期策略 2.2 创 ...

  7. 阿里云Elasticsearch 智能化运维实践

    背景   Elasticsearch作为一个开箱即用的搜索引擎,其丰富的功能和极低的使用门槛吸引着越来越多的公司和用户选择它作为搜索和数据分析的工具.用户在运维Elasticsearch集群时往往会遇 ...

  8. 干货 | Elasticsearch 索引设计实战指南

    题记 随着 Elastic 的上市,ELK Stack 不仅在 BAT 的大公司得到长足的发展,而且在各个中小公司都得到非常广泛的应用,甚至连"婚庆网站"都开始使用 Elastic ...

  9. 看完这篇文章,再也不怕 Elasticsearch 索引设计

    题记 随着 Elastic 的上市,ELK Stack 不仅在 BAT 的大公司得到长足的发展,而且在各个中小公司都得到非常广泛的应用,甚至连"婚庆网站"都开始使用 Elastic ...

最新文章

  1. Atitit.文件搜索工具 attilax 总结
  2. 本人制作的股票技术分析软件正式开源(.net wpf)
  3. html select 多选取值,下拉框多选实现 jquery-multiselect 并获取选中的值
  4. 超基础的Android studio的安装教程
  5. 算法太多挑花眼?教你如何选择正确的机器学习算法
  6. 中国剩余定理求解“六位教授必须首次都停止上课”问题
  7. C++运算符与类型转换
  8. 『号外』 排名进入3000,特致感谢!
  9. jQuery 根据值或者文本选中select
  10. 现在企业为何越来越难呢?
  11. MySql实现sequence功能的代码
  12. 没有tpm不能装win11的解决方法
  13. python itchat_Python使用itchat获取微信好友
  14. node和onbot安装教程(解决傻妞机器人不回复 没弹窗登录二维码问题)
  15. 计算机d代表什么,DVI-D和DVI-I区别是什么?
  16. 《Flutter入门疑难杂症》imagepicker ImagePicker().getVideo()返回.jpg
  17. Vue.js基础(极简、自用)
  18. LOGO创意-IT行业-随记
  19. opencv自定义从一幅图片截取特定区域函数cvExtractRegion
  20. 视觉高精度测量,影响精度的5大关键因素

热门文章

  1. 山东专升本计算机网络(四)
  2. [访问学者申请]美国访问学者申请经验分享
  3. 让程序员崩溃的 60 个瞬间
  4. 传输指令ssh,sftp,scp
  5. access IIf 函数
  6. 微信小程序环形图/折线图(canvas)
  7. 使用MapReduce实现寻找共同好友的案例
  8. CMMI终于评估完了
  9. unix cp 原理_Unix的工作原理:您都不敢问的一切
  10. 用好.net SDK