Elasticsearch介绍

什么是搜索

  • 我们比如说想找寻任何的信息的时候,就会去上百度搜索一下,比如搜一本书,一部电影(提到搜索的第一印象)
  • 互联网的搜索,电商网站,各种APP
  • IT系统的搜索,OA软件

如果用数据库做搜索会怎么样

  • 做软件开发的话,或者对IT,计算机有一定了解的话,都知道,数据都是存储在数据库里面的,比如说电商网站的商品信息,招聘网站的职位信息,新闻网站的新闻信息
  1. 比方说,每条记录的指定字段的文本,可能会很长,比如说"商品描述"字段的长度,有长达数千个,甚至数万个字符,这个时候,每次都要对每条记录的所有文本进行扫描,来判断说,你包不包含我指定的这个关键词,比如说:牙膏
  2. 还不能将搜索词拆分开来,尽可能去搜索更多的符合你的期望的结果,比如说:输入生化机,就搜不出来生化危机用数据库来实现搜索,是不太靠谱的,通常来说,性能会很差

什么是全文检索和Lucene

  • lucene,就是一个jar包,里面包含了封装好的各种建立倒排索引,以及进行搜索的代码,包含各种算法,我们就用java开发的时候,引入lucene jar,然后基于lucene的api去进行开发就可以了,我们就可以将已有的数据数据建立索引,lucene会在本地磁盘上面,给我们组织索引的数据结构.另外的话,我们也可以用lucene提供的的功能和api来针对磁盘上的索引数据,进行搜索.

QQ图片20200528101315.png

Elasticsearch的功能

  1. 分布式搜索和分析引擎
  2. 全文检索,结构化检索,数据分析
  3. 对海量数据进行近实时的处理
  • 分布式:ES自动可以将海量数据分散到多台服务器上存储和检索
  • 海量数据的处理:分布式以后,就可以采用大量的服务器去存储和检索数据,自然而然就可以实现海量数据的处理了.跟分布式/海量数据相反的,lucene,单机应用,只能在单台服务器上使用,最多只能处理单台服务器可以处理的数据量.
  • 近实时:在秒级别对数据进行搜索和分析

Elasticsearch的适用场景

  1. 维基百科,全文检索,高亮,搜索推荐
  2. 新闻网站,用户日志+社交网络数据,分析
  3. Stack Overflow(国外的程序异常讨论论坛),全文检索,搜索相关问题和答案
  4. GitHub(开源代码管理),搜索上亿行代码
  5. 电商网站,检索商品
  6. 日志数据分析,logstash采集日志,ES进行复杂的数据分析
  7. 商品价格监控网站,用户设定某商品的价格阈值,当低于该阈值的时候,发视消息给用户
  8. BI系统,ES执行数据分析和挖掘,Kibana进行数据可视化
  9. 国内,站内搜索(电商,招聘,门户)
  10. BI 系统,商业智能,分析用户消费趋势和用户群体的组成构成

Elasticsearch的特点

  1. 可以作为一个大型分布式集群(数百台服务器)技术,处理PB级数据,服务大公司,也可以运行在单机上,服务小公司
  2. Elasticsearch不是什么新技术,主要是将全文检索,数据分析以及分布式技术,合并在一起,才形成了独一无二的ES,lucene(全文检索)
  3. 对用户而言,是开箱即用的,非常简单,作为中小型的应用,直接3分钟部署一下ES,就可以作为生产环境的系统来使用了,数据量不大,操作不是太复杂
  4. 数据库的功能面对很多领域是不够的,优势:事务,各种联机事务型的操作,特殊的功能,比如全文检索,同义词处理,相关度排名,复杂数据分析,海量数据的近实时处理,Elasticsearch作为传统数据库的一个补充,提供了数据库所不能提供的很多功能

Elasticsearch安装

安装方式

安装方式 优点 缺点
docker 1.部署方便
2.开箱即用
3.启动迅速
1.需要有docker的知识
2.修改配置麻烦,需要重新生成镜像
3.数据存储需要挂载目录
tar 1.部署灵活
2.对系统的侵占性小
1.需要自己写启动管理文件
2.目录提前需要规划好
rpm|deb 1.部署方便
2.启动脚本安装即用
3.存放目录标准化
1.软件各个组件分散在不同的目录
2.卸载可能不干净
3.默认配置需要修改
ansible 1.极其的灵活
2.你想要的功能都有
3.批量部署速度快
1.需要学习ansible语法和规则
2.需要提前规划好所有的标准
3.需要专人维护

Elasticsearch安装部署

#db01
### 安装java
yum install -y java-1.8.0-openjdk.x86_64 

### 下载安装软件
mkdir -p /data/es_soft/
cd /data/es_soft/
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.6.0.rpm
rpm -ivh elasticsearch-6.6.0.rpm

### 配置启动
systemctl daemon-reload
systemctl enable elasticsearch.service
systemctl start elasticsearch.service
systemctl status elasticsearch.service

### 检查是否启动成功
ps -ef|grep elastic
lsof -i:9200
netstat -luntp|grep 9200
tail -f /var/log/elasticsearch/elasticsearch.log

Elasticsearch目录文件说明

#查看elasticsearch软件安装了哪些目录
rpm -ql elasticsearch
#查看elasticsearch的所有配置文件
rpm -qc elasticsearch
  • /etc/elasticsearch/elasticsearch.yml : 配置文件
  • /etc/elasticsearch/jvm.options : jvm虚拟机配置文件
  • /etc/init.d/elasticsearch : init启动文件
  • /etc/sysconfig/elasticsearch : 环境变量配置文件
  • /usr/lib/sysctl.d/elasticsearch.conf : sysctl变量文件修改最大描述符
  • /usr/lib/systemd/system/elasticsearch.service : systemd启动文件
  • /var/lib/elasticsearch : 数据目录
  • /var/log/elasticsearch : 日志目录
  • /var/run/elasticsearch : pid目录

Elasticsearch配置

  • /etc/elasticsearch/elasticsearch.yml
#db01
#以下为修改后有效内容
node.name: node-1
path.data: /data/elasticsearch
path.logs: /var/log/elasticsearch
#设置内存锁定(提前占用内存)
bootstrap.memory_lock: true
network.host: 10.0.0.51,127.0.0.1
http.port: 9200

创建数据目录并修改归属

mkdir -p /data/elasticsearch
chown -R elasticsearch.elasticsearch /data/elasticsearch
  • /etc/elasticsearch/jvm.options
################################################################
## IMPORTANT: JVM heap size
################################################################
##
## You should always set the min and max JVM heap
## size to the same value. For example, to set
## the heap to 4 GB, set:
##
## -Xms4g
## -Xmx4g
##
## See https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html
## for more information
##
################################################################

# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space
#占用内存调整为实际内存的一半,要给系统和其他软件预留内存
-Xms1g
-Xmx1g
  • 内存设置不要超过32g
  • 最大最小内存设置一样
  • 配置文件锁定内存
  • 至少给服务器本身空余50%的内存

修改完配置文件后我们需要重启

QQ截图20200528115207.jpg

#编辑
systemctl edit elasticsearch.service

#添加以下内容
[Service]
LimitMEMLOCK=infinity

#保存退出,重新加载文件,重启
systemctl daemon-reload
systemctl restart elasticsearch.service

Elasticsearch术语及概念

  • 索引词

在elastiasearch中索引词(term)是一个能够被索引的精确值.foo,Foo,FOO几个单词是不同的索引词.索引词(term)是可以通过term查询进行准确的搜索

  • 文本(text)

文本是一段普通的非结构化文字.通常,文本会被分拆成一个个的索引词,存储在elasticsearch的索引库中.为了让文本能够进行搜索,文本字段需要事先进行分析了;当对文本中的关键词进行查询的时候,搜索引擎应该根据搜索条件搜索出原文本.

  • 分析(analysis)

分析是将文本转换为索引词的过程,分析的结果依赖于分词器.比如:FOO BAR,Foo-Bar和foo bar这几个词有可能会被分析成相同的索引词foo和bar,这些索引词存储在Elasticsearch的索引库中.

  • 集群(cluster)

集群由一个或多个节点组成,对外提供服务,对外提供索引和搜索功能.在所有节点,一个集群有一个唯一的名称默认为elasticsearch.此名称是很重要的,因为每个节点只能是集群的一部分,当该节点被设置为相同的集群名称时,就会自动加入集群.当需要有多个集群的时候,要确保每个集群的名称不能重复,否则节点可能会加入到错误的集群.请注意,一个节点只能加入到一个集群.此外,你还可以拥有多个独立的集群,每个集群都有其不同的集群名称

  • 节点(node)

一个节点是一个逻辑上独立的服务,它是集群的一部分,可以存储数据,并参与集群的索引和搜索功能.就像集群一样,节点也有唯一的名字,在启动的时候分配.如果你不想要默认名称,你可以定义任何你想要的节点名.这个名字在理中很重要,在Elasticsearch集群通过节点名称进行管理和通信.一个节点可以被配置加入到一个特定的集群.默认情况下,每个节点会加人名为Elasticsearch的集祥中,这意味着如果你在网热动多个节点,如果网络畅通,他们能彼此发现井自动加人名为Elasticsearch 的一个集群中,你可以拥有多个你想要的节点.当网络没有集祥运行的时候,只要启动一个节点,这个节点会默认生成一个新的集群,这个集群会有一个节点.

  • 分片(shard)

分片是单个Lucene 实例,这是Elasticsearch管理的比较底层的功能.索引是指向主分片和副本分片的逻辑空间. 对于使用,只需要指定分片的数量,其他不需要做过多的事情.在开发使用的过程中,我们对应的对象都是索引,Elasticsearch 会自动管理集群中所有的分片,当发生故障的时候,Elasticsearch 会把分片移动到不同的节点或者添加新的节点.一个索引可以存储很大的数据,这些空间可以超过一个节点的物理存储的限制.例如,十亿个文档占用磁盘空间为1TB.仅从单个节点搜索可能会很慢,还有一台物理机器也不一定能存储这么多的数据.为了解决这一问题,Elasticsearch将索引分解成多个分片.当你创建一个索引,你可以简单地定义你想要的分片数量.每个分片本身是一个全功能的、独立的单元,可以托管在集群中的任何节点.

  • 主分片

每个文档都存储在一个分片中,当你存储一个文档的时候,系统会首先存储在主分片中,然后会复制到不同的副本中.默认情况下,一个索引有5个主分片. 你可以事先制定分片的数量,当分片一旦建立,则分片的数量不能修改.

  • 副本分片

每一个分片有零个或多个副本.副本主要是主分片的复制,其中有两个目的.增加高可用性:当主分片失败的时候,可以从副本分片中选择一个作为主分片.提高性能:当查询的时候可以到主分片或者副本分片中进行查询.默认情況下,一个主分片配有一个副本,但副本的数量可以在后面动态地配置增加.副本分片必部署在不同的节点上,不能部署在和主分片相同的节点上.   分片主要有两个很重要的原因,允许水平分割扩展数据和允许分配和井行操作(可能在多个节点上)从而提高性能和吞吐量. 这些很强大的功能对用户来说是透明的,你不需要做什么操作,系统会自动处理.

  • 索引(index)

索引是具有相同结构的文档集合.例如,可以有一个客户信息的索引,包括一个产品目录的索引,一个订单数据的索引. 在系统上索引的名字全部小写,通过这个名字可以用来执行索引、搜索、更新和删除操作等.在单个集群中,可以定义多个你想要的索引.

  • 类型(type)

在索引中,可以定义一个或多个类型,类型是索引的逻辑分区.在一般情况下,一种类型被定义为具有一组公共字段的文档.例如,让我们假设你运行一个博客平台,并把所有的数据存储在一个索引中.在这个索引中,你可以定义一种类型为用户数据,一种类型为博客数据,另一种类型为评论数据.

  • 文档(doc)

文档是存储在Elasticsearch中的一个JSON格式的字符串.它就像在关系数据库中表的一行.每个存储在索引中的一个文档都有一个类型和一个ID,每个文档都是一个JSON对象,存储了零个或者多个字段,或者键值对.原始的JSON 文档假存储在一个叫作Sour的字段中.当搜索文档的时候默认返回的就是这个字段.

  • 映射

映射像关系数据库中的表结构,每一个索引都有一个映射,它定义了索引中的每一个字段类型,以及一个索引范围内的设置.一个映射可以事先被定义,或者在第一次存储文档的时候自动识别.

  • 字段

文档中包含零个或者多个字段,字段可以是一个简单的值(例如字符串、整数、日期),也可以是一个数组或对象的嵌套结构.字段类似于关系数据库中表的列.每个字段都对应一个字段类型,例如整数、字符串、对象等.字段还可以指定如何分析该字段的值.

  • 主键

ID是一个文件的唯一标识,如果在存库的时候没有提供ID,系统会自动生成一个ID,文档的 index/type/id必须是唯一的.

  • 复制

复制是一个非常有用的功能,不然会有单点问题.当网络中的某个节点出现问题的时候,复制可以对故障进行转移,保证系统的高可用.因此,Elasticsearch 允许你创建一个或多个拷贝,你的索引分片就形成了所谓的副本或副本分片.

复制提供了高可用性,当节点失败的时候不受影响.需要注意的是,一个复制的分片不会存储在同一个节点中.它允许你扩展搜索量,提高并发量,因为搜索可以在所有副本上并行执行.每个索引可以拆分成多个分片.索引可以复制零个或者多个分片.一旦复制,每个索引就有了主分片和副本分片.分片的数量和副本的数量可以在创建索引时定义.当创建索引后,你可以随时改变副本的数量,但你不能改变分片的数量.默认情況下,每个索引分配5个分片和一个副本,这意味着你的集群节点至少要有两个节点,你将拥有5个主要的分片和5个副本分片共计10个分片.每个Elasticsearch分片是一个Lucene 的索引.有文档存储数量限制,你可以在一个单一的Lucene索引中存储的最大值为lucene-5843,极限是2147483519(=integer.max_value-128)个文档.你可以使用cat/shards API监控分片的大小.

Elasticsearch交互

curl命令

所有其他语言可以使用RESTful API通过端口9200和Elasticsearch进行通信,你可以用web客户端访问Elasticsearch.事实上,你甚至可以使用curl命令和Elasticsearch交互

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
  • VERB : 适当的HTTP方法GET,POST,PUT,HEAD或者DELETE
  • PROTOCOL : http或者https(如果你在Elasticsearch前面有一个https`代理)
  • HOST : Elasticsearch集群中任意节点的主机名,或者用localhost代表本地机器上的节点
  • PORT : 运行Elasticsearch HTTP服务的端口号,默认是9200
  • PATH : API的终端路径(例如_count将返回集群中文档数量).Path可能包含多个组件,例如_cluster/stats_nodes/stats/jvm
  • QUERY_STRING : 任意可选的查询字符串参数(例如pretty将格式化地输出JSON返回值,使其更容易阅读)
  • BODY : 一个JSON格式的请求体(如果请求需要的话)

es-head插件

以谷歌浏览器为例,打开以下地址(所有chrome内核的浏览器都适用)

#扩展程序
chrome://extensions/

QQ截图20200528145047.jpg

  • 开启开发者模式,将解压以后的文件夹导入,浏览器地址栏结尾处会出现图标点击使用
  • es-head-0.1.4_0.crx.zip

QQ截图20200528145318.jpg

  • 连接成功

QQ图片20200528145601.png

Elasticsearch API应用

创建索引

[root@db01 es_soft]# curl -XPUT '10.0.0.51:9200/vipinfo?pretty'
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "vipinfo"
}

创建索引以后,查看插件会显示刚才创建的索引,集群健康值因为默认配置不满足变成黄色

QQ图片20200528150146.png

插入文档数据

[root@db01 es_soft]# curl -XPUT '10.0.0.51:9200/vipinfo/user/1?pretty' -H 'Content-Type: application/json' -d'
> {
>     "first_name" : "John",
>     "last_name": "Smith",
>     "age" : 25,
>     "about" : "I love to go rock climbing", "interests": [ "sports", "music" ]
> }'
{
  "_index" : "vipinfo",
  "_type" : "user",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}
[root@db01 es_soft]# curl -XPUT  '10.0.0.51:9200/vipinfo/user/2?pretty' -H 'Content-Type: application/json' -d' {
> "first_name": "Jane",
> "last_name" : "Smith",
> "age" : 32,
> "about" : "I like to collect rock albums", "interests": [ "music" ]
> }'
{
  "_index" : "vipinfo",
  "_type" : "user",
  "_id" : "2",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}
[root@db01 es_soft]# curl -XPUT  '10.0.0.51:9200/vipinfo/user/3?pretty' -H 'Content-Type: application/json' -d' {
> "first_name": "Douglas", "last_name" : "Fir",
> "age" : 35,
> "about": "I like to build cabinets", "interests": [ "forestry" ]
> }'
{
  "_index" : "vipinfo",
  "_type" : "user",
  "_id" : "3",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

查看结果

QQ图片20200528151303.png

查询操作

按索引查询

[root@db01 es_soft]# curl -XGET 10.0.0.51:9200/vipinfo/user/_search?pretty
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 3,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "vipinfo",
        "_type" : "user",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "first_name" : "Jane",
          "last_name" : "Smith",
          "age" : 32,
          "about" : "I like to collect rock albums",
          "interests" : [
            "music"
          ]
        }
      },
      {
        "_index" : "vipinfo",
        "_type" : "user",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "first_name" : "John",
          "last_name" : "Smith",
          "age" : 25,
          "about" : "I love to go rock climbing",
          "interests" : [
            "sports",
            "music"
          ]
        }
      },
      {
        "_index" : "vipinfo",
        "_type" : "user",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "first_name" : "Douglas",
          "last_name" : "Fir",
          "age" : 35,
          "about" : "I like to build cabinets",
          "interests" : [
            "forestry"
          ]
        }
      }
    ]
  }
}

查询指定文档数据

[root@db01 es_soft]# curl -XGET '10.0.0.51:9200/vipinfo/user/1?pretty'
{
  "_index" : "vipinfo",
  "_type" : "user",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "first_name" : "John",
    "last_name" : "Smith",
    "age" : 25,
    "about" : "I love to go rock climbing",
    "interests" : [
      "sports",
      "music"
    ]
  }
}

按条件查询文档数据

#查询索引中符合条件的数据:搜索姓氏为Smith的雇员
[root@db01 es_soft]# curl -XGET '10.0.0.51:9200/vipinfo/user/_search?q=last_name:Smith&pretty'
{
  "took" : 48,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "vipinfo",
        "_type" : "user",
        "_id" : "2",
        "_score" : 0.2876821,
        "_source" : {
          "first_name" : "Jane",
          "last_name" : "Smith",
          "age" : 32,
          "about" : "I like to collect rock albums",
          "interests" : [
            "music"
          ]
        }
      },
      {
        "_index" : "vipinfo",
        "_type" : "user",
        "_id" : "1",
        "_score" : 0.2876821,
        "_source" : {
          "first_name" : "John",
          "last_name" : "Smith",
          "age" : 25,
          "about" : "I love to go rock climbing",
          "interests" : [
            "sports",
            "music"
          ]
        }
      }
    ]
  }
}

#使用Query-string查询
[root@db01 es_soft]# curl -XGET '10.0.0.51:9200/vipinfo/user/_search?pretty' -H 'Content-Type: application/json' -d '
> {
>   "query" : { 
>     "match" : {
>         "last_name" : "Smith"
>      }
>   } 
> }'
{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "vipinfo",
        "_type" : "user",
        "_id" : "2",
        "_score" : 0.2876821,
        "_source" : {
          "first_name" : "Jane",
          "last_name" : "Smith",
          "age" : 32,
          "about" : "I like to collect rock albums",
          "interests" : [
            "music"
          ]
        }
      },
      {
        "_index" : "vipinfo",
        "_type" : "user",
        "_id" : "1",
        "_score" : 0.2876821,
        "_source" : {
          "first_name" : "John",
          "last_name" : "Smith",
          "age" : 25,
          "about" : "I love to go rock climbing",
          "interests" : [
            "sports",
            "music"
          ]
        }
      }
    ]
  }
}


#使用过滤器查询
#搜索姓氏为 Smith 的雇员,但这次我们只需要年龄大于30的
#查询需要稍作调整,使用过滤器 filter,它支持高效地执行一个结构化查询
[root@db01 es_soft]# curl -XGET '10.0.0.51:9200/vipinfo/user/_search?pretty' -H 'Content-Type: application/json' -d '{
>   "query" : {
>     "bool": {
>       "must": {
>         "match" : {
>           "last_name" : "smith"
>           }
>      },
>      "filter": {
>         "range" : {"age" : { "gt" : 30 }
>           }
>         }
>       }
>     }
>  }'
{
  "took" : 13,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "vipinfo",
        "_type" : "user",
        "_id" : "2",
        "_score" : 0.2876821,
        "_source" : {
          "first_name" : "Jane",
          "last_name" : "Smith",
          "age" : 32,
          "about" : "I like to collect rock albums",
          "interests" : [
            "music"
          ]
        }
      }
    ]
  }
}

使用插件查询

QQ图片20200528152901.png

更新数据

#PUT更新,需要填写完整的信息
[root@db01 es_soft]# curl -XPUT '10.0.0.51:9200/vipinfo/user/1?pretty' -H 'Content-Type: application/json' -d'
> {
>     "first_name" : "John",
>     "last_name": "Smith",
>     "age" : 27,
>     "about" : "I love to go rock climbing", "interests": [ "sports", "music" ]
> }'
{
  "_index" : "vipinfo",
  "_type" : "user",
  "_id" : "1",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

删除数据

#删除指定文档数据
[root@db01 es_soft]# curl -XDELETE '10.0.0.51:9200/vipinfo/user/1?pretty'
{
  "_index" : "vipinfo",
  "_type" : "user",
  "_id" : "1",
  "_version" : 5,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 4,
  "_primary_term" : 1
}

#删除索引
[root@db01 es_soft]# curl -XDELETE '10.0.0.51:9200/vipinfo?pretty'
{
  "acknowledged" : true
}