# 配置

# index template

:索引模板。用于在创建索引时进行初始化配置。

  • 创建索引时,会根据索引模式匹配索引模板。如果存在多个匹配的索引模板,则采用优先级最高的那个。

    • 创建索引时,如果加上了配置信息,则会覆盖索引模板中的对应配置。
    • 创建、修改索引模板时,只会影响之后新创建的索引,不会影响已创建的索引。
  • 相关 API :

    GET     /_template                            # 查询所有的索引模板
    GET     /_template/<template>                 # 查询指定的索引模板
    PUT     /_template/<template>  <request_body> # 创建索引模板
    DELETE  /_template/<template>                 # 删除索引模板
    
  • 例:创建一个索引模板

    PUT /_template/my_template_1
    {
      "index_patterns": ["mysql-log-*", "nginx-log-*"], # 索引模式,用于匹配一些索引
      "aliases": {
        "test-alias-1": {}
      },
      "settings": {...},
      "mappings": {...},
      # "version" : 1,                  # 声明该索引模板的版本
      # "_meta": {                      # 配置该索引模板的元数据,可以加入任意名称的参数,并不会被 ES 使用
      #   "description": "This is a log template."
      # }
    }
    
    • 至少要声明 index_patterns ,其它配置则可以省略。
  • ES v7.8 版本引入了可组合模板,API 为 _index_template 。

    • 可设置 "priority": 100 参数,表示该模板的优先级。
      • 默认为 0 ,即优先级最低。
      • 如果一个索引匹配多个索引模板,则采用优先级最高的那个。

# index pattern

:索引模式。一个用于匹配任意个索引名的字符串。

  • 可以是以下格式:
    my-index-1                      # 一个索引名
    my-index-1,my-index-2           # 多个索引名,用逗号分隔
    my-index-*                      # 可以使用通配符 * 匹配多个索引名
    my-index-*,-my-index-2          # 可以在索引名之前加上 - ,从而排除它
    

# alias

  • 每个索引可以创建一个或多个别名(alias)。
    • ES 的大多数 API 都支持输入索引的别名,会自动解析到原名。
    • 别名与索引名共享一个命名空间,不允许重名。
  • 相关 API :
    GET   /_alias                     # 查询所有索引的所有别名
    GET   /_alias/<alias>             # 加上一个 alias 名称进行筛选,支持使用通配符 *
    GET   /<index>/_alias             # 查询指定索引的所有别名
    GET   /<index>/_alias/<alias>
    
    HEAD  /_alias/<alias>             # 检查索引是否存在
    HEAD  /<index>/_alias/<alias>
    
    PUT   /<index>/_alias/<alias>     # 给索引创建别名
    
    DELETE  /<index>/_alias/<alias>   # 删除索引的别名
    

# mappings

:映射,用于定义某个 index 中存储的文档的数据结构、字段类型。

  • 定义方式分为两种:
    • explicit mapping
      • :显式映射。是在 properties 区块,根据字段名定义一些字段。
      • index 在创建之后,不能修改显示映射中已有的字段,只能增加字段。也可以创建一个拥有新 mappings 的新 index ,然后将旧 index 的文档通过 reindex 拷贝过去。
    • dynamic mapping
      • :动态映射。是在 dynamic_templates 区块,根据至少一个匹配条件,为还没有显式映射的字段添加显式映射。
  • 例:
    "mappings": {
      "_source": {
        "enabled": true                     # 是否保存 _source 字段
      },
      "dynamic_templates" : [               # 动态映射
        {
          "integer_fields": {
            # "match" : "*",                # 匹配字段名
            # "path_match" : "test",        # 匹配字段的 JSON 路径
            "match_mapping_type": "long",   # 匹配字段值的 JSON 数据类型
            "mapping": {                    # 为匹配的字段生成显式映射
              "type": "integer"             # 该效果为:如果新增的文档中,任意字段满足匹配条件,则存储为 integer 数据类型
            }
          }
        },
        {
          "string_fields" : {
            "match_mapping_type" : "string",
            "mapping" : {
              "type" : "text"
            }
          }
        }
      ],
      "properties": {             # 显式映射
        "@timestamp" : {
          "type" : "date"
        },
        "level" : {
          "type" : "text"
        },
        "message": {
          "type": "text"
          # "index": true,        # 是否允许搜索该字段,默认为 true
          # "fielddata": false,   # 是否允许 aggregations、sorting、scripting 操作
          # "norms": true,        # 是否启用 norms
        }
      }
    }
    
    • text 类型的字段默认禁用了 fielddata ,因为会占用大量内存。与其启用 fielddata ,不如给 text 类型的字段增加一个 keyword 类型的子字段:
      "message" : {
        "type" : "text",
        "fields" : {              # 定义子字段
          "keyword" : {           # 一个名为 keyword 的子字段
            "type" : "keyword",
            "ignore_above" : 256  # 限制字段取值的长度,默认为无限大。如果超过,则保存该字段时不会建立索引
          }
        }
      }
      
    • norms :给每个字段额外使用一个字节,存储多种有利于计算 score 的调节因子(normalization factors)。
      • text 字段默认启用 norms ,keyword 字段默认关闭 norms 。

# 数据类型

文档中,字段名为字符串类型(区分大小写),而字段值的常见类型如下:

  • 字符串 :分为两种:
    • text
      • 适合存储非结构化数据,比如一篇文章。
      • 适合全文搜索。
    • keyword
      • 适合存储结构化数据,比如文章标题、编号。
      • 适合精确搜索、排序、聚合查询。
  • 数字 :分为 integer、byte、float 等。
  • 布尔值 :boolean
  • 日期 :date
  • 数组 :array ,其中的所有元素必须采用相同的数据类型。
  • 对象 :即 JSON Object
  • nested
    • :用于嵌套一组文档。这会在当前文档之外,创建独立的 Lucene 文档。
  • join
    • :用于声明父子文档。
    • 父文档与子文档必须位于同一索引、同一 shard 。
    • 例:
      PUT test_index
      {
        "mappings": {
          "properties": {
            "test_join": {
              "type": "join",
              "relations": {
                "question": "answer"  # 定义一个 join 字段,声明 question 对 answer 的父子关系
              }
            }
          }
        }
      }
      
      PUT test_index/_doc/1
      {
        "text": "This is a question",
        "test_join": {
          "name": "question"          # 新增一个文档,join 名称为 question ,因此为父文档
        }
      }
      
      PUT test_index/_doc/2?routing=1 # 设置 routing 参数,将 HTTP 请求路由到 _id=1 的文档所在 shard
      {
        "text": "This is an answer",
        "test_join": {
          "name": "answer",           # 新增一个文档,join 名称为 answer ,因此为子文档
          "parent": "1"               # 父文档是 _id=1 的文档
        }
      }
      

# 文本分析

  • 文本分析(Text analysis):ES 存储 text 类型的字段时,会先经过 analyzer 处理,再建立索引。从而方便全文搜索。

    • 查询时,也先将查询字符串经过 analyzer 处理,再进行查询。
    • text 字段存储之后的字符内容、顺序可能变化,因此使用 term、regexp 查询时可能不匹配,应该用 match 查询。
  • 一个分析器(analyzer)包含多个组件:

    • character filter :字符过滤器,用于添加、删除、转换某些字符。
    • tokenizer :分词器,用于将字符串拆分成一个个单词,称为 token 。
      • 比如英语 "Hello World" 会拆分成 2 个单词,汉语 "你好啊" 会拆分成 3 个单词。
    • token filter :用于添加、删除、转换某些 token 。
      • 例如 the、on、to 等单词通常不影响查询,可以删除。
  • ES 内置了多种 analyzer :

    • standard :默认采用。根据大部分标点符号进行分词。
      • 还启用了 Lower Case Token Filter ,将 token 全部小写。
    • simple :根据非字母的的字符进行分词,还启用了 Lower Case Token Filter 。
    • whitespace :根据空白字符进行分词。
    • stop :与 simple 相似,但启用了 Stop token filter ,会删除 a、an、and、are、it、no、the 等冠词、介词、连词。
  • index 的 analyzer 配置示例:

    {
      "settings": {
        "analysis": {
          "analyzer": {
            "default": {            // 设置存储时的默认 analyzer
              "type": "standard"
            },
            "default_search": {     // 设置查询时的默认 analyzer
              "type": "standard"
            }
          }
        }
      },
      "mappings": {
        "properties": {
          "message": {
            "type":     "text",
            "analyzer": "standard"  // 设置指定字段的 analyzer
          }
        }
      }
    }
    
  • 可用 API /_analyze 测试分析一个字符串:

    POST /_analyze
    {
      "analyzer": "standard",
      "text": "Hello World! -_1"
    }
    

    结果如下:

    {
      "tokens": [
        {
          "token": "hello",
          "start_offset": 0,
          "end_offset": 5,
          "type": "<ALPHANUM>",
          "position": 0
        },
        {
          "token": "world",
          "start_offset": 6,
          "end_offset": 11,
          "type": "<ALPHANUM>",
          "position": 1
        },
        {
          "token": "_1",
          "start_offset": 14,
          "end_offset": 16,
          "type": "<NUM>",
          "position": 2
        }
      ]
    }
    

# settings

:用于控制索引的存储等操作。

  • settings 中的配置参数按修改类型分为两种:
    • dynamic :支持在运行的索引上配置。
    • static :只能在创建索引时配置,有的也支持在 closed 索引上配置。
      • index.number_of_replicas 属于动态配置,index.number_of_shards 属于静态配置。因此索引在创建之后,不能修改主分片数量。
  • 例:
    "settings": {
      "index": {
        # "codec": "best_compression",  # 索引段的压缩率,默认为 LZ4 。更高的压缩率会减少占用的磁盘空间,但是增加读写文档的耗时
        "number_of_shards": 3,          # 主分片的数量,默认为 1 。该参数属于 static settings 。
        "number_of_replicas": 2,        # 每个主分片的副本数量,默认为 1
        "refresh_interval" : "5s",      # 每隔一定时间自动刷新一次索引。默认为 1 s ,接近实时搜索。设置成 -1 则不自动刷新
        "max_result_window": 10000,     # 单个请求返回文档的最大数量
        "mapping": {
          "total_fields.limit": 1000,       # 限制索引包含的字段数
          "depth.limit": 50,                # 限制字段的深度
          "field_name_length.limit": 1000,  # 限制字段名的长度,默认不限制
        }
        "blocks": {                         # 用于禁止对索引的一些操作
          "read": true,                     # 禁止读文档
          "write": true,                    # 禁止写文档
          "metadata": true,                 # 禁止读写元数据
          "read_only": true,                # 禁止写文档、元数据,也不能删除索引
          "read_only_allow_delete": true,   # 在 read_only 的基础上,允许删除索引(但依然不允许删除文档,因为这样并不会释放磁盘空间)
        }
      }
    }
    

# component template

:组件模板。可以被索引模板继承,从而实现更抽象化的模板。

  • 例:创建一个组件模板
    PUT /_component_template/my_component_template
    {
      "template": {
        "mappings": {
          "properties": {
            "@timestamp": {
              "type": "date"
            }
          }
        }
      }
    }
    

# shard

  • ES 的分片(shard)根据用途分为两种:
    • 主分片(primary shard)
      • :用于存储某个索引的数据。
      • 支持读、写请求。
      • 每个索引可以划分 1 个或多个主分片。
    • 副分片(replica shard)
      • :用作某个主分片的副本。
      • 只支持读请求,不支持写请求。
      • 每个主分片可以有 0 个或多个副分片。

# 分配

  • ES 集群中,master 节点会决定将每个 shard 分配到哪个节点进行存储。

    • 副分片必须分配到主分片以外的节点,否则不能实现灾备。
      • 如果没有其它可用节点,副分片就会一直处于未分配状态,导致该索引的状态为 yellow 。
  • 默认启用了自动分配。配置如下:

    PUT  /_cluster/settings
    {
      "transient": {
        "cluster.routing.allocation.enable": "all"
      }
    }
    
    • enable 可以取值为:
      • all :自动分配所有分片。
      • primaries :只分配主分片。
      • new_primaries :只分配新索引的主分片。
      • none :禁用自动分配。
    • 改变索引、分片、节点数量时,都可能触发 shard 的自动分配。
  • 默认启用了基于磁盘的分配规则。配置如下:

    "cluster.routing.allocation.disk.threshold_enabled": true       # 是否启用基于磁盘阈值的分配规则
    "cluster.routing.allocation.disk.watermark.low": "85%"          # 低阈值。超出时,不会将新的副分片分配到该节点
    "cluster.routing.allocation.disk.watermark.high": "90%"         # 高阈值。超出时,会尝试将该节点上的分片迁移到其它节点
    "cluster.routing.allocation.disk.watermark.flood_stage": "95%"  # 洪水位(危险阈值)。超出时,会找出该节点上存储的所有分片,将它们所属的 index 开启 read_only_allow_delete
    "cluster.info.update.interval": "30s"                           # 每隔多久检查一次各节点的磁盘使用率
    
    • 这里可以设置磁盘使用率的一组阈值。超出阈值时会自动开启限制,低于阈值时会自动解除限制。
    • 阈值可以设置为磁盘的剩余大小,比如 "100gb" 。
  • 可以添加基于过滤器的分配规则。配置如下:

    "cluster.routing.allocation.exclude._name": "node1,node2"       # 禁止分配分片到指定节点上,已有的分片也会被迁移走。可以指定 _ip、_name 等
    
  • 默认会自动均衡各个节点上存储的分片数量。配置如下:

    "cluster.routing.rebalance.enable": "all"                           # 对哪些类型的分片进行均衡。all 表示主分片+副分片
    "cluster.routing.allocation.allow_rebalance": "indices_all_active"  # 什么时候开始均衡。默认为主发片+副分片都已经被分配时
    
    • rebelance 均衡会遵守其它分配规则,因此不一定完全均衡。
    • 建议将一个索引的不同主分片分配到不同节点,从而分散 IO ,也有利于并发查询。
  • 可以手动迁移 shard 。示例:

    POST /_cluster/reroute
    {
      "commands": [
        {
          "move": {
            "index": "test1",
            "shard": 0,
            "from_node": "node1",
            "to_node": "node2"
          }
        }
      ]
    }
    
    • 上例是将 test1 索引的 0 号主分片,从 node1 迁移到 node2 。
    • 目标节点上不能存在该分片的副分片,否则不允许迁移。
    • 迁移时,建议先禁用自动分配、自动均衡:
      "cluster.routing.allocation.enable": "none"
      "cluster.routing.rebalance.enable": "none"
      

# split

  • API 格式: POST /<index>/_split/<target-index>
  • 用途:将一个索引分割为拥有更多主分片的新索引
  • 例:
    POST /my-index-1/_split/my-index-2
    {
      "settings": {
        "index.number_of_shards": 2
      }
    }
    
  • 分割索引的前提条件:
    • 源索引的 health 为 green 。
    • 源索引改为只读模式。可执行以下请求:
      PUT /my-index-1/_settings
      {
        "settings": {
          "index.blocks.write": true    # 禁止写操作,但允许删除
        }
      }
      
    • 目标索引不存在。
    • 目标索引的主分片数,是源索引的主分片数,的整数倍,比如 1 倍、2 倍。使得源索引的每个主分片,都可以平均拆分成多个目标索引的主分片。
  • 分割索引的工作流程:
    1. 创建目标索引,继承源索引的配置,但主分片数更多。
    2. 将源索引的数据通过硬链接或拷贝,迁移到目标索引。
    3. 允许目标索引被客户端访问。

# shrink

  • API 格式: POST /<index>/_shrink/<target-index>
  • 用途:将一个索引收缩为拥有更少主分片的新索引。
  • 例:
    POST /my-index-1/_shrink/my-index-2
    {
      "settings": {
        "index.number_of_shards": 1
      }
    }
    
  • 收缩索引的前提条件:
    • 源索引的 health 为 green 。
    • 源索引为只读,并且所有主分片位于同一个节点上。可使用以下配置:
      PUT /my-index-1/_settings
      {
        "settings": {
          "index.number_of_replicas": 0,                        # 将主分片的副分片数量改为 0 ,方便迁移
          "index.routing.allocation.require._name": "node-1",   # 将主分片全部移到一个节点上
          "index.blocks.write": true
        }
      }
      
    • 目标索引不存在。
    • 源索引的主分片数,是目标索引的主分片数,的整数倍。

# segment

# API

  • 相关 API :

    POST  /<index>/_refresh       # 触发一次索引的 Refresh
    POST  /<index>/_flush         # 触发一次索引的 Flush
    
    POST  /_forcemerge                                    # 执行一次 segment 的强制合并
    POST  /<index>/_forcemerge?                           # 将指定的索引强制合并
                              only_expunge_deletes=true   # 只合并文档删除率超过 expunge_deletes_allowed 的 segment
                              max_num_segments=1          # 将每个 shard 中的 segment 合并到只剩几个,不管文档删除率
    GET   /_tasks?detailed=true&actions=*forcemerge       # 查看正在执行的 forcemerge 任务
    
    • 删除一个文档之后,如果没有 Refresh ,则依然可以查询到该文档,并且再次请求删除该文档时会报错:version conflict, current version [2] is different than the one provided [1]
    • 发出 forcemerge 请求时:
      • 会阻塞客户端,直到合并完成才返回响应。
      • 如果客户端断开连接,也会继续执行合并任务。
      • 如果服务器正在对该 index 执行 delete 任务或 forcemerge 任务,则会忽略客户端发出的合并请求。
      • 如果合并请求没有加上 URL 参数,则也是按照自动合并的算法,只处理适合合并的 segment 。
  • 请求 GET /_cat/segments/test_segments?v 的结果示例:

    index         shard prirep ip         segment   generation  docs.count  docs.deleted    size size.memory committed searchable version compound
    test_segments 0     p      10.0.0.1   _x                33        6665             0  15.4mb       74939 true      true       7.4.0   true
    test_segments 0     p      10.0.0.1   _12               38       13000             0    28mb       97976 true      true       7.4.0   true
    test_segments 0     p      10.0.0.1   _14               40       39416             0  78.6mb      178092 true      true       7.4.0   true
    

    表中每行描述一个 segment 的信息,各列的含义如下:

    index           # 该 segment 所属的索引
    shard           # 所属的分片
    prirep          # 分片类型,为 primary 或 replica
    ip              # 分片所在主机的 IP
    segment         # segment 在当前 shard 中的 36 进制编号,从 _0 开始递增。新增的文档会存储在编号最大的 segment 中,但合并之后,文档所在的 segment 可能变化
    generation      # generation 的十进制编号,从 0 开始递增
    
    docs.count      # 可见的文档数。不包括 deleted 文档、尚未 refresh 的文档、副分片的文档
    docs.deleted    # deleted 文档数
    size            # 占用的磁盘空间,单位 bytes
    size.memory     # 占用的内存空间,单位 bytes
    committed       # 该 segment 是否已经提交到磁盘。取值为 false 则说明正在使用 translog
    searchable      # 该 segment 是否允许搜索
    
    version         # 存储该 segment 的 Lucene 版本
    compound        # 该 segment 的所有文件是否已经合并为一个文件。这样能减少打开的文件描述符,但是会占用更多内存,适合体积小于 100M 的 segment
    
    • docs.count + docs.deleted 等于实际存储的文档总数。
    • docs.deleted / (docs.count + docs.deleted) 等于文档删除率。

# 配置

  • 索引中关于 Lucene segment 配置:
    PUT /my-index-1
    {
      "settings": {
        "index": {
          "translog": {
            "durability": "request",            # 当客户端发出写请求时,要等到将 translog 通过 fsync 写入磁盘之后,才返回响应
            "sync_interval": "5s",              # 每隔多久执行一次 fsync (不考虑是否有客户端请求)
            "flush_threshold_size": "512mb",    # 当 translog 超过该大小时,就执行一次 Flush
          }
          "merge": {
            "policy": {
              "expunge_deletes_allowed": 10,    # 调用 expungeDeletes 时,只合并文档删除率超过该值的 segment ,默认为 10%
              "floor_segment": "2mb",           # 自动合并时,总是合并小于该体积的 segment ,不管文档删除率。这样能避免存在大量体积过小的 segment
              "max_merged_segment": "5gb",      # 自动合并时,限制产生的 segment 的最大大小
              "max_merge_at_once": 10,          # 自动合并时,每次最多同时合并多少个 segment
              "max_merge_at_once_explicit": 30, # forcemerge 或 expunge_delete 时,每次最多同时合并多少个 segment
              "segments_per_tier": 10,          # 每层最多存在的 segment 数,如果超过该值则触发一次自动合并
            }
          }
        }
      }
    }
    
  • 对于 max_merged_segment :
    • 如果 n 个 segment 预计的合并后体积低于 max_merged_segment ,则自动合并。否则,让 n-1 再预计合并后体积。
      • 即使 n=1 ,但如果存在 deleted 文档,也可能被自动合并。
    • 如果某个 segment 的体积超过 max_merged_segment ,则可能一直不会被自动合并,除非其中的文档删除率足够大。
      • 此时可以通过 forcemerge 强制合并,或者通过 reindex 重新创建该索引。

# data stream

:数据流。一种管理单元,包含一个或多个后端索引(backing index)。

  • 数据流适合存储大量呈时间序列的数据,且平时只需要新增文档,很少修改、删除文档。
  • 数据流创建的索引默认按以下格式命名:
    ds-<data-stream>-<yyyy.MM.dd>-<generation_id>
    
  • 当数据流收到一个查询文档的请求时,会自动路由到它的各个索引。
  • 每个存储到数据流的文档,必须包含一个 @timestamp 字段,属于 date 或 date_nanos 类型。
  • 例:向一个数据流中新增一个文档
    POST /my-data-stream/_doc/
    {
      "@timestamp": "2020-03-08T11:06:07.000Z",
      "message": "Hello"
    }
    
    查询数据流中的文档:
    GET /my-data-stream/_search
    {
      "query": {
        "match": {
          "message": "Hello"
        }
      }
    }
    

# ILM

:索引生命周期管理(Index lifecycle Management),是一些自动管理索引的策略,比如减少副本的数量、超过多少天就删除索引。

# 线程池

  • ES 的每个节点创建了多个线程池(thread pool),分别处理 get、index 等不同类型的请求。

  • 可通过 GET /_nodes/stats 查询各个节点的线程池状态,例如:

    "thread_pool": {
      "get": {                # 处理 get 请求的线程池
        "threads": 16,        # 线程总数
        "queue": 0,           # 等待被处理的请求数
        "active": 0,          # 正在处理请求的线程数
        "rejected": 0,        # 已拒绝的请求数,ES 重启之后会重新计数
        "largest": 16,        # 最大的 active 数
        "completed": 1580335  # 已完成的请求数,ES 重启之后会重新计数
      },
      "search": {
        "threads": 25,
        "queue": 0,
        "active": 1,
        "rejected": 0,
        "largest": 25,
        "completed": 3340013239
      },
      ...}
    
    • 也可通过 GET /_cat/thread_pool?v&h=host,name,size,active,queue_size,queue,rejected,largest,completed 查询。
    • 如果 active 的线程数达到线程池上限,即没有空闲的线程,则新增的请求会被放到 queue 缓冲队列,等待处理。
    • 如果 queue 中的请求数达到队列上限,则新增的请求会被拒绝(rejected),对客户端报错 HTTP 429 。
    • ES 集群的 queue 总量等于 node_count*queue_size 。
  • 配置示例:

    node.processors: 2      # 当前主机可用的 CPU 核数,默认为全部核数
    
    thread_pool:
      write:
        # type: fixed       # 线程池大小的类型,fixed 是固定数量,scaling 是自动调整数量
        # size: 10          # 线程池大小
        queue_size: 1000    # 队列大小,取值为 -1 则不限制
    
    • 如果 ES 经常发生 rejected 报错,建议采用默认的线程池 size ,只是增加 queue_size ,或者增加节点数量、增加 CPU 核数。
  • 几个线程池的默认容量:

    线程池 处理操作 size queue_size
    search count、search、suggest CPU_count*3/2+1 1000
    get get CPU_count 1000
    write index、delete、update、bulk CPU_count 1000
    force_merge force_merge 1 -1

# 相关 API

# cat

:Compact and aligned text(紧凑的文本信息)

  • ES 返回的响应内容默认采用 JSON 格式,方便程序处理。而使用 _cat API 会按列表形式返回一些统计信息,更适合供人阅读。
  • 相关 API :
    GET  /_cat/nodes                # 查询节点的信息
    GET  /_cat/indices[/<index>]    # 查询索引的信息
    GET  /_cat/shards[/<index>]     # 查询分片的信息
    GET  /_cat/segments[/<index>]   # 查询索引段的信息
    GET  /_cat/templates            # 查询索引模板的信息
    
    • _cat 支持在 URL 中加入以下请求参数:
      ?v                      # verbose ,增加显示一行表头
      ?help                   # 显示所有可用的列名及其含义
      ?v&h=ip,disk*           # headers ,只显示指定的列。支持使用通配符
      ?sort=index,docs.count  # 按一个或多个字段升序排列
      ?sort=index:desc        # 降序排列
      

# tasks

  • _tasks API 用于管理 ES 集群中执行的任务。
  • 相关 API :
    GET   /_tasks                       # 查询各个节点上正在执行的任务
    GET   /_tasks?detailed=true         # 查询任务的详细信息
    GET   /_tasks?nodes=node1,node2     # 查询指定节点上执行的任务
    GET   /_tasks?wait_for_completion=true&timeout=10s  # 等待任务执行完,才返回响应
    
    POST  /_tasks/<task_name>/_cancel         # 取消任务
    POST  /_tasks/_cancel?nodes=node1,node2   # 取消任务
    

# reindex

  • reindex API 用于将源 index 中的文档拷贝到目标 index 中。

    • 源 index 可以是位于当前 ES ,也可以是位于其它 ES 。
    • 拷贝时,不会拷贝 settings、mappings ,因此需要实现创建 dest index 或 index template 。
  • 例:

    POST /_reindex
    {
      "source": {
        "index": "index_1",
        # "query": {            # 可以加上 query 子句,只拷贝部分文档
        #   "match": {
        #     "test": "data"
        #   }
        # },
        # "_source": ["user.id", "_doc"]  # 指定要拷贝的字段。默认为 true ,拷贝全部字段
        # "max_docs": 1000,     # 限制拷贝的文档数,默认不限制
      },
      "dest": {
        "index": "index_2",
        # "op_type": "create"
      },
      # "conflicts": "proceed"  # 拷贝时,如果遇到文档已存在的 version conflict 报错,默认会停止 reindex 。如果设置该参数,则会继续执行 reindex ,只是记录冲突的次数
    }
    
  • 例:从其它 ES 拷贝文档到当前 ES

    1. 在 elasticsearch.yml 中添加允许 reindex 的远程 ES 白名单:
      reindex.remote.whitelist: "10.0.0.2:9200,10.0.1.*:*"   # 可以填多个服务器地址,不需要加 http:// 前缀
      
    2. 调用 reindex API :
      POST /_reindex
      {
        "source": {
          "remote": {                       # 要连接的远程 ES
            "host": "http://10.0.0.2:9200", # ES 的地址必须加协议前缀,且声明端口号
            "username": "test",
            "password": "******"
          },
          "index": "index_1",               # 要拷贝的源 index 名称
        },
        "dest": {
          "index": "index_2"
        }
      }
      
    3. 查看 reindex 任务的进度:
      GET /_tasks?detailed=true&actions=*reindex
      

# rollover

  • 过渡(rollover):当满足指定条件时,将索引迁移到另一个索引。
  • 相关 API :
    POST /<rollover-target>/_rollover/<target-index>  <request_body>  # 给索引添加一个过渡规则
    
    • 过渡目标 target-index 可以是索引别名或数据流。如果省略该值,则将原索引名递增 1 ,作为目标名。
  • 例:
    POST /my-index-1/_rollover/my-index-2
    {
      "conditions": {                       # 这里指定了多个条件,只要满足其中之一即可
        "max_age":   "7d",                  # 索引创建之后的存在时长
        "max_docs":  1000,
        "max_size": "5gb"
      }
    }
    

# snapshot

:用于将索引保存为快照文件,从而备份数据。

  • 用法:

    1. 在 elasticsearch.yml 中加入配置:
      path.repo: ["backups"]    # 声明存储备份仓库的目录
      
    2. 创建一个备份仓库:
      PUT _snapshot/backup_repo_1
      {
        "type": "fs",                             # fs 类型表示共享文件系统,需要挂载到所有 ES 节点
        "settings": {
          "location": "backup_repo_1",            # 指定该仓库的存储路径,这里使用相对路径,实际保存路径为 elasticsearch/backup/backup_repo_1
          # "max_snapshot_bytes_per_sec": "20mb", # 限制生成快照的速度
          #"max_restore_bytes_per_sec": "20mb"    # 限制导入快照的速度
        }
      }
      
    3. 创建快照:
      PUT /_snapshot/backup_repo_1/snapshot_1
      {
        "indices": "index_1,index_2"
      }
      
      • 此时会立即返回响应报文,然后在后台创建快照。
      • 如果已存在同名的 snapshot ,则会报错:Invalid snapshot name [snapshot_1], snapshot with the same name already exists
      • 生成的第一个快照文件是全量备份,而之后的快照文件是增量备份。
    4. 从快照中导入索引,从而恢复数据:
      PUT /_snapshot/backup_repo_1/snapshot_1
      {
        "indices": "index_1,index_2"
      }
      
  • 相关 API :

    PUT   /_snapshot/<repo>                     [request_body]  # 创建备份仓库
    PUT   /_snapshot/<repo>/<snapshot>          [request_body]  # 生成快照
    POST  /_snapshot/<repo>/<snapshot>/_restore [request_body]  # 导入快照
    
    POST    /_snapshot/<repo>/_cleanup          # 删除未被现有快照引用的过时数据
    DELETE  /_snapshot/<repo>/<snapshot>        # 删除快照
    
    GET   /_snapshot/_all                       # 查看所有备份仓库
    GET   /_snapshot/<repo>                     # 查看一个备份仓库的信息
    GET   /_snapshot/<repo>/_all                # 查看一个备份仓库下的所有快照
    GET   /_snapshot/<repo>/<snapshot>          # 查看指定快照的信息
    GET   /_snapshot/<repo>/<snapshot>/_status  # 增加显示快照的 size_in_bytes
    
    GET   /_recovery/                           # 查看所有创建、恢复快照的记录