Elasticsearch如何修改Mapping结构并实现业务零停机

Elasticsearch 版本:6.4.0

一、疑问

在项目中后期,如果想调整索引的 Mapping 结构,比如将 ik_smart 修改为 ik_max_word 或者 增加分片数量 等,但 Elasticsearch 不允许这样修改呀,怎么办?

常规 解决方法:

  • 根据最新的 Mapping 结构再创建一个索引
  • 将旧索引的数据全量导入到新索引中
  • 告知用户,业务要暂停使用一段时间
  • 修改程序,将索引名替换成新的索引名称,打包,重新上线
  • 告知用户,服务可以继续使用了,并说一声抱歉

我认为最大的弊端就是:需要修改替换程序,甚至有时候还得告知用户暂停使用业务

有没有更好的方式去解决上面的需求呢?有!幸好,Elasticsearch 为我们提供了另外一种解决方法,可以不需要告知用户和修改程序代码。那就是通过索引别名来重建索引

二、索引别名

索引别名可以关联一个或多个索引,并且可以在任何需要索引名称的 API 中使用。 通俗解释,别名类似于 windows 的快捷方式,linux 的软链接,mysql 的视图。别名为我们提供了极大的灵活性。它们允许我们执行以下操作:

  • 在正在运行的集群上,允许一个索引与另外一个索引之间透明切换。
  • 对多个索引进行分组组合。比如,有根据月份来创建的索引,别名可与近三个月的索引进行关联。这样的话,我们就可以通过 别名查询近三个月索引 的全部数据。如果别名用得好,可以更好地控制检索数据量的大小,来提高查询效率,但这也需要经验的积累。

本文开头遇到的问题,就可以通过索引别名来实现,现在我们学习一下具体操作。

三、具体操作

如何在零停机(该索引所用到的程序不停止运行)的前提下,修改索引的 Mapping 字段类型呢?可大体分为三步:

1、步骤一:复制数据

使用 reindex 操作来将旧索引(dynamic_data_v2)的数据完全复制到新索引(dynamic_data_v5)上:

POST _reindex
{
    "source": {
        "index": "dynamic_data_v2"
    },
    "dest": {
        "index": "dynamic_data_v5"
    }
}

执行结果:

2、步骤二:修改别名关联

POST /_aliases
{
    "actions": [
        { "remove": { "index": "dynamic_data_v2", "alias": "dynamic_data" }},
        { "add":    { "index": "dynamic_data_v5", "alias": "dynamic_data" }}
    ]
}

3、步骤三:删除旧索引(可选)

DELETE dynamic_data_v2

4、小结

至此,我们达到了伪更新(对于用户来说透明化,无需停止服务)的效果。不过这里存在一个问题,如果数据量超大的话,复制数据所消费的时间比较多,所以构建索引前还是要尽量考虑周全 mapping 结构。

关于索引别名更多操作,可参考:

https://www.elastic.co/guide/en/elasticsearch/reference/6.4/indices-aliases.html

四、可修改 mapping 的个别情况

Elasticsearch 不允许修改/删除 Mapping 已存在字段是因为:其底层使用的是 lucene 库,索引和搜索要涉及分词方式等操作,更改 Mapping 将意味着使已建立索引的文档失效,所以不允许修改 已存在字段类型等设置。

但也有个别情况:Elasticsearch 允许我们 将字段添加到索引现有的 Mapping 结构中 或 更改现有字段的仅搜索设置。

1、可以新增字段

POST dynamic_data_v2/_mapping/_doc
{
  "properties": {
     "amount":{
        "type":"text"
     }
  }
}

2、可以更改字段类型为 multi_field

PUT dynamic_data_v2/_mapping/_doc
{
  "properties": {
     "amount":{
        "type":"text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 10
          }
        }
     }
  }
}
# 为 amount 增加 multi_field
# "fields": {
#    "keyword": {
#       "type": "keyword",
#       "ignore_above": 10
#    }
# }

3、可以将新 properties 添加到 “对象” 数据类型字段。

在 Mapping 的 field 里面设置 properties ,可以使字段存储 Object 的数据类型。以下的 name 可以理解为 “对象”数据类型字段:

# 新增 name 字段,附带first的properties属性
PUT dynamic_data_v2/_mapping/_doc
{
  "properties": {
     "name":{
        "properties": {
            "first": {
              "type": "text"
            }
        }
     }
  }
}
# 可以支持继续新增一个名为last的properties属性
PUT dynamic_data_v2/_mapping/_doc
{
  "properties": {
     "name":{
        "properties": {
            "last": {
              "type": "text"
            }
        }
     }
  }
}

如下图所示:

存储数据:

# name 的对象里面有两个字段,分别为:first 和 last,代表名和姓,比如“范闲”。
PUT dynamic_data_v2/_doc/1
{
  "name": {
    "first": "闲",
    "last": "范"
  }
}

查询数据:

GET dynamic_data_v2/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase": {
            "name.last": "范"
          }
        },
        {
          "match_phrase": {
            "name.first": "闲"
          }
        }
      ]
    }
  }
}

返回结果:

上述三种方式,详情可参考:

https://www.elastic.co/guide/en/elasticsearch/reference/6.4/indices-put-mapping.html#updating-field-mappings

五、总结

别名是个好东西,而索引别名只是别名的其中一个类型。一般在项目中后期,索引中有大量数据的时候,才能体会到索引别名的妙用。正如本文提及:

  • 用户无感知地维护数据修改更新。
  • 索引组合查询,如果使用得当,可以实现精准快速查询,提高效率。

建议: 相同索引别名的物理索引有 一致的 Mapping 和 数据结构 ,以提升检索效率。


点关注,不迷路

好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是人才

白嫖不好,创作不易。各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

如果本篇博客有任何错误,请批评指教,不胜感激 !

原文地址:https://www.cnblogs.com/createboke/p/12234184.html

时间: 2024-07-31 22:12:09

Elasticsearch如何修改Mapping结构并实现业务零停机的相关文章

Elasticsearch系列---定制mapping

概要 本篇接着前一篇内容,继续介绍mapping信息,重点倾向于自定义mapping.自定义对象以及数组集合类的底层结构. 自定义mapping 上一篇文章介绍的都是Elasticsearch的自动mapping,我们在创建索引时,可以先指定好mapping的信息,还是以music索引为例: PUT /music { "mappings": { "children": { "properties": { "content":

mariadb 实用功能3   修改表结构显示进度

在工作中需要修改一个表结构不知道进度,苦苦的等待也是很煎熬的事情. mariadb 贴心的小功能,让人眼前一亮,产生了临时表,还有进度可以看, good,good. 直接操作,看结果 MariaDB [test]> select version(); +-----------------+ | version()       | +-----------------+ | 10.1.20-MariaDB | +-----------------+ 1 row in set (0.00 sec)

MySQL在线修改表结构pt-osc

MySQL在线修改表结构pt-osc 重所周知 MySQL的DDL操作操作是相比比较昂贵的.因为MySQL在修改表期间会阻塞任何读写操作. 基本上业务处于瘫痪.如果数据量较大可能需要好几个小时才能完成,无法容忍这个操作.Percona开发了一系列的工具 Percona Toolkit包,其中有一个工具pt-online-schema-change可以在线执行DDL操作,不会阻塞读写操作从而影响业务程序.当然也有其他的工具 例如 MySQL5.6的online ddl 还有gh-ost 本文主要讲

SQL_修改表结构

***********************************************声明***********************************************************************  原创作品,出自 "深蓝的blog" 博客,欢迎转载,转载时请务必注明出处,否则追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlong/article/details/39758393 *******

Mysql修改表结构工具OnlineSchemaChange使用心得

OnlineSchemaChange是Facebook开源的在线修改表结构的工具,具体原理这里不多说了,有兴趣的同学可以看下官方文档:https://github.com/facebookincubator/OnlineSchemaChange/wiki 这里主要介绍下在迁移的时候使用的情况,首先官网的OSC工具不支持主从同步,当时测试是在单库上进行测试,而生产环境是有主从的,结果在主库上直接运行了OSC,可以看到如下的输出: 可以看到主库运行基本正常,表结构也正常修改了,并没有锁表影响到线上正

第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理

第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲-elasticsearch(搜索引擎)的mapping映射管理 1.映射(mapping)介绍 映射:创建索引的时候,可以预先定义字段的类型以及相关属性elasticsearch会根据json源数据的基础类型猜测你想要的字段映射,将输入的数据转换成可搜索的索引项,mapping就是我们自己定义的字段数据类型,同时告诉elasticsearch如何索引数据以及是否可以被搜索 作用:会让索引建立的更加细致和完善 类型:静态映射和动态

mysql笔记--数据库基本增删改查 修改表结构

数据库基本增删改查 1. 增-添加/插入数据,insert into 插入哪张表,那些列,什么值, 语句:insert into 表名(列1,列2,列3)values (值1,值2,值3): 可以不按原列的顺序插入,也可以插入部分列,但是值与列要一一对应,不能混乱!!! 一次插入多行数据 : Insert into 表名(列1,列2)values (值1,值2),(值1,值2): 2. 改-更新数据update 更新哪张表,哪些列,哪些值 语句:update 表名 set 列1=值1,列2=值2

用 pt-online-schema-change在线修改表结构的时候报超时

用工具pt-online-scheme-change执行添加字段是报错,提示超时,在凌晨反复执行几次后都是在创建触发器的时候超时退出了,表并不是很大大概1000w数据 执行语句:pt-online-schema-change --user=root --password='xxxxxx' --host=127.0.0.1 --port=3306 --charset=utf8 --alter="add flow_n int(11)  default 1  COMMENT '数据流个数' "

数据库复制:修改表结构、新增表、新增存储过程 会被复制到订阅服务器

[SQL Server高可用性]数据库复制:修改表结构.新增表.新增存储过程 会被复制到订阅服务器? 在SQL Server上配置好数据库复制后: 1.如果给表加了字段,会不会复制到订阅服务器呢?如果是删除1个字段呢? 2.如果新创建了1个表,会不会被同步过去呢? 3.如果新建了一个存储过程,会不会同步过去呢? 本文将会通过实验,回答上述问题. 1.首先,需要配置数据库复制. 这里为了简单起见,用了机器上的2个SQL Server 2008R2的实例. 两个实例分别是:MSSQLSERVER.S