《Elasticsearch核心技术与实战》笔记 -- 第三章:入门(1)

749 阅读12分钟

这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

视频课程:极客时间 -- Elasticsearch核心技术与实战-- 配套代码 GitHub

系列文章:

《Elasticsearch核心技术与实战》笔记 -- 第一章:概述
《Elasticsearch核心技术与实战》笔记 -- 第二章:安装上手

基本概念:索引、文档和 REST API

文档

  • ElasticSearch 是面向文档的,文档是所有可搜索数据的最小单位
    • 日志文件中的日志项
    • 一部电影的具体信息 / 一张唱片的详细信息
    • MP3 播放器里的一首歌 / 一篇PDF 文档中的具体内容
  • 文档会被序列化成 JSON 格式,保存在 Elasticsearch 中
    • JSON 对象由字段组成
    • 每个字段都有对应的字段类型 (字符串 / 数值 / 布尔 / 日期 / 二进制 / 范围类型)
  • 每个文档都有一个 Unique ID
    • 你可以自己指定 ID
    • 或者通过 Elasticsearch 自动生成

JSON 文档

  • 一篇文档包含了一系列的字段。类似数据库表中的一条记录
  • JSON 文档,格式灵活,不需要预先定义格式
    • 字段的类型可以指定或者通过 ElasticSearch 自动推算
    • 支持数组 / 支持嵌套

1、json文档.png

文档的元数据

2、文档元数据.png

  • 元数据,用于标注文档的相关信息
    • _index - 文档所属的索引名
    • _type - 文档所属的类型名
    • _id - 文档唯一 Id
    • _source - 文档的原始 Json 数据
    • _all - 整合所有字段内容到该字段,已被废除(7.0版本后被废除)
    • _version - 文档的版本信息
    • _score - 相关性打分

索引

3、索引.png

  • Index - 索引是文档的容器,是一类文档的结合
    • Index 体现了逻辑空间的概念,每个索引都有自己的 Mapping 定义,用于定义包含的文档的字段名和字段类型
    • Shard 体现了物理空间的概念;索引中的数据分散在 Shard 上
  • 索引的 Mapping 与 Setting
    • Mapping 定义文档字段的类型
    • Setting 定义不同的数据分布

索引的不同语意

4、索引的不同语意.png

  • 名词:一个 ElasticSearch 集群中,可以创建很多个不同的索引
  • 动词:保存一个文档到 ElasticSearch 的过程也叫索引(indexing)
    • ES 中,创建一个倒排索引的过程
  • 名词:一个B 树索引,一个倒排索引

Type

5、type.png

  • 在 7.0 之前,一个 Index 可以设置多个 Types
  • 在 6.0 开始, Type 已经被 Deprecated,7.0 开始,一个索引只能创建一个 Type - _doc 默认类型(default type)
  • 字段类型详解:www.cnblogs.com/candlia/p/1…

抽象与类比

  • 传统关系型数据库和 ElasticSearch 的区别
    • ElasticSearch - Schemalass / 相关性 / 高性能全文检索
    • RDMS - 事务性 / Join
RDBMSElasticSearch
TableIndex(Type)
RowDocument
ColumnFiled
SchemaMapping
SQLDSL

REST Api -- 很容易被各种语言调用

6、restapi.png

一些基本的 API

  • Indices
    • 创建 Index
      • PUT Movies
  • 查看所有 Index
    • _cat/indices

kibana 索引管理及操作

http://localhost:5601/app/management/data/index_management/indices

7、kibana索引管理.png

查看索引相关信息

  • GET kibana_sample_data_ecommerce
{
  "kibana_sample_data_ecommerce" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "category" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword"
            }
          }
        },
        "currency" : {
          "type" : "keyword"
        },
        "customer_birth_date" : {
          "type" : "date"
        },
        "customer_first_name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "customer_full_name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
          
    ....此处省略部分信息....
          
    "settings" : {
      "index" : {
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            }
          }
        },
        "number_of_shards" : "1",
        "auto_expand_replicas" : "0-1",
        "provided_name" : "kibana_sample_data_ecommerce",
        "creation_date" : "1636645300804",
        "number_of_replicas" : "0",
        "uuid" : "3krdWclZQe66NVj1TmobYQ",
        "version" : {
          "created" : "7150099"
        }
      }
    }
  }
}

查看索引文档数

  • GET kibana_sample_data_ecommerce/_count
{
  "count" : 4675,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  }
}
  • 查看前十条文档,了解文档格式
    • POST kibana_sample_data_ecommerce/_search
{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4675,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "kibana_sample_data_ecommerce",
        "_type" : "_doc",
        "_id" : "mhapD30B2_nndi5vbKef",
        "_score" : 1.0,
        "_source" : {
          "category" : [
            "Men's Clothing"
          ],
          "currency" : "EUR",
          "customer_first_name" : "Eddie",
          "customer_full_name" : "Eddie Underwood",
          "customer_gender" : "MALE",
          "customer_id" : 38,
          "customer_last_name" : "Underwood",
          "customer_phone" : "",
          "day_of_week" : "Monday",
          "day_of_week_i" : 0,
          "email" : "eddie@underwood-family.zzz",
          "manufacturer" : [
            "Elitelligence",
            "Oceanavigations"
          ],
          "order_date" : "2021-11-22T09:28:48+00:00",
          "order_id" : 584677,
          "products" : [
            {
              "base_price" : 11.99,
              "discount_percentage" : 0,
              "quantity" : 1,
              "manufacturer" : "Elitelligence",
              "tax_amount" : 0,
              "product_id" : 6283,
              "category" : "Men's Clothing",
              "sku" : "ZO0549605496",
              "taxless_price" : 11.99,
              "unit_discount_amount" : 0,
              "min_price" : 6.35,
              "_id" : "sold_product_584677_6283",
              "discount_amount" : 0,
              "created_on" : "2016-12-26T09:28:48+00:00",
              "product_name" : "Basic T-shirt - dark blue/white",
              "price" : 11.99,
              "taxful_price" : 11.99,
              "base_unit_price" : 11.99
            },
            {
              "base_price" : 24.99,
              "discount_percentage" : 0,
              "quantity" : 1,
              "manufacturer" : "Oceanavigations",
              "tax_amount" : 0,
              "product_id" : 19400,
              "category" : "Men's Clothing",
              "sku" : "ZO0299602996",
              "taxless_price" : 24.99,
              "unit_discount_amount" : 0,
              "min_price" : 11.75,
              "_id" : "sold_product_584677_19400",
              "discount_amount" : 0,
              "created_on" : "2016-12-26T09:28:48+00:00",
              "product_name" : "Sweatshirt - grey multicolor",
              "price" : 24.99,
              "taxful_price" : 24.99,
              "base_unit_price" : 24.99
            }
          ],
          "sku" : [
            "ZO0549605496",
            "ZO0299602996"
          ],
          "taxful_total_price" : 36.98,
          "taxless_total_price" : 36.98,
          "total_quantity" : 2,
          "total_unique_products" : 2,
          "type" : "order",
          "user" : "eddie",
          "geoip" : {
            "country_iso_code" : "EG",
            "location" : {
              "lon" : 31.3,
              "lat" : 30.1
            },
            "region_name" : "Cairo Governorate",
            "continent_name" : "Africa",
            "city_name" : "Cairo"
          },
          "event" : {
            "dataset" : "sample_ecommerce"
          }
        }
      },
      ...剩余还有九条记录...
    ]
  }
}

查看indices

  • GET /_cat/indices/kibana*?v&s=index
health status index                        uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   kibana_sample_data_ecommerce 3krdWclZQe66NVj1TmobYQ   1   0       4675            0      3.9mb          3.9mb
green  open   kibana_sample_data_flights   pDqG7IFiTU-OmBGWNxFoUg   1   0      13059            0      5.4mb          5.4mb
green  open   kibana_sample_data_logs      wnDLe-UKThm_bxeEHttUMA   1   0      14074            0      8.8mb          8.8mb

查看状态为绿色的索引

  • GET /_cat/indices?v&health=green
health status index                           uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .geoip_databases                eQG671gRQ_iZVqTsQjCoXg   1   0         42           39     40.6mb         40.6mb
green  open   .kibana_7.15.0_001              oUpr8MWaSSSz03le9LY7Pw   1   0        303           49      3.4mb          3.4mb
green  open   .apm-custom-link                FPjNyXGNTVqCoIRznmUH8Q   1   0          0            0       208b           208b
green  open   kibana_sample_data_ecommerce    3krdWclZQe66NVj1TmobYQ   1   0       4675            0      3.9mb          3.9mb
green  open   .kibana-event-log-7.15.0-000001 Y-1aDsuUTZy39aCZbLmPVQ   1   0          2            0     11.9kb         11.9kb
green  open   .apm-agent-configuration        ExWGfjcESt6TR5zLtg0LJw   1   0          0            0       208b           208b
green  open   kibana_sample_data_logs         wnDLe-UKThm_bxeEHttUMA   1   0      14074            0      8.8mb          8.8mb
green  open   .async-search                   IXKJJTPCSRmg3LcrI3cpiQ   1   0          0            0    279.3kb        279.3kb
green  open   .kibana_task_manager_7.15.0_001 jtovZQEQSey9HJD4xnaUqA   1   0         15        10135      1.7mb          1.7mb
green  open   kibana_sample_data_flights      pDqG7IFiTU-OmBGWNxFoUg   1   0      13059            0      5.4mb          5.4mb
green  open   .tasks                          VK0TmD2HTdSCjQsxmy_vUA   1   0          2            0     13.7kb         13.7kb

按照文档个数排序

  • GET /_cat/indices?v&s=docs.count:desc
health status index                           uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   movies                          p54hyh_sR-6L1OF05s7Ihg   1   1      62424            0      7.3mb          7.3mb
green  open   kibana_sample_data_logs         wnDLe-UKThm_bxeEHttUMA   1   0      14074            0      8.8mb          8.8mb
green  open   kibana_sample_data_flights      pDqG7IFiTU-OmBGWNxFoUg   1   0      13059            0      5.4mb          5.4mb
green  open   kibana_sample_data_ecommerce    3krdWclZQe66NVj1TmobYQ   1   0       4675            0      3.9mb          3.9mb
green  open   .kibana_7.15.0_001              oUpr8MWaSSSz03le9LY7Pw   1   0        303           52      3.4mb          3.4mb
green  open   .geoip_databases                eQG671gRQ_iZVqTsQjCoXg   1   0         42           39     40.6mb         40.6mb
green  open   .kibana_task_manager_7.15.0_001 jtovZQEQSey9HJD4xnaUqA   1   0         15        10188      1.6mb          1.6mb
green  open   .kibana-event-log-7.15.0-000001 Y-1aDsuUTZy39aCZbLmPVQ   1   0          2            0     11.9kb         11.9kb
green  open   .tasks                          VK0TmD2HTdSCjQsxmy_vUA   1   0          2            0     13.7kb         13.7kb
green  open   .apm-custom-link                FPjNyXGNTVqCoIRznmUH8Q   1   0          0            0       208b           208b
green  open   .apm-agent-configuration        ExWGfjcESt6TR5zLtg0LJw   1   0          0            0       208b           208b
green  open   .async-search                   IXKJJTPCSRmg3LcrI3cpiQ   1   0          0            0    279.3kb        279.3kb

查看索引所占的内存

  • GET /_cat/indices?v&h=i,tm&s=tm:desc
i                                   tm
kibana_sample_data_ecommerce      72kb
kibana_sample_data_logs           50kb
movies                            39kb
kibana_sample_data_flights      35.4kb
.kibana_task_manager_7.15.0_001   29kb
.kibana_7.15.0_001              28.3kb
.geoip_databases                 8.5kb
.kibana-event-log-7.15.0-000001  4.7kb
.tasks                           4.4kb
.apm-custom-link                    0b
.apm-agent-configuration            0b
.async-search                       0b

8、kibana操作.png

# 查看索引相关信息
GET kibana_sample_data_ecommerce

# 查看索引的文档数
GET kibana_sample_data_ecommerce/_count

# 查看前十条文档,了解文档格式
POST kibana_sample_data_ecommerce/_search

# _cat indices api
# 查看indices
GET /_cat/indices/kibana*?v&s=index

# 查看状态为绿色的索引
GET /_cat/indices?v&health=green

# 按照文档个数排序
GET /_cat/indices?v&s=docs.count:desc

# 查看具体的字段
GET /_cat/indices/kibana*?pri&v&h=health,index,pri,rep,docs.count,mt

# 查看索引所占的内存
GET /_cat/indices?v&h=i,tm&s=tm:desc

基本概念:节点、集群、分片及副本

分布式特征

  • ElasticSearch 分布式架构的好处
    • 存储的水平扩容
    • 提高系统的可用性,部分节点停止服务,整个集群的服务不受影响
  • ElasticSearch 的分布式架构
    • 不同的集群通过不同的名字来区分,默认名字 “elasticsearch”
    • 通过配置文件修改,或者命令行中 -E cluster.name=tyron 进行设定
    • 一个集群可以有一个或者多个节点

节点

  • 节点是一个 ElasticSearch 的实例
    • 本质上就是一个 Java 进程
    • 一台机器上可以运行多个 ElasticSearch 进程,但是生产环境一般建议一台机器上只运行一个 ElasticSearch 实例
  • 每一个节点都有名字,通过配置文件进行配置,或者启动时候 -E node.name=node1 指定
  • 每一个节点在启动之后,会分配一个 UID,保存在 data 目录下

Master-eligible nodes 和Master Node

  • 每个节点启动后,默认就是一个 Master eligible 节点
    • 可以设置 node.master:false 禁止
  • Master-eligible 节点可以参加选举主流程,成为 Master 几点
  • 当每一个节点启动时候,它会将自己选举成 Master 节点
  • 每个节点上都保存了集群的状态,只有 Master 节点才能修改集群的状态信息
    • 集群状态(Cluster State),维护了一个集群中必要的信息
      • 所有的节点信息
      • 所有的索引和其相关的 Mapping 与 Setting 信息
      • 分片的路由信息
    • 任意节点都能修改信息会导致数据的不一致性

Data Node & Coordinating Node

  • Data Node
    • 可以保存数据的节点,叫做 Data Node。负责保存分片数据,在数据扩展上起到了至关重要的作用。
  • Coordinating Node
    • 负责接收 Client 的请求,将请求分发到合适的节点,最终把结果汇聚到一起
    • 每个节点默认都起到了 Coordinating Node的职责

其他的节点类型

  • Hot & Warm Node
    • 不同硬件配置的 Data Node,用来实现 Hot & Warm 架构,降低集群部署成本
  • Machine Learning Node
    • 负责跑机器学习的 Job,用来做异常检测
  • Tribe Node
    • (5.3 开始使用 Cross Cluster Search)Tribe Node 连接到不同的 ElasticSearch 集群,并且支持将这些集群当做一个单独的集群处理

配置节点类型

  • 开发环境中,一个节点可以承担多种juese
  • 生产环境中,应该设置单一角色的节点 (dedicated node)
节点类型配置参数默认值
master eligiblenode.mastertrue
datanode.datatrue
ingestnode.ingesttrue
coordinating only每个节点默认都是 coordinating 节点,设置其他类型全部为false
machine learningnode.mltrue(需enable x-pack)

分片(Primary Shard & Replica Shard)

  • 主分片,用以解决数据水平拓展的问题。通过主分片,可以将数据分布到集群内的所有节点之上

    • 一个分片是一个运行的 Lucene 的实例
    • 主分片数在索引创建时指定,后续不允许修改,除非 Reindex
  • 副本,用以解决数据高可用的问题,分片主分片的拷贝

    • 副本分分片数,可以动态调整
    • 增加副本数,还可以在一定程度上提高服务的可用性(读取得吞吐)
  • 一个三节点的集群中,blogs 索引的分片分布情况

    • 思考:增加一个节点或改大主分片数对系统的影响?

9、分片.png

分片的设定

  • 对于生产环境中分片的设定,需要提前组好容量规划
    • 分片数设置过小
      • 导致后续无法增加节点实现水平扩容
      • 单个分片的数据量太大,导致数据重新分配耗时
    • 分片数量设置过大,7.0 开始,默认主分片设置为 1,解决了 over-sharding 的问题
      • 影响搜索结果的相关性打分,影响统计结果的准确性
      • 单个节点上过多的分片,对导致资源的浪费,同时也会影响性能

查看集群的健康状况

10、集群健康状况.png

集群操作在docker环境安装后进行演示补充。

文档的基本 CRUD 与批量操作

CRUD操作
IndexPUT my_index/_doc/1 {"user":"mike","comment":"You know,for search"}
CreatePUT my_index/_create/1 {"user":"mike","comment":"You know,for search"}
POST my_index/——doc (不指定ID,自动生成) {"user":"mike","comment":"You know,for search"}
ReadGET my_index/_doc/1
UpdatePOST my_index/_update/1 {"doc":{"user":"mike","comment":"You know,for search"}}
DeleteDELETE my_index/_doc/1
  • Type 名,约定都用 _doc
  • Create,如果 ID 已经存在,会失败
  • Index,如果 ID 不存在,创建新的文档,否则,会先删除现有文档,再创建新的文档,版本会增加
  • Update,文档必须已经存在,更新只会对相应字段做增量修改

Create 文档

  • 支持自动生成文档 Id 和指定文档 Id 两种方式
  • 通过调用 “POST /users/_doc“ ,系统会自动生成 document Id
  • 使用 HTTP PUT user/_create/1 创建时,URI 中显示指定 _create,此时如果该 id 的文档已经存在,操作失败

GET 文档

  • 找到文档,返回 HTTP 200
    • 文档元信息
      • 版本信息,同一个 id 的文档,即使被删除,Version号也会不断增加
      • _source 中默认包含了文档的所有原始信息
  • 找不到文档,返回 HTTP 404

Index 文档

  • Index 和 Create 不一样的地方:如果文档不存在,就会索引新的文档,否则现有文档会被删除,新的文档被索引,版本信息 +1

Update 文档

  • Update 方法不会删除原来的文档,而是实现真正数据的更新
  • Post 方法 / Payload 需要包含在 “doc” 中

ES 操作

# create document 自动生成 _id
POST users/_doc
{
  "user":"Tyron",
  "poset_date": "2021-10-10T 13:10:10",
  "message":"trying out kibana"
}

{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "zTFsH30BWlRHpTG9YJXm",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

# create document,指定id,如果id已经存在,报错
PUT users/_doc/1?op_type=create
{
  "user":"Milk",
  "poset_date": "2021-10-10T 13:10:10",
  "message":"trying out kibana"
}
#第一次执行
{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}
#第二次执行
{
  "error" : {
    "root_cause" : [
      {
        "type" : "version_conflict_engine_exception",
        "reason" : "[1]: version conflict, document already exists (current version [1])",
        "index_uuid" : "vTw-Xm05TeycobYXlwN1eA",
        "shard" : "0",
        "index" : "users"
      }
    ],
    "type" : "version_conflict_engine_exception",
    "reason" : "[1]: version conflict, document already exists (current version [1])",
    "index_uuid" : "vTw-Xm05TeycobYXlwN1eA",
    "shard" : "0",
    "index" : "users"
  },
  "status" : 409
}

#get document by id
GET users/_doc/1

{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "user" : "Milk",
    "poset_date" : "2021-10-10T 13:10:10",
    "message" : "trying out kibana"
  }
}

# put index操作会将原文档删除,再将新文档添加,同时version+1
PUT users/_doc/1
{
  "user":"Tyron"
}
{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 2,
  "_primary_term" : 1
}
#再执行get操作
{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "_seq_no" : 2,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "user" : "Tyron"
  }
}

# 在原文档中增加字段
POST users/_update/1/
{
 "doc": {
    "user":"POST",
    "poset_date": "2021-10-10T 13:10:10",
    "message":"users/_update/1"
 }
}
{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 3,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 3,
  "_primary_term" : 1
}
# 在原文档中增加字段
{
  "_index" : "users",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 3,
  "_seq_no" : 3,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "user" : "POST",
    "message" : "users/_update/1",
    "poset_date" : "2021-10-10T 13:10:10"
  }
}

Bulk API

  • 支持在一次 API 调用中,对不同的索引进行操作

  • 支持四种类型操作

    • Index
    • Create
    • Update
    • Delete
  • 可以在 URI 中指定 Index,也可以在请求的 Payload 中进行

  • 操作中单条操作失败,并不会影响其他操作

  • 返回结果包括了每一条操作执行的结果

11、bulk操作.png

批量读取 - mget

  • 批量操作,可以减少网络连接所产生的开销,提高性能

12、mget.png

批量查询 - msearch

13、msearch.png

常见错误返回

问题原因
无法连接网络故障或集群挂了
连接无法关闭网络故障或节点出错
429集群过于繁忙
4XX请求体格式有错
500集群内部错误