龙叔学ES:ElasticSearch扫盲篇

1,624 阅读14分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


    希望读完本文,你会对 ElasticSearch 有一个基本且全面的了解。

    (注意哦 本文讲解的主要都是 ES 7版本之后 的内容))

1 什么是ElasticSearch?

    一个采用 restful API 标准的 考扩展型 和 高可用型的 实时数据分析的全文搜索工具

2 ES概念、架构、原理

2.1 基础概念

  • Node(节点):单个装有ES的服务器。

  • Cluster(集群):一个ES集群就是由一个或多个Node组成(每个Node都是对等关系,去中心化)。

  • Document(文档):一个文档就是一个可被索引的基础信息单元

  • Index(索引):索引就是一个拥有相似特征的文档的集合

  • Type(类型):一个索引中,你可以定义一种或多种类型(7.x版本及之后已经剔除)

  • Filed(字段):Filed是ES的最小单位,相当于数据的某一列

  • Shards(分片):ES将索引分成多份,每一份就是一个Shard

  • Replicas(复制):Replicas是索引一份或多份拷贝

2.2 ES和关系型数据库概念对比

7.x 版本之前的关系对比

7.x 版本之后的关系对比(剔除了type)

2.3 ES架构

  • Gateway代表ElasticSearch索引的持久化存储方式。在Gateway中,ElasticSearch默认先把索引存储在内存中,然后当内存满的时候,再持久化到Gateway里。当ES集群关闭或重启的时候,它就会从Gateway里去读取索引数据。比如LocalFileSystem和HDFS、AS3等。

  • DistributedLucene Directory,它是Lucene里的一些列索引文件组成的目录。它负责管理这些索引文件。包括数据的读取、写入,以及索引的添加和合并等。

  • River,代表是数据源。是以插件的形式存在于ElasticSearch中。 

  • Mapping,映射的意思,非常类似于静态语言中的数据类型。比如我们声明一个int类型的变量,那以后这个变量只能存储int类型的数据。

  • Search Moudle,搜索模块

  • Index Moudle,索引模块

  • Disvcovery,主要是负责集群的master节点发现。比如某个节点突然离开或进来的情况,进行一个分片重新分片等。

  • Scripting,即脚本语言。包括很多,这里不多赘述。如mvel、js、python等。   

  • Transport,代表ElasticSearch内部节点,代表跟集群的客户端交互。包括 Thrift、Memcached、Http等协议

  • RESTful Style API,通过RESTful方式来实现API编程。

  • 3rd plugins,代表第三方插件。

  • Java(Netty),是开发框架。

  • JMX,是监控。

2.4 主分片与副本

    假如一个索引被设置为3分片,1副本,那么他在一个有3个数据节点的集群中的存储方式可能是下图这样的。

2.5 ES数据写入原理

2.6 节点类型

    节点类型是由配置文件中【node.roles】配置项决定的,一个集群至少要有master和date两种角色的节点存在。

    随着集群的增长,特别是当有大量的机器学习任务或连续转换时,考虑将专用的主节点与专用的数据节点、机器学习节点和转换节点分开是比较合理的一种做法。

    不过大部分的节点类型一般是用不到的。

a、Master-eligible node 【候选主节点】

    主节点负责轻量级集群范围的操作,例如创建或删除索引、跟踪哪些节点是集群的一部分,以及决定将哪些分片分配给哪些节点。集群运行状况需要一个稳定的主节点。而主节点就是从候选主机点中产生的

    任何有候选主节点角色的节点,都可以在选举过程被选为主节点。

配置文件中配置:

node.roles: [ master ]

或者

node.roles: [ master,data ]

b、Voting-only master-eligible node【仅参与投票的候选主节点】

    这种候选主节点,只是会在选举阶段,参与投票,但是不会被选为主节点(只有具有master角色的节点才能被标记为具有voting_only角色。)

配置文件中配置:

node.roles: [ data, master, voting_only ]

或者

node.roles: [ master, voting_only ]

c、Data node【数据节点】

    数据节点保存 包含已建立索引的文档 的分片。处理与数据相关的操作,如CRUD、搜索和聚合。这些操作都是I/O、内存和cpu密集型的,所以监视这些资源很重要,并在它们过载时添加更多的数据节点进行横向扩容。

配置文件中配置:

node.roles: [ data ]

d、Content data node【内容数据节点】

    内容数据节点容纳用户创建的内容。它们支持CRUD、搜索和聚合等操作。

配置文件中配置:

node.roles: [ data_content]

e、Hot data node【热数据节点】

    热数据节点会存储时间序列数据。热层的读写速度要求较高,需要占用较多的硬件资源(如SSD硬盘)。

配置文件中配置:

node.roles: [ data_hot ]

f、Warm data node【暖数据节点】

    暖数据节点存储那些不再定期更新但仍在查询的索引。 查询量的频率通常低于索引处于热层时的频率。 性能较低的硬件通常可用于此层中的节点。

配置文件中配置:

node.roles: [ data_warm ]

g、Cold data node【冷数据节点】

    冷数据节点存储只读索引,只读索引访问频率较低。这一层使用性能较差的硬件,并且可以利用可搜索的快照索引来最小化所需的资源。

配置文件中配置:

node.roles: [ data_cold ]

h、Frozen data node【冻结数据节点】

    冻结层只存储部分安装的指数。建议使用专用节点。

配置文件中配置:

node.roles: [ data_frozen ]

i、Ingest node【摄取节点】

    摄取节点可以执行由一个或多个摄取处理器组成的预处理管道。根据摄取处理器执行的操作类型和所需资源的不同,使用专用的摄取节点可能是有意义的,这些节点将只执行这个特定的任务。

配置文件中配置:

node.roles: [ ingest ]

j、Coordinating only node【协调节点】

    如果一个节点不处理主任务、不保存数据和不预处理文档,没有任何角色,那么这个节点就可以说是协调节点,它只能路由请求、处理搜索reduce阶段和分发批量索引。本质上,就像智能负载均衡器。

    协调节点可以使大型集群受益。它们加入集群并监视完整的集群状态,就像其他每个节点一样,它们使用集群状态将请求直接路由到适当的节点。

配置文件中配置:

node.roles: [ ]

k、Remote-eligible node 【跨集群客户端节点】

    符合远程条件的节点充当跨集群客户端,并连接到远程集群。连接后,可以使用跨集群搜索搜索远程集群。还可以使用跨集群复制在集群之间同步数据。

配置文件中配置:

node.roles: [ remote_cluster_client  ]

l、Machine learning node【机器学习节点】

    机器学习节点运行作业并处理机器学习API请求。

配置文件中配置:

node.roles: [ ml, remote_cluster_client ]

m、Transform node【转换节点】

    转换节点运行转换并处理转换API请求

配置文件中配置:

node.roles: [ transform, remote_cluster_client ]

3、ES安装搭建

3.1、安装JDK

    这里要注意:在elasticsearch7以上的版本中会自带jdk.也就无需再单独安装jdk了

    jdk下载地址:jdk.java.net/19/

    ES的版本是和JDK的版本有对应关系的,如果版本不匹配,安装会异常。

    对应关系可以参考官方文档:

安装过程

解压jdk压缩包:
tar -zxvf jdk-xxx-.tar.gz

然后配置环境变量
vim  /etc/profile 加入下面内容

export JAVA_HOME=【你的java路径】
export JAVA_BIN=【你的java路径】/bin
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
export JAVA_HOME JAVA_BIN PATH CLASSPATH

java -version 查看是否安装ok

3.2、安装ES

    注意:运行ES 不可以用root账户,所以要为ES建一个账号     在官网下载你需要的ES版本

    解压ES压缩包:

    tar -zxvf elasticsearch-xxx-linux-x86_64.tar.gz

    ES的各个目录简介:

    然后进入解压后的目录,进入config目录,修改 elasticsearch.yml 文件

    这里将认证相关全部关闭了,认证如何配置会单独发文

cluster.name: my-es
node.name: es-node-1
node.roles: [ data, master ]
path.data: /data/es/es_data
path.logs: /data/es/es_log
network.host: x.x.x.97
http.port: 9200
transport.port: 9300
ingest.geoip.downloader.enabled: false

discovery.seed_hosts: ["x.x.x.97:9300","x.x.x.162:9300","x.x.x.165:9300"]
cluster.initial_master_nodes: ["es-node-1","es-node-2","es-node-3"]

xpack.security.enabled: false

xpack.security.enrollment.enabled: false

xpack.security.http.ssl:
  enabled: false
  keystore.path: certs/http.p12

xpack.security.transport.ssl:
  enabled: false
  verification_mode: certificate
  keystore.path: certs/transport.p12
  truststore.path: certs/transport.p12

    然后进入解压后的目录,进入bin目录,执行后台运行启动命令:

    ./elasticsearch -d

    就可以看到ES的进程了

    然后访问服务器的9200端口可以看到相关信息就算安装成功了

    用同样的方式安装好三台之后,就可以形成集群

3.3、ES配置

配置文件介绍

  • elasticsearch.yml :ES相关配置
  • jvm.options :ES 所用JVM相关配置
  • log4j2.properties :ES的日志配置

    这里主要介绍elasticsearch.yml的配置

    配置项格式有两种写法:

path:
    data: /var/lib/elasticsearch
    logs: /var/log/elasticsearch
或者
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch

    常见重要的配置项如下 (我这是8.1版本):

    在官网会有更详细的介绍

4、索引

4.1、什么是倒排索引

    也被称为反向索引,是一中索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射,他是文档检索系统中最常用的数据结构。

    常规的索引建立方式

    【文档-->关键词】 的映射过程(正向索引,缺点:效率低,需要将文档全部遍历一遍)

    如下图

    倒排反向建立索引

    【关键词-->文档】 的映射,把正向索引的结果重新构造成倒排索引(反向索引)

    如下图,有五分文档,先对文档进行分词

    给单词和文档都进行编号

    根据单词集合和文档集合,形成矩阵:

    横向:(乔布斯,(文档1,文档2,文档3));(雷布斯,(文档1,文档2,文档3,文档4))

    纵向:(文档1,(乔布斯,雷布斯));文档5(黄章,苹果)

    再转换为倒排列表,如下图,例如:“乔布斯”在文档1的3和11位置,文档2的7位置,文档3的9位置

    也可以添加更多信息。例如单词出现频率,例如“乔布斯”在文档1的3和11位置,文档1中出现的次数是2

4.2、索引操作(curl)

a、初始化索引设置

    我们给tt_index这个所用初始化 分片数为5,副本数为1

PUT /tt_index/
{
  "settings":{
      "number_of_shards":5,
      "number_of_replicas":1
  }
}

    这里要注意:

    number_of_shards 只能在创建 index 指定,后期无法修改

    number_of_replicas 后续可以修改

b、查看索引设置

    查看单个索引的设置

GET /test_index/_settings

    查看多个索引的设置

GET /tt_index,tt_index2/_settings

    查看所有索引的设置

GET /_all/_settings

c、索引内新增数据

    不指定ID,随机ID

POST /tt_index2/_doc/
{
  "name":"dragon",
  "age":"18",
  "like":{
    "food":"apale",
    "color":"white"
  }
}

    指定ID,ID存在则被覆盖

PUT /tt_index2/_doc/2
{
  "name":"dragon",
  "age":"18",
  "like":{
    "food":"apale",
    "color":"white"
  }
}

    指定ID,ID存在则报错

PUT /tt_index2/_create/2
{
  "name":"dragon",
  "age":"18",
  "like":{
    "food":"apale",
    "color":"white"
  }
}

d、查询索引数据

    查询某个索引全部数据:

GET /tt_index2/_search

    查询某个索引有多少数据

GET /tt_index2/_count

    查询某个索引指定ID的数据

GET /tt_index2/_doc/2

    按照条件过滤查询索引数据

POST /tt_index/_search
{
    "query": {
        "range": {
            "age": {
                "lt": 19
            }
        }
    }
}

    查看索引数据的分布

GET /_cat/shards/tt_index

e、更新索引数据

PUT /tt_index2/_doc/2

{
  "name":"dragon23333",
  "age":"18",
  "like":{
    "food":"apale",
    "color":"white"
  }
}

f、删除索引数据

    删除指定ID的数据

DELETE /tt_index2/_doc/2

    删除符合条件的索引数据


POST /tt_index/_doc/_delete_by_query
{
    "query": {
        "range": {
            "age": {
                "gt": 19
            }
        }
    }
}

g、删除索引

DELETE /tt_index2

5、Mapping

5.1、什么是Mapping

    Mapping是定义文档及其包含的字段如何存储和索引的过程。

5.2、Mapping种类

a、Dynamic mapping(动态映射)

    ES真的是非常的智能,你创建一个索引,可以不进行Mapping的设置,在你插入数据的时候会自动解析生成Mapping

    直接创建索引后,此时mapping为空

    插入数据之后,就自动解析胜场了Mapping

    **要说明一点,字段的类型一旦mapping之后是不可以改的。 **

    ES动态解析的解析规则如下

b、Explicit mapping(显式映射)

    显式映射允许精确地选择如何去定义,而不是由ES自动解析创建。

  • 哪些 string 类型的 field 应当被当成当成 full-text 字段
  • 哪些字段应该是数值类型、日期类型或者是地理位置信息
  • 日期类型字段的格式是怎么样的
  • 是否文档的所有字段都需要被索引到 _all 字段

    简单举例显示的映射,如下图:

5.3、字段类型

    字段的类型真的非常多,但是一般很多都是用不到的,常见的类型如:text,keyword,date,long,double,boolean,ip。我们可以看到,类型当中没有String,字符串的类型是text,所有text类型的字段都会被全文索引。数字类型有两个,long(长整型)和double(浮点型)。

    更多的类型介绍可以在官方文档中查看

5.4、Mapping相关API

    这里说一些常见的

a、创建索引时设置mapping

PUT /mapping_index2
{
  "mappings": {
    "properties": {
      "age":    { "type": "integer" },  
      "email":  { "type": "keyword"  }, 
      "name":   { "type": "text"  }     
    }
  }
}

b、查看索引的mapping设置

GET /mapping_index/_mapping

c、新增字段类型到mapping

PUT /mapping_index2/_mapping
{
  "properties":{
    "add-field":{
      "type": "keyword",
      "index": false
    }
  }
}
 

6、别名(Aliases)

6.1、索引的别名

    别名是一组数据流或索引的次要名称。大多数Elasticsearch api接受一个别名来代替数据流或索引名。

    可以在任何时候更改别名的数据流或索引。如果在应用程序的Elasticsearch请求中使用别名,可以重新索引数据,而无需停机或更改应用程序的代码。如下图:

a、创建别名

POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-nginx",
        "alias": "logs"
      }
    }
  ]
}

b、删除别名

POST _aliases
{
  "actions": [
    {
      "remove": {
        "index": "logs-nginx",
        "alias": "logs"
      }
    }
  ]
}

c、在同一个操作中完成别名切换指向的索引

POST _aliases
{
  "actions": [
    {
      "remove": {
        "index": "logs-nginx",
        "alias": "logs"
      }
    },
    {
      "add": {
        "index": "logs-nginx2",
        "alias": "logs"
      }
    }
  ]
}

d、在创建索引的时候给索引定义别名

PUT index-aliases-1
{
  "aliases": {
    "index-aliases": {}
  }
}

e、查看别名

    查看所有索引对应的别名

GET _alias

    查看指定索引的别名

GET index-aliases-1/_alias

    查看制定别名对应的索引

GET _alias/index-aliases

6.2、字段的别名

    字段有一种类型是alias

    别名映射为索引中的字段定义了一个替代名称。别名可以在搜索请求中代替目标字段

    别名的目标有一些限制:

  • 1、目标必须是一个具体的字段,而不是一个对象或另一个字段别名。

  • 2、在创建别名时,目标字段必须已经存在。

  • 3、如果定义了嵌套对象,则字段别名必须具有与其目标相同的嵌套作用域。

    此外,一个字段别名只能有一个目标。这意味着不能使用字段别名在一个子句中查询多个目标字段。

    在Mapping中给字段定义别名字段

PUT trips
{
  "mappings": {
    "properties": {
      "distance": {
        "type": "long"
      },
      "route_length_miles": {
        "type": "alias",
        "path": "distance" 
      },
      "transit_mode": {
        "type": "keyword"
      }
    }
  }
}

     当然在一些API中是不支持使用别名字段的