侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 352 篇文章
  • 累计创建 135 个标签
  • 累计收到 10 条评论

目 录CONTENT

文章目录

ES教程1-实时搜索引擎Elasticsearch相关概念介绍

孔子说JAVA
2022-10-06 / 2 评论 / 0 点赞 / 180 阅读 / 7,726 字 / 正在检测是否收录...
广告 广告

Elasticsearch是一个基于Lucene的搜索服务器,是一个分布式可扩展的实时搜索和分析引擎。它提供了一个分布式多用户能力的全文检索引擎,基于RESTful web接口。Elasticsearch是用java语言开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

1、简介

Elasticsearch(以下简称ES)是一个基于Apache Lucene™的开源搜索引擎,无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。 但是,Lucene只是一个库。想要发挥其强大的作用,你需使用Java并要将其集成到你的应用中。Lucene非常复杂,你需要深入的了解检索相关知识来理解它是如何工作的。 ES也是使用Java编写并使用Lucene来建立索引并实现搜索功能,但是它的目的是通过简单连贯的RESTful API让全文搜索变得简单并隐藏Lucene的复杂性。 另外ES不仅仅是Lucene和全文搜索引擎,它还提供:

  • 分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。
  • 实时分析的分布式搜索引擎。
  • 可以扩展到上百台服务器,处理PB级结构化或非结构化数据。

而且,所有的这些功能被集成到一台服务器,你的应用可以通过简单的RESTful API、各种语言的客户端甚至命令行与之交互。上手Elasticsearch非常简单,它提供了许多合理的缺省值,并对初学者隐藏了复杂的搜索引擎理论。它开箱即用(安装即可使用),只需很少的学习既可在生产环境中使用。Elasticsearch在Apache 2 license下许可使用,可以免费下载、使用和修改。

随着知识的积累,你可以根据不同的问题领域定制Elasticsearch的高级特性,这一切都是可配置的,并且配置非常灵活。

2、ES与关系型数据库之间的比较

2.1 数据库搜索存在的问题

用数据库做搜索的主要问题如下:

  1. 每次搜索都要对记录的一长条内容进行扫描。
  2. like %关键字% 不能使用到索引。
  3. 不能将搜索词拆分开来,很难实现部分匹配,比如杭州医疗保险,如果搜索杭州保险,就搜索不到。
  4. 同义词的实现也比较复杂。
  5. 要给表中新增一些column,必须用复杂的修改表结构的语法去执行。而且可能对系统代码还有一定的影响。

2.2 lucene存在的问题

lucene解决了数据库搜索的相关问题,但是其也存在其他问题。首先lucene是部署在单台机器上的,假设磁盘有500个G的空间,如果我们数据量很大,有一个T的数据量,lucene放不下怎么办?

  • 放在多台设备上,分布式,散落在多台机器上。如电商网站前端搜索功能,与多台机器通信的过程,以及数据的管理,都非常麻烦。另外,保证数据不丢失,系统的高可用性上也存在很大的挑战。

这个过程如果我们自己来实现是很麻烦的。

2.3 Elasticsearch解决方案

在这种情况下Elastic search应运而生。每个es节点都封装了lucene,多个es暴露出一个统一的地址。elastic search给我们管理多台设备。还实现了副本、故障恢复等机制及性能优化。

所以,elastic search是分布式、近实时、可伸缩的搜索引擎和数据分析引擎。也可以把es当成了一个NoSQL存储引擎,一个可以存储文档类型数据的存储系统,操作里面的document。

2.4 关系型数据库与ES对比

在Elasticsearch中,文档归属于一种类型(type) ,而这些类型存在于索引(index)中,类比传统关系型数据库:

  • Elasticsearch(ES)的重要概念:Index(索引)、Type(类型)、Mapping(索引定义)、Documents(文档)、Fields(字段)、DSL(查询等语句)。

  • Relational DB(关系型数据库)的重要概念:Databases(数据库)、Tables(表)、Schema(结构、定义)、 Rows(数据行)、Column(数据列)、SQL(查询等语句)。

2.4.1 存储对比

数据库核心概念 elastic search核心概念
Database Index
Table Type
Row Document
Column Field
Schema mapping
Index Everything isindexed
sql dsl

2.4.2 操作对比

sql操作 es操作
like match query
where term filter
in terms filter多值搜索,match query 或者 should, 加上 and operator 或者 minimum_should_match
between range filter
order by sort 语句
group by bucket
聚合操作 metric

2.4.3 操作符对比

sql操作符 es操作符
and or not bool, must, should, must_not, query+operator(and, or)

3、ES核心概念

Elasticsearch有几个核心概念。从一开始理解这些概念会对整个学习过程有莫大的帮助。

1)接近实时(NRT)

Elasticsearch是一个接近实时的搜索平台。这意味着,从索引一个文档直到这个文档能够被搜索到有一个轻微的延迟(通常是1秒)。

2)集群(Cluster)

Elasticsearch 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个Elasticsearch实例。单个Elasticsearch实例称为一个节点(Node),一组节点构成一个集群(Cluster),并一起提供索引和搜索功能。

一个集群由一个唯一的名字标识,这个名字默认就是“elasticsearch”。这个名字非常重要,因为一个节点只能通过指定某个集群的名字,来加入这个集群。在产品环境中显式地设定这个名字是一个好习惯,但是使用默认值来进行测试/开发也是不错的。

3)节点(Node)

一个节点是你集群中的一个服务器,作为集群的一部分,它存储你的数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网络中的哪些服务器对应于Elasticsearch集群中的哪些节点。

  • 一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做“elasticsearch”的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此,它们将会自动地形成并加入到一个叫做“elasticsearch”的集群中。

  • 在一个集群里,只要你想,可以拥有任意多个节点。如果当前你的网络中没有运行任何Elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。

4)索引(Index)

Elasticsearch 数据管理的顶层单位就叫做 Index(索引),相当于关系型数据库里的数据库的概念。另外,每个Index的名字必须是小写。

  • 一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。

  • 在一个集群中,如果你想,可以定义任意多的索引。

5)类型(Type)

在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。类型相当于关系型数据库中Table的概念。类型是虚拟的逻辑分组,用来过滤 Document。

  • 通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。
  • 类型是文档的逻辑容器,类似于数据库中的表,类型在 Elasticsearch中表示一类相似的文档,每个类型中字段的定义称为映射。ES7.x已经将类型移除,7.x中一个索引只能有一个类型,默认为_doc。

6)文档(Document)

Index里面单条的记录称为 Document(文档),许多条 Document 构成了一个 Index。文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个非常常见的互联网数据交互格式。文档类似于关系型数据库中 Record/Row 的概念。

  • 一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。实际上一个文档除了用户定义的数据外,还包括 _index、_type 和 _id字段。

  • 同一个 Index 里面的 Document,不要求有相同的结构(scheme),但是最好保持相同,这样有利于提高搜索效率。

  • 在一个index/type里面,只要你想,你可以存储任意多的文档。

  • 注意:尽管一个文档物理上存在于一个索引之中,但文档必须被索引/赋予一个索引的type。type是虚拟的逻辑分组,用来过滤 Document。

7)文档元数据(Document metadata)

文档元数据为_index, _type, _id, 这三者可以唯一表示一个文档,_index表示文档在哪存放,_type表示文档的对象类别,_id为文档的唯一标识。

8)字段(Fields)

每个Document都类似一个JSON结构,它包含了许多字段,每个字段都有其对应的值,多个字段组成了一个 Document,可以类比关系型数据库数据表中的字段。

9)映射(mapping)

mapping映射, 就像数据库中的 schema ,定义索引中字段的名称、字段的数据类型(如 string, integer 或 date),设置字段倒排索引的相关配置。当索引文档遇到未定义的字段,会使用dynamic mapping 来确定字段的数据类型,并自动把新增加的字段添加到类型映射。在实际生产中一般或禁用dynamic mapping,避免过多的字段导致cluster state占用过多,同时禁止自动创建索引的功能,创建索引时必须提供Mapping信息或者通过Index Template创建。

10)分片和复制(shards & replicas)

一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。

  • 为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。

分片之所以重要,主要有两方面的原因:

  • 允许你水平分割/扩展你的内容容量。
  • 允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量。

至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为用户的你来说,这些都是透明的。

在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了。这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。

复制之所以重要,主要有两方面的原因:

  • 在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。
  • 扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行

总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制数量,但是不能改变分片的数量。

默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。一个索引的多个分片可以存放在集群中的一台主机上,也可以存放在多台主机上,这取决于你的集群机器数量。主分片和复制分片的具体位置是由ES内在的策略所决定的。

4、Elasticsearch与关系型数据库实例对比

4.1 创建实例过程

关系型数据库

关系型数据库创建一张 student 表,创建过程如下:

  • 创建学生数据库
  • 创建学生信息表(student)
  • 配置 student 表字段,如:姓名 name - vachar 类型、性别 sex - char 类型、年龄 age - int 类型
  • student 表的每一行表示一个学生信息,不同列表示这个学生不同的属性

ES

使用 ES 创建 student 索引,创建过程如下:

  • 配置 ES,启动一个 ES 实例(在 ES 中启动一个 ES 实例,这个实例就相当于数据库)
  • 创建学生信息索引(student)
  • 不需要配置字段属性,ES 会自动识别
  • 一个 json 字符串表示一个学生信息,json 字符串中包含学生属性的字段 Field

4.2 创建 Index 和 Table 对比

关系型数据库

关系型数据表使用 SQL 语句来创建数据表和数据,但需要提前定义好表结构和数据类型,创建数据表:

CREATE TABLE student(

    name varchar(20),

    sex char(5),

    age int

);

创建一条数据:

INSERT INTO student (`name`,`sex`,`age`) VALUES ('gala','male','22');

ES

ES 是基于 http 协议的,所以增删改查的接口都是基于 http 协议的,因此创建数据时,需要使用 ES 的 Rest API 才能够创建,只需要将 json 格式的学生信息数据利用 Rest API PUT 给 ES 接口创建数据,下面的操作是基于 ES 的可视化界面 Kibana 来操作的,使用 POST 的方式,索引是 student,操作是 _create 创建,这样就能自动创建好索引,并且自动识别各字段的数据类型。

POST student/_create/1

{

  "name":"gala",

  "sex":"male",

  "age":22

}

这样就可以轻松创建一个索引(Index)和一条数据了。

4.3 Document 和 Row 对比

关系型数据库

关系型数据表,Row 就是一行数据,每行数据是一条记录,查询 SQL 和结果如下:

select * from student;

image-1664246277622

ES

ES 中的数据记录的方式是 Document,数据格式是 json,因此查询返回的结果也是 json,查询 DSL 语句如下:

GET student/_search

查询结果:

{

  "took" : 44,

  "timed_out" : false,

  "_shards" : {

    "total" : 1,

    "successful" : 1,

    "skipped" : 0,

    "failed" : 0

  },

  "hits" : {

    "total" : {

      "value" : 1,

      "relation" : "eq"

    },

    "max_score" : 1.0,

    "hits" : [

      {

        "_index" : "student",

        "_type" : "_doc",

        "_id" : "1",

        "_score" : 1.0,

        "_source" : {

          "name" : "gala",

          "sex" : "male",

          "age" : 22

        }

      }

    ]

  }

}

4.4 Field 和 Column 对比

关系型数据库

关系型数据表每列(Column)代表一个属性,student 表的列数据格式如下:

image-1664246401994

ES

ES 的字段(Field)类型是自动创建的,比如会给 name 字段自定义为 string 类型,下图是在 Kibana 上创建索引模式之后可以方便看出该类索引的 Field 数据类型:

123123123123

4.5 Mapping 和 Schema 对比

关系型数据表的 Schema 说明表之间的关联结构,字段、主外键等关系,但 ES 是没有这么多复杂关系的,不存在主外键,表与表之间的相互联系,ES 是将 json 数据直接存在 ES 中,通过 Mapping 来查看具体数据结构.

查询 DSL 语句:

GET student/_mapping

查询结构:

{

  "student" : {

    "mappings" : {

      "properties" : {

        "age" : {

          "type" : "long"

        },

        "name" : {

          "type" : "text",

          "fields" : {

            "keyword" : {

              "type" : "keyword",

              "ignore_above" : 256

            }

          }

        },

        "sex" : {

          "type" : "text",

          "fields" : {

            "keyword" : {

              "type" : "keyword",

              "ignore_above" : 256

            }

          }

        }

      }

    }

  }

}

4.6 DSL 和 SQL 对比

上面的查询用到了 DSL 和 SQL 语句,两者都是一种语法,SQL 针对关系型数据表的,DSL 针对 ES,两者的语法有较大的区别,但应用场景非常相似,比如两者都有“增删改查”等基础功能。在这里不在赘述,后面的学习中会很频繁使用 DSL 语句,届时再详细介绍。

0

评论区