Elasticsearch学习系列五(零停机索引重建)

打印 上一主题 下一主题

主题 637|帖子 637|积分 1911

Elasticsearch是一个实时的分布式搜索引擎,为用户提供搜索服务,当我们决定存储某种数据时,在创建索引的时候需要数据结构完整确定下来,与此同时索引的设定和很多固定配置将不能改变。当需要改变索引结构时就需要重建索引。
下面介绍索引重建的3个方案:
方案一:外部数据导入方案

整体介绍
系统架构设计中,一般有关系型数据库用来存储数据,Elasticsearch在系统架构里起到查询加速的作用。如果是遇到索引重建的操作,待系统模块发布新版本后,可以从数据库中将数据查询出来,重新写入ES即可。
详细操作步骤

  • 微服务模块从数据库里查询数据的总数和批次信息,将每个批次的分页信息发给MQ,分页信息包含查询条件和偏移量
  • 微服务根据接收到的分页信息,从数据库获得数据,根据新索引结构的定义,将数据组装成JSON,并执行bulk命令,将数据写入es
方案特点
微服务模块实例可能会部署多个,数据是分批处理的,批次信息会一次性发给MQ,利用MQ的异步处理机制,可以充分的利用多实例的并发优势,加速数据重建的速度。
方案缺点

  • 对数据库造成读取压力,短时间内大量的读操作,会占用数据库的硬件资源。
  • 网络带宽占用多,从数据库写入ES会有大量的数据传输带宽占用
方案二:基于scroll+bulk+索引别名方案

整体介绍
利用java客户端做持续的scroll查询和bulk命令写入,数据自给自足,不依赖其他数据源。
执行步骤
假设原索引名称是item,新的索引名称为item_new,java客户端使用别名item_alias链接ES,该别名指向原索引item。

  • 先建立一个别名
  1. PUT /item/_alias/item_alias
复制代码

  • 新建索引item_new,将mapping信息等按新的格式定义好
  • 使用scroll api将数据批量查询出来,这个1m就是保存搜索的上下文环境的时间。
  1. GET /item/_search?scroll=1m
  2. {
  3.   "query": {
  4.     "match_all": {}
  5.   },
  6.   "sort": ["_doc"],
  7.   "size": 2
  8. }
复制代码

  • 采用bulk api将scroll查出来的数据,批量写入新索引
  1. POST /_bulk
  2. {"index":{"_index":"item_new","_id":"tr6YgYEB9TD2fYkcFzjY"}}
  3. {"title":"小米手机","price":"2688","images":"http://image.lagou.com/12479122.jpg","createTime":"2022-02-01 12:02:02","lifecycle":1}
复制代码

  • 反复执行步骤3和4(注意步骤3中,需要指定上一次查询的scroll_id)
  1. GET /_search/scroll
  2. {
  3.   "scroll":"1m",
  4.   "scroll_id":"步骤3查出来的值"
  5. }
复制代码

  • 切换别名item_alias到新的索引item_new上面,此时java客户端让使用别名访问,不需要修改代码,也不需要停机。
  1. POST /_aliases
  2. {
  3.   "actions": [
  4.     {
  5.       "remove": {
  6.         "index": "item",
  7.         "alias": "item_alias"
  8.       }
  9.     }
  10.     ,{
  11.       "add": {
  12.          "index": "item_new",
  13.         "alias": "item_alias"
  14.       }
  15.     }
  16.   ]
  17. }
复制代码
方案特点
在数据传输上自给自足,不依赖其他数据源。网络传输占用带宽较小。
另外在java客户端访问es集群时,使用别名是一个好习惯。
方案三:Reindex API方案

ES v6.3.1已经支持Reindex API,它对scroll、bulk做了一层封装,能够对文档重建索引不需要任何插件或外部工具。

  • 基础使用:
  1. POST _reindex
  2. {
  3.   "source": {
  4.     "index": "item"
  5.   },
  6.   "dest": {
  7.     "index": "item_new"
  8.   }
  9. }
复制代码
注意: 如果不手动创建新索引book_new的mapping信息,那么Elasticsearch将启动自动映射模板对数据进行类型映射,可能不是期望的类型,这点要注意一下

  • version_type属性
使用reindex api也是创建快照后再执行迁移的,这样目标索引的数据可能会与原索引有差异,version_type属性可以决定乐观锁并发处理的规则
  1. POST _reindex
  2. {
  3.   "source": {
  4.     "index": "item"
  5.   },
  6.   "dest": {
  7.     "index": "item_new",
  8.     "version_type": "internal"
  9.   }
  10. }
复制代码
version_type属性含义如下:

  • internal:直接拷贝文档到目标索引,对相同的type、文档ID直接进行覆盖,默认值
  • external:迁移文档到目标索引时,保留version信息,对目标索引中不存在的文档进行创建,已
    存在的文档按version进行更新,遵循乐观锁机制

  • op_type属性和conflicts属性
如果op_type设置为create,那么迁移时只在目标索引中创建ID不存在的文档,已存在的文档,会提示错误,如下请求:
  1. POST _reindex
  2. {
  3.   "source": {
  4.     "index": "item"
  5.   },
  6.   "dest": {
  7.     "index": "item_new",
  8.     "op_type": "create"
  9.   }
  10. }
复制代码
错误信息会比较多,如果加上"conflicts":"proceed"配置项,那么冲突信息将不展示,只展示冲突的文档数量,请求和响应结果将变成这样:
  1. POST _reindex
  2. {
  3.   "conflicts": "proceed",
  4.   "source": {
  5.     "index": "item"
  6.   },
  7.   "dest": {
  8.     "index": "item_new",
  9.     "op_type": "create"
  10.   }
  11. }
复制代码

  • query支持
reindex api支持数据过滤、数据排序、size设置、_source选择等,也支持脚本执行。
  1. POST _reindex
  2. {
  3.   "size": 10,
  4.   "source": {
  5.     "index": "item",
  6.     "query": {
  7.       "term": {
  8.         "title": {
  9.           "value": "手机"
  10.         }
  11.       }
  12.     }
  13.   },
  14.   "dest": {
  15.     "index": "item_new",
  16.     "op_type": "create"
  17.   }
  18. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

冬雨财经

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表