EleasticSearch 线上大索引按日期分割

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接和本声明。
本文连接:https://blog.csdn.net/Norman_Hu/article/details/89917569
1. 背景
因为项目初期设计问题,采集到es的业务日志只使用了一个索引(index),随着线上日志量的增加,es很快飙升到磁盘警惕线,网上找了一圈,不少文章版本都比较老旧,最终直接啃官方文档,没有copy别人博客,若是你中途不走神,本文总共15min。version 适用于es 6.0+node

本文前提保障:算法

文档中有时间字段,方便按日期切割
index的mapping配置中,_source需为 true(默认),以保证es存入了源文档,而不只仅是docId,便于执行reindex!
curl -XGET "localhost:9200/your_index_name/_mapping"
# 若是没有显示 _source, 表明"_source": false
1
2
2. 删文档(不建议)
这第一个想到的方法,将最老旧的日志删掉,如只保留近3个月的,采用 delete_by_query 接口json

curl -X POST "localhost:9200/twitter/_delete_by_query" -H 'Content-Type: application/json' -d'
{
  "query": {
    "range" : {
        "day" : {
           "lt" : "2018-12-01"
        }
    }
  }
}
'
1
2
3
4
5
6
7
8
9
10
11
可是,es的delete,并非真正的物理删,磁盘使用率(utilization)并不会降低。删除的文档仅仅被标记,es将文档存入一个个segment file中,其file数量随着文档的写入不断增长,es所以会有合并segment file的操做,将多个小的segment合并成一个大的segment file,当segment合并的时候,标记的文档才会真正的物理删除。api

这种方案,只适合在 项目早期、文档量少、且机器负载不高 状况下进行,由于批量读写会致使cpu utilization的飙升,形成系统负载加剧,能够在晚上业务量不高的时候进行多线程

3. 磁盘扩容 (短时间有效)
那若是标记删除不能当即解决问题,那就对磁盘扩容吧!1T 到 2T,2T 到 4T,因为升级磁盘须要重启机器,因此,如何作到优雅滚动关停es相当重要!app

3.1 中止es集群服务
常见就是ps看一下es的进程,而后kill,先等一下!在此以前,需对集群进行配置,方便更加快速的服务重启curl

3.1.1 中止分片分配
因为es中的index是分布式存储,因此一个index分红了多个shard,分布在各个节点node上,每一个shard均可以单独提供服务,同时每一个shard能够配置多个副本(replicas),保证集群的高可用,提升了查询效率。同时,es在管理这些分片时,有一套自有的均衡算法,保证shard均匀分散在各个node上,同时保证每一个shard和其对应的replica不在同一node上。正是这种机制,使得当node离开和从新加入的时候,分片的分配会copy文件,会形成大量的io,由于node重启很快就回来,因此暂时关掉自动分片分配,详情参见另外一篇文章,介绍集群重启步骤。这里选择直接中止分配分布式

curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
  "persistent": {
    "cluster.routing.allocation.enable": "none"
  }
}'
1
2
3
4
5
6
这样,在node停掉的时候,不会出现分片分配从新均衡了。ide

3.1.2 挂载新盘
因为机器是云上资源,所以按照各个云上的扩容文档操做便可,不管是自有机房仍是云上机器,无非是下面几个步骤:学习

reboot重启

df -h 看一下如今的挂载点(如/dev/vdb)和 挂载路径(如/data/es/)

fdisk -l 能够进一步确认盘的信息

fdisk /dev/vdb,对新盘进行从新挂载,命令中可能涉及到的选项,不分区的话,大部分按回车默认选项:d n p 1 wq

其余操做 如e2fsck -f /dev/vdb,resize2fs /dev/vdb

mount /dev/vdb /data 从新挂载便可

3.1.3 恢复分配分配
curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
  "transient": {
    "cluster.routing.allocation.enable": "all"
  }
}
'
1
2
3
4
5
6
7
这一步,会有部分io,等到recovery结束,集群恢复正常。若是有 Unassigned 状态的shard,须要手动执行分片分配,对应的命令reroute,这个不难,正常状况下,几乎不会出现 Unassigned 的shard。
执行完上述操做,磁盘体积翻倍。在短时间内,能够保证服务正常。

4. 索引拆分(最佳实践)
不管标记删除,仍是磁盘扩容,都没有真正的解决索引过大的问题,随着文档数的增长,索引势必会变得更大。针对大索引,标记删除以及扩容后分片恢复的操做时间,也会大幅增长,可能会从几小时到一两天。上述方法不可行!

由于es对index的删除是物理删除,是当即的,既然不能直接删除原索引,得想办法把大索引拆成小索引,而后再删除老旧的。那么es有么有这种api,将大的索引按照某种条件(按天、按月)进行拆分呢?为此,我找了不少博客,最后发现,不少博客里介绍的api都很老旧,仍是官网的文档最实在,文档是英文,不过理解起来并不复杂。墙裂推荐看官方文档。为此,我调研了这些api:_rollover,alias,template,reindex,你们能够有针对的深刻学习这几个api,细节这里就不讲了,先看我怎么用的吧~

4.1. 错误尝试
_rollover 当看到这个api时,我觉得找到了最接近需求的api,这个api介绍以下

The rollover index API rolls an alias over to a new index when the existing index is considered to be too large or too old.

显然被 too large 和 too old 吸引了。。。

curl -X PUT "localhost:9200/logs-000001" -H 'Content-Type: application/json' -d'
{
  "aliases": {
    "logs_write": {}
  }
}
'
# Add > 1000 documents to logs-000001
curl -X POST "localhost:9200/logs_write/_rollover" -H 'Content-Type: application/json' -d'
{
  "conditions": {
    "max_age":   "7d", #当文档建立时间大于7天
    "max_docs":  1000, #当文档数量超过上限1000
    "max_size":  "5gb" #当索引大小超过5GB
  }
}
'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
思路:

先给 index 建一个别名 alias,再 rollover,当执行时,知足任一个条件便可建立新索引,同时别名 alias 指向新的,除此以外,_rollover还能够按日期生成新索引

问题:

拆分只在api执行时生效,后面不会自动拆分,若是按天索引,则必须天天定时执行,增长维护成本,若是定时任务失败…
当别名滚向新的索引后,旧索引不能经过 alias 再访问
并无将历史的索引按天生成,只是在此api执行后,新文档才会进新index
4.2 最佳实践
假设原索引name knight-log,当前月份 2019-02

思路:

建立别名alias:alias-knight-log
为旧的 knight-log 关联别名 alias-knight-log
建立索引模板template: template-knight-log,该模板匹配全部 knight-log.* 索引,在模板中定义settings和mappings,以及自动关联别名 alias-knight-log
此外,将项目中读写es的操做分别设置:

读 alias-knight-log,能够查询全部关联索引
写 knight-log.2019-02,在原索引后append月份便可!调用Java api进行索引时,接口规定每条文档须要指定index name,所以将原来的 name 变为 name + current_month 便可,其余语言同理!
更新业务代码,从新上线后,新文档会进入到形如 knight-log.2019-02 的索引中,原 knight-log 将不会有写请求,读请求也通过别名 alias-knight-log 代理了

通过上述步骤,旧的index只读不写,写请求所有进入 knight-log.2019-02 的索引中,保障了这一点,咱们就能够对 knight-log 按时间粒度以大化小,逐个删除了!

Sad,没有这种直接的api,不过,不起眼的reindex却承担起这个重任,一开始我以为跟这个api应该没有关系,不只不省空间,反而还翻倍,直到发现能够按条件reindex后,眼前一亮!我按时间条件reindex不就行了嘛~~

# 将 2019-01 月的文档, 所有 reindex 到 knight-log.2019-01 中
curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "knight-log",
    "type": "your_doc_type",
    "query": {
      "bool": {
        "filter": {
          "range": {
            "day": {
              "gte": "2019-01-01",
              "lt": "2019-02-01"
            }
          }
        }
      }
    }
  },
  "dest": {
    "index": "knight-log.2019-01"
  }
}
'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
tips1: 在reindex到新index以前,为了加快索引,能够对新index设置,常规的批量索引设置注意项,这里也适用,如:replicas=0,refresh_interval=-1

tips2:第一次使用reindex,没有开启slice(至关于多线程),io和cpu虽然都不高,但很慢,可适当开启,但注意slice不要超过index的shard数,看官方文档,此处很少提!

tips3:若是一个月的文档数太多,不放心一次性操做,你能够尝试先按天reindex到新月份index中,这样能够观察cup和io,而后适当调整reindex相关参数后,再把当月余下天数的文档所有reindex到新index中

tips4:当进行完一次reindex,恢复 refresh_interval 后,能够对新旧索引同时查询,看文档数是否一致!确保无异常!

tips5:手误执行reindex,能够中途取消本次task

将 knight-log 的replicas数从默认的1 变为 0,这样整个index省掉一半大小(非必须,剩余磁盘多能够忽略),而后,对 knight-log 按月份进行reindex,这样反复操做几回,可完成近几月的备份,形如 knight-log.2019-01,knight-log.2018-12 等(不要忘记2月的旧文档哦,一样须要reindex,这样2月的index才会完整),同时由于模板的特性,月份索引会自动加上 alias-knight-log 这个别名,一箭双雕!

reindex完必要的数据后(如近3月),就能够直接删掉 knight-log!

若几个月后,磁盘又满了,就能够将最久老月份的index直接物理删除,方便快捷!

5. 总结
追根究底,这种问题就不该该存在!可能一开始使用es不熟吧,起码按天/月索引是应该具有的基本sense吧,你们要避免这个坑!

其次,若是单条文档体积较大,能够考虑将数据存入HBase,es中只存docId便可,经过条件搜出对应的docId,而后用docId去HBase取数据,进一步高效利用es,这经过禁用_source字段(保存原文档的json字段)实现。不过,由于es只存倒排索引,因此没了原文档,会缺失部分便捷性,慎重考虑!

说回来,es不支持将大的索引按时间拆分红小索引,只能在多个api组合中找到最优实践,对应用来讲,须要改动索引名后重启,已是最小化改动,在整个过程当中,es保障了正常提供服务,不影响其余业务。 经历过上述操做,更加熟练的掌握了es多个相关api,了解查询原理,写入原理,分片分配策略以及查询语句优化等知识点。另: kibana下使用dev tools也很是爽,会弹提示,算是发现的彩蛋,建议多用! ———————————————— 版权声明:本文为CSDN博主「Norman_Hu」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接及本声明。 原文连接:https://blog.csdn.net/Norman_Hu/article/details/89917569

相关文章
相关标签/搜索