ElasticSearch不停机重建索引延伸思考及优化详解

目录
  • 前言
  • 需求
  • 查询本体
    • 查询限制
    • 聚合查询优化
    • 遇到问题
  • 不停机重建索引
    • 新建索引
    • 切换别名指向新索引
    • 迁移数据
    • 查询异步迁移任务详情
    • 调整正常索引配置
  • MySQL扩容
    • 停机扩容
    • 不停机扩容
    • 随便聊聊
  • 最后

前言

距离我第一次上手ES过去了一年半多了吧,当时我是从零开始花了大半年时间搭建了一整套Filebeat+Kafka+数据处理服务+Elasticsearch+Kibana+Skywalking日志收集系统。感觉还是很刺激的,毕竟同时去深度学习和运用多个刚上手的中间件对我来说是个极大的磨练。日志收集系统的数据处理服务切换到了Flink,这个后面总结完毕后我会出一篇单独的文章讲讲Flink和改造过程。但是始终有一个问题困扰着我,团队内部对于ES的应用尚浅,仅仅用来做日志收集,导致我对ES的认识一直不算深刻,所以我之前也没有写一篇优秀的文章来阐述我的认知。当然现在我依旧算个小白,但是因为一两个需求重新深刻认识了ES,算是一段不错的经历,因此分享给大家,有问题的话请各位大佬指正。

需求

同事提给我的,说是需要对过去半年时间做一个系统应用的用户使用情况统计,很急。具体是需要按照系统分组统计每个用户的使用情况,很好,之前完全没有单独设计过相关的统计入口,因此只能根据日志内容硬写查询语句了。因为需求比较麻烦,所以注定是个复杂聚合查询,不巧的是我对于ES的查询API有点忘了,只能现学现卖了。为啥不熟呢?我自己总结的原因一是日志场景单一,JavaAPI只需要布尔查询拼条件即可,不会很复杂,后面改成Kibana后索引模式用上就不存在什么API调用了。原因二是由于工作繁忙,没有别的技术场景,因此没有太关注ES的API部分,重点都是在性能优化和日志收集系统的完善上面。

除了上面的复杂查询让我稍微感到难度之外,在聚合查询的时候还发现了历史遗留的问题,新索引优化了映射并没有修改老索引,因此新老索引映射是有一点区别的,需要重建索引。重建索引自然要上真实场景,不停机重建索引。

查询本体

对应查询语句和执行结果如上图,简要提几点限制打开的方法和一些优化的手段。

查询限制

1.查询总数默认限制10000条

查询时带上"track_total_hits": true,打开限制,返回真实条数

2.聚合查询时使用term,默认限制10条

聚合查询参数中加上"size": 50,配置展示最多50条

聚合查询优化

聚合查询为了尽量返回少的数据量,提升查询效率,通常设置size为0,体现为查询结果中hits不返回具体文档数据。

遇到问题

1.text类型不支持聚合

报错内容:

Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [userId] in order to load field data by uninverting the inverted index. Note that this can use significant memory(文本字段未针对需要每个文档字段数据的操作(如聚合和排序)进行优化,因此默认情况下禁用这些操作。请改用关键字字段。或者,在 [userId] 上设置 fielddata=true,以便通过反转倒排索引来加载字段数据。请注意,这可能会占用大量内存)

解决方案:

text类型默认不支持聚合和排序,因此要么修改mapping增加属性fielddata=true,或者直接修改字段类型为keyword

2.分词查询时不知道写哪些词

查询文档分词结果--索引=log-zero-pro-202302-alias1,id=1xKdCoYBeajfMMIRdyre,字段=msg

GET /log-zero-pro-202302-alias1/_doc/1xKdCoYBeajfMMIRdyre/_termvectors?fields=msg

我想这是大多数新手遇到的问题,配了分词后,我就随便乱输发现匹配不了,开始懵逼,疑惑这分词怎么没有效果。但是我们把分词当作一个模糊查询去用了,两者还是有一定区别的,特别是粗分词的时候,不太熟练的情况下,还是先查一下分成啥样再去查询比较好。

不停机重建索引

为啥要重建索引呢?因为索引创建之后是不允许修改映射的,如果修改只能重建。不停机重建索引的步骤还是比较简单,就三步。

新建索引

新建索引正常建就行,因为重建索引用到了reIndex这个API,内部是由scroll+bulk实现,本质上就是先查询再批量插入。因此可以做一些写入优化,副本数可以先设置为0,刷新间隔禁用,落盘机制调整异步和延迟。

PUT /log-zero-pro-202206_re/_settings
{
  "index" : {
    "number_of_replicas" : 0,
    "refresh_interval": "-1"
  }
}

切换别名指向新索引

ES的索引设计时最好提前加上一个别名,用别名去管理索引,它就像一层代理,让我们不用在意底层索引,可以随时切换。我们建立一个新的索引后,将别名指向新的索引,这样新数据就会灌到新索引中,避免老索引在迁移中仍有数据进入,导致数据迁移不完整,需要二次迁移。

POST /_aliases
{
    "actions" : [
        { "remove" : { "index" : "log-zero-pro-202207-alias1", "alias" : "log-zero-pro-202207" } },
        { "add" : { "index" : "log-zero-pro-202207_re", "alias" : "log-zero-pro-202207" } }
    ]
}

迁移数据

选择ES自带的reIndex进行迁移,这里尽量优化一下

  • slices=auto&refresh,因为内部使用scroll查询,因此可以选择分片查询提升效率,auto意思是自动改成索引分片数
  • wait_for_completion=false,为了避免迁移时间过长超时,所以选择异步执行
  • size: 5000,也是提升单次查询数据,默认1000条,根据实际插入效率动态调整
POST _reindex?slices=auto&refresh&wait_for_completion=false
{
  "conflicts": "proceed",
  "source": {
    "index": "log-zero-pro-202207-alias1",
    "size": 5000
  },
  "dest": {
    "index": "log-zero-pro-202207_re"
  }
}
结果
{
  "task" : "iDnr1JBPRjyPVqwl2TcqqA:889565588"
}

查询异步迁移任务详情

有两个API可以调用,上面是查询所有reindex任务,下面是查询某个任务的详情,一般用下面的查看任务是否完成

GET _tasks?detailed=true&actions=*reindex
GET /_tasks/iDnr1JBPRjyPVqwl2TcqqA:889578807

调整正常索引配置

把之前的副本和刷新禁用重新打开

PUT /log-zero-pro-202206_re/_settings
{
  "index" : {
    "number_of_replicas" : 1,
    "refresh_interval": "1s"
  }
}

莫名想到了MySQL扩容,就顺道来聊聊,扩容和重建索引不是一回事哈,不能直接对比。

MySQL扩容

当前已存在n台数据库,并且通过id取模。一般是m*n扩容m倍,这样做元素迁移时比较方便,当然更建议一开始给足数据库,尽量不要扩容,增加操作风险。扩容通常分为停机和不停机两种,各有优劣。

停机扩容

最简单的方案,找个没人的深夜停机,写个程序读取老的n台数据库,按照id重新取模输入到新的m*n台数据库上,修改应用配置再重新上线。

回滚也方便,发现出问题,把配置修改为之前的,继续用老数据库,啥时候新的弄对了再迁过去。

优点就是简单明了,缺点就是费人,而且万一运行了一段时间后发现搞错了,只能回退到扩容前,会丢失部分数据。

不停机扩容

这个就相对复杂,假设现在有两台数据库A和B,选择两倍扩容,也就是增加到四台ABCD。

  • A和C,B和D分别配置双主同步,等待数据同步完成。
  • 修改应用路由配置同时写入ABCD四台数据库,取模规则变成四等分
  • 删除双主同步,同时删除四台数据库里的冗余数据(不属于当前取模规则的数据)

优点很多啊,最重要的就是不停机,而且占用资源也少,原来两台数据库也用上了。回滚也简单,只要不删除冗余数据,随时都能切回来,直接修改取模规则即可。缺点就是比较复杂,双主同步、双写,而且老数据库较大的时候,扩容相当费时费力。

随便聊聊

其实在做ES不停机重建索引的时候,我一开始是没想到这么简单的,居然几条命令就搞定了,WTF。但是事实就是这样,分布式架构面对单体架构的优势是碾压式的,这也是我最近在看分布式数据库TiDB的原因,迟早会迁移过去的。啥也不说,运维成本相对就低了,几条命令就完成了,细节不用管还更有保障,排除了单体架构时人为原因,这可太爽了。

最后

最近有个问题难住我了,flink往es写数据放在服务器上跑老是报错,我这菜的还解决不了,少年痛苦祈祷中。回到ES,本次也算是再次加深了我对ES的认识,还可以,有所收获。下一篇绝对是口语化系列了,这篇属于临时小插曲,大约2个晚上写完,还算不错。鸭梨很大,日子难过啊,啊啊啊啊啊,我一定要让这痛苦压抑的世界绽放幸福快乐之花。

以上就是ElasticSearch不停机重建索引延伸思考及优化详解的详细内容,更多关于ElasticSearch不停机重建索引的资料请关注我们其它相关文章!

(0)

相关推荐

  • ElasticSearch 深度分页示例解析

    目录 1 前言 2 from + size 分页方式 2.1 Query 阶段 2.2 Fetch 阶段 2.3 ES 示例 2.4 实现示例 2.5 小结 3 Scroll 分页方式 3.1 执行过程 1 前言 ElasticSearch 是一个实时的分布式搜索与分析引擎,常用于大量非结构化数据的存储和快速检索场景,具有很强的扩展性.纵使其有诸多优点,在搜索领域远超关系型数据库,但依然存在与关系型数据库同样的深度分页问题,本文就此问题做一个实践性分析探讨 2 from + size 分页方式

  • 详解Elasticsearch如何把一个索引变为只读

    目录 正文 设置为只读 正文 将索引设置为只读可能听起来很奇怪,但在 Elasticsearch 中执行此类操作是可能的.想象一下这样一种情况,你特别需要限制对索引的写入操作,无论是维护.业务规则还是任何其他原因.让我们学习如何将索引配置为已读以及如何撤消操作. 我们先使用如下的命令来创建一个叫做 test 的索引: PUT test/_doc/1 { "content": "I am xiaoguo from Elastic" } 设置为只读 要进行此更改,我们需

  • 与近日火爆的ChatGPT聊Elasticsearch源码

    目录 正文 ChatGpt对话内容 ChatGpt对话截图 正文 最近在研读Elasticsearch最新的源代码,今天突发奇想能不能和ChatGPT聊聊Elasticsearch,看看他对Elasticsearch源码有多少了解,试了后发现这货还不赖. 参考下面的对话内容和最后的对话截图. 不过美中不足的是,ChatGPT的知识截止2021年,所以当我问他一些最新源码时,他的分析还停留在以前的版本上,希望ChatGPT能紧跟时事潮流,早日实现实时迭代更新知识库. ChatGpt对话内容 我:聊

  • ElasticSearch整合SpringBoot搭建配置

    目录 前言 项目搭建 配置客户端 索引API初探 & Index API ping 创建索引 & create 索引是否存在 & exist 删除索引 结束语 前言 目前正在出一个Es专题系列教程, 篇幅会较多, 请持续关注我们 本节来给大家讲一下在Springboot中如何整合es~ 本文偏实战一些,为了方便演示,本节示例沿用上节索引,好了, 废话不多说直接开整吧~ 项目搭建 老规矩,先建maven项目,下面是我的pom.xml <?xml version="1.

  • ElasticSearch突然采集不到日志问题解决分析

    目录 0-前言 1-解决 2-延展 0-前言 组内同学反馈,kibana上最新的k8s日志看不到了.由于我们是采用elk(elastic search+logstash+kibana)的方式下部署日志采集系统,其中logstash以Deamonset方式部署到k8s的每一个node节点上,先去查看logstash的pod日志,发现: "reason": "Validation Failed: 1: this action would add [2] shards, but t

  • ElasticSearch之索引模板滚动索引实现详解

    目录 一. 前言 二. 索引 三. 索引模板 3.1 索引模板的创建 3.2 索引模板 Setting 3.3 索引映射 :mapping 四. 业务功能 4.1 创建滚动索引 4.2 创建和绑定策略 总结 一. 前言 文章合集 : https://zhannei.baidu.com/cse/site?q=ElasticSearch&click=1&cc=jb51.net&s=&nsid= Github : github.com/black-ant CASE 备份 : gi

  • 基于php数组中的索引数组和关联数组详解

    php中的索引数组是指以数字为键的数组.并且这个键值 是自增的 关联数组指的是一个键值对应一个值,并且这个键值是不规律的,通常都是我们自己指定的. 他们两还有不同的地方,索引数组转为json后是数组.而关联数组转为json后是对象.通常我们给app端写接口都是用索引数组转成json传过去.客户端那边对数组更为友好一点. 需要注意点: $arr = [0=>1,2=>3a]; 上述数组$arr转为json会是对象形式的. $arr = ['a','b']; 这里的$arr转为json后是数组的形

  • MySQL索引优化之适合构建索引的几种情况详解

    目录 结论 建立索引的场景 小结 结论 在where后面的过滤字段上建立索引(select/update/delete后面的where都是适用的),使用索引加快过滤效率,不用进行全表扫描 在具有唯一要求的字段上添加唯一索引,加快查询效率,查到即可直接返回 group by或者order by后面的字段添加索引,由于索引是排好序的,所以建立索引就等同于在查询之前已经是排好序了(这里需要注意建立的联合索引建立中字段的顺序,可以结合具体案例场景7进行学习) 在DISTINCT(去重字段)后面的字段添加

  • SqlServer索引的原理与应用详解

    索引的概念 索引的用途:我们对数据查询及处理速度已成为衡量应用系统成败的标准,而采用索引来加快数据处理速度通常是最普遍采用的优化方法. 索引是什么:数据库中的索引类似于一本书的目录,在一本书中使用目录可以快速找到你想要的信息,而不需要读完全书.在数据库中,数据库程序使用索引可以重啊到表中的数据,而不必扫描整个表.书中的目录是一个字词以及各字词所在的页码列表,数据库中的索引是表中的值以及各值存储位置的列表. 索引的利弊:查询执行的大部分开销是I/O,使用索引提高性能的一个主要目标是避免全表扫描,因

  • postgresql 索引之 hash的使用详解

    os: ubuntu 16.04 postgresql: 9.6.8 ip 规划 192.168.56.102 node2 postgresql help create index postgres=# \h create index Command: CREATE INDEX Description: define a new index Syntax: CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON

  • Mysql索引选择以及优化详解

    索引模型 哈希表 适用于只有等值查询的场景,Memory引擎默认索引 InnoDB支持自适应哈希索引,不可干预,由引擎自行决定是否创建 有序数组:在等值查询和范围查询场景中的性能都非常优秀,但插入和删除数据需要进行数据移动,成本太高.因此,只适用于静态存储引擎 二叉平衡树:每个节点的左儿子小于父节点,父节点又小于右儿子,时间复杂度是 O(log(N)) 多叉平衡树:索引不止存在内存中,还要写到磁盘上.为了让一个查询尽量少地读磁盘,就必须让查询过程访问尽量少的数据块.因此,要使用"N 叉"

  • MySQL中的全表扫描和索引树扫描 的实例详解

    目录 引言 实例 引言 在学习mysql时,我们经常会使用explain来查看sql查询的索引等优化手段的使用情况.在使用explain时,我们可以观察到,explain的输出有一个很关键的列,它就是type属性,type表示的是扫描方式,代表 MySQL 使用了哪种索引类型,不同的索引类型的查询效率是不一样的. 在type这一列,有如下一些可能的选项: system:系统表,少量数据,往往不需要进行磁盘IOconst:常量连接eq_ref:主键索引(primary key)或者非空唯一索引(u

  • MySQL索引最左匹配原则实例详解

    目录 简介 准备 理论详解 聚集索引和非聚集索引 回表查询 索引覆盖 最左匹配原则 详细规则 补充:为什么要使用联合索引 总结 简介 这篇文章的初衷是很多文章都告诉你最左匹配原则,却没有告诉你,实际场景下它到底是如何工作的,本文就是为了阐述清这个问题. 准备 为了方面后续的说明,我们首先建立一个如下的表(MySQL5.7),表中共有5个字段(a.b.c.d.e),其中a为主键,有一个由b,c,d组成的联合索引,存储引擎为InnoDB,插入三条测试数据.强烈建议自己在MySQL中尝试本文的所有语句

  • Mysql索引的类型和优缺点详解

    索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针. 注: [1]索引不是万能的!索引可以加快数据检索操作,但会使数据修改操作变慢.每修改数据记录,索引就必须刷新一次.为了在某种程序上弥补这一缺陷,许 多SQL命令都有一个DELAY_KEY_WRITE项.这个选项的作用是暂时制止MySQL在该命令每插入一条新记录和每修改一条现有之后立刻对索引进 行刷新,对索引的刷新将等到全部记录插入/修改完毕之后再进行.在需要把许多新记录插入某个数据

  • oracle 索引组织表的深入详解

    索引组织表(IOT)不仅可以存储数据,还可以存储为表建立的索引.索引组织表的数据是根据主键排序后的顺序进行排列的,这样就提高了访问的速度.但是这是由牺牲插入和更新性能为代价的(每次写入和更新后都要重新进行重新排序).索引组织表的创建格式如下: 复制代码 代码如下: create table indexTable(   ID   varchar2 (10),   NAME varchar2 (20),   constraint pk_id primary key (ID)   )   organi

  • MySQL组合索引与最左匹配原则详解

    前言 之前在网上看到过很多关于mysql联合索引最左前缀匹配的文章,自以为就了解了其原理,最近面试时和面试官交流,发现遗漏了些东西,这里自己整理一下这方面的内容. 什么时候创建组合索引? 当我们的where查询存在多个条件查询的时候,我们需要对查询的列创建组合索引 为什么不对没一列创建索引 减少开销 覆盖索引 效率高 减少开销:假如对col1.col2.col3创建组合索引,相当于创建了(col1).(col1,col2).(col1,col2,col3)3个索引 覆盖索引:假如查询SELECT

随机推荐