Elasticsearch入门、Kibana 索引管理(elasticserch-head 插件使用, Kibanan 安装和使用)

目录

一、搜索的介绍

二、全文检索的介绍

三、ELK日志协议栈

1、ELK协议栈基本介绍

四、Elasticsearch介绍

1、什么是ElasticSearch

2、ElasticSearch使用案例

3、ElasticSearch对比Solr

4、ElasticSearch架构图以及基本概念(术语)

1、es概述

2、ES架构模块

3、Elasticsearch核心概念

五、ES的集群部署

六、node01服务器安装elasticsearch-head插件

1 、node01机器安装nodejs

2 、node01机器安装 elasticsearch-head 插件

七、node01服务器安装Kibana

八、使用kibana管理索引

1、使用 Xput创建索引

2、返回值说明

1、Hits

2、took

3、Shard

4、timeout

3、花式查询

4、索引映射(mappings)管理

1、为什么要映射

2、基本命令

3、获取映射字段

5、索引库配置管理(settings)

1、 索引库配置

2、 零停机重新索引数据

九、分页解决方案

1、导入数据

2、size+from浅分页

3、scroll深分页

十、三台机器安装IK分词器

十一、分片交互过程

1、创建索引

2、删除索引

3、查询索引


一、搜索的介绍

搜索是指搜寻检索,指代使用一定手段来检索到我们自己需要的信息,包括从文件当中检索,百度当中检索,网站内部搜索等等


二、全文检索的介绍

1、全文检索的需求介绍

首先我们谈几个公司,如雷贯耳的:百度、谷歌、维基百科;这些公司都有一个相似性就是门户网站,可以提供我们通过关键字搜索,然后快速的检索出我们想要的信息;

【网页百度展示】

比如我们检索传智播客,百度后台就会按照这个关键字进行查找(里面有搜索库,以及爬虫库),然后按照权重来进行从上到下的排序,给我们高亮的展示出现

【京东或者淘宝展示】

随便搜索东西,就会高精度的展示我们想要的;就会根据关键词进行海量数据的快速的检索

比如我们查找:”护手霜“ , 那么这期间内部会经过大体的:1、分词(护手,手霜,护等)2、根据这些词去海量的数据中检索 3、然后根据权重把检索出来的信息进行排序展示给我们

【传统做法】

那么对于一般的公司,初期是没有那么多数据的,所以很多公司更倾向于使用传统的数据库:mysql;比如我们要查找关键字”华为“,那么查询的方式大概就是:select * from table where field like ‘%华为%’; 但是随着业务发展,数据会不断的膨胀,那么问题就来了;mysql单表查询能力即便经过了优化,它的极限也就是400W左右的数据量。而且还会经常出现查询超时的现象;

然后很多公司开始对数据库进行横向和纵向的扩容,开始进行数据库表的“拆分”:横向拆分和纵向拆分;但是即便这样操作,仍然会出现很多问题,比如:

1、数据库会出现单点故障问题,先天主从复制关系,于是增加了运维成本

2、因为对表的拆分,增加了后期维护的难度,同样也是增加了运维成本

3、即便做了大量的维护,但对于大数据的检索操作,依然很慢,完全达不到期望值

于是出现了lucene,全文检索的工具。但是lucene对外暴露出的可用接口对于开发人员来说,操作是非常的复杂,而且没有效率的;于是在lucene的基础上进一步的封装,有了一个叫做 solr 的高性能分布式检索服务框架,但是,solr有一个致命的缺点就是:在建立索引期间,solr的搜索能力会极度下降,这就在一定程度上造成了solr在实时索引上效率并不高;

最后,出现了一个叫做 elasticsearch的框架,同样是以 lucene 为基础,并且吸收了前两代的教训而开发出的分布式多用户能力的全文搜索引擎,并且 elasticsearch 是基于RESTful web接口进行发布的,那么这就意味着,我们开发人员操作起来更方便快捷;同时 ES 拓展节点方便,可用于存储和检索海量数据,接近实时搜索能力,自动发现节点、副本机制保障可用性。

2、非结构化数据查找方法

1:顺序扫描法(Serial Scanning) 
所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢。

2:全文检索(Full-text Search) 
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。 
这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。 虽然创建索引的过程也是非常耗时的,但是索引一旦创建就可以多次使用,全文检索主要处理的是查询,所以耗时间创建索引是值得的。

3如何实现全文检索

可以使用Lucene实现全文检索。Lucene是 apache下的一个开放源代码的全文检索引擎工具包(提供了Jar包,实现全文检索的类库)。它提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便地在目标系统中实现全文检索的功能。  
注意:Lucene只是一个引擎,只是一个工具包,如果使用Lucene开发全文检索功能,要记住Lucene是不能单独运行的

4lucene实现全文检索流程

1. 绿色表示索引过程,对要搜索的原始内容进行索引构建一个索引库,索引过程包括:确定原始内容即要搜索的内容→采集文档→创建文档→分析文档→索引文档。 
2. 红色表示搜索过程,从索引库中搜索内容,搜索过程包括:用户通过搜索界面→创建查询→执行搜索,从索引库搜索→渲染搜索结果。

从上面了解到的知识点也可看出,索引和搜索流程图也可表示为: 

                                        
 
总结:全文检索过程分为索引、搜索两个过程:

  • 索引 
    1. 从关系数据库中、互联网上、文件系统采集源数据(要搜索的目标信息),源数据的来源是很广泛的。
    2. 将源数据采集到一个统一的地方,要创建索引,将索引创建到一个索引库(文件系统)中,从源数据库中提取关键信息,从关键信息中抽取一个一个,词和源数据是有关联的。也即创建索引时,词和源数据有关联,索引库中记录了这个关联,如果找到了词就说明找到了源数据(http的网页、pdf电子书等……)。
  • 搜索 
    1. 用户执行搜索(全文检索)编写查询关键字。
    2. 从索引库中搜索索引,根据查询关键字搜索索引库中的一个一个词
    3. 展示搜索的结果。

5全文检索框架介绍

市面上全文检索的框架很多,较早期的一个框架就是lucene,基本上所有的全文检索的工作都交给lucene来实现,但是lucene最大的弊端就是API太原生,没有经过任何封装,不太好使用。所以后来出现一个叫做solr的框架,它也是基于lucene进行改造封装和包装,将服务端单独提取出来,客户端进行请求即可。

另外一个框架就是大名鼎鼎的elasticsearch了,es也是一个基于lucene打造的全文检索的框架,且一经推出就迅速被市场认可,市场占有率越来越多,现在首选的全文检索的框架基本就是ES了。


三、ELK日志协议栈

1、ELK协议栈基本介绍

1集中式日志系统

日志,对于任何系统来说都是及其重要的组成部分。面对如此海量的数据,又是分布在各个不同地方,如果我们需要去查找一些重要的信息,难道还是使用传统的方法,去登陆到一台台机器上查看?看来传统的工具和方法已经显得非常笨拙和低效了。于是,一些聪明人就提出了建立一套集中式的方法,把不同来源的数据集中整合到一个地方。

一个完整的集中式日志系统,是离不开以下几个主要特点的。

  • 收集-能够采集多种来源的日志数据
  • 传输-能够稳定的把日志数据传输到中央系统
  • 存储-如何存储日志数据
  • 分析-可以支持 UI 分析
  • 警告-能够提供错误报告,监控机制

2ELK 协议栈介绍及体系结构

                       

ELK 其实并不是一款软件,而是一整套解决方案,是三个软件产品的首字母缩写,Elasticsearch,Logstash 和 Kibana。这三款软件都是开源软件,通常是配合使用,而且又先后归于 Elastic.co 公司名下,故被简称为 ELK 协议栈。

  Elasticsearch

      ES 是一个实时的分布式搜索和分析引擎,它可以用于全文搜索,结构化搜索以及分析。它是一个建立在全文搜索引擎 Apache Lucene 基础上的搜索引擎,使用 Java 语言编写。   

   主要特点:

  •  实时分析
  • 分布式实时文件存储,并将每一个字段都编入索引
  • 文档导向,所有的对象全部是文档
  • 高可用性,易扩展,支持集群(Cluster)、分片和复制(Shards 和 Replicas)。见图 2 和图 3
  • 接口友好,支持 JSON                   

 Logstash

       Logstash是一个具有实时渠道能力的数据收集引擎(像 flume)。使用 JRuby 语言编写。其作者是世界著名的运维工程师乔丹西塞 (JordanSissel)。

  主要特点

  • 几乎可以访问任何数据
  • 可以和多种外部应用结合
  • 支持弹性扩展

它由三个主要部分组成

  • Shipper-发送日志数据
  • Broker-收集数据,缺省内置 Redis
  • Indexer-数据写入

Kibana

       Kibnan是一款基于 Apache 开源协议,使用 JavaScript 语言编写,为 Elasticsearch 提供分析和可视化的 Web 平台。它可以在 Elasticsearch 的索引中查找,交互数据,并生成各种维度的表图。

3Elk整体架构

        

4参考文档

ELK官网

ELK官网文档

ELK中文手册

ELK中文社区


四、Elasticsearch介绍

1什么是ElasticSearch

Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。es也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

2ElasticSearch使用案例

  • 2013年初,GitHub抛弃了Solr,采取ElasticSearch 来做PB级的搜索。 “GitHub使用ElasticSearch搜索20TB的数据,包括13亿文件和1300亿行代码”
  • 维基百科:启动以elasticsearch为基础的核心搜索架构
  • SoundCloud:“SoundCloud使用ElasticSearch为1.8亿用户提供即时而精准的音乐搜索服务”
  • 百度:百度目前广泛使用ElasticSearch作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部20多个业务线(包括casio、云分析、网盟、预测、文库、直达号、钱包、风控等),单集群最大100台机器,200个ES节点,每天导入30TB+数据
  • 新浪使用ES 分析处理32亿条实时日志
  • 阿里使用ES 构建挖财自己的日志采集和分析体系

3ElasticSearch对比Solr

  • Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
  • Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
  • Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;
  • Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch

4ElasticSearch架构图以及基本概念(术语)

1、es概述

Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。

Elasticsearch比传统关系型数据库如下:

Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices   -> Types  -> Documents -> Fields

2、ES架构模块

                                         

Gateway是 ES 用来存储索引的文件系统,支持多种类型。

Gateway的上层是一个分布式的 lucene 框架。

Lucene之上是ES的模块,包括:索引模块、搜索模块、映射解析模块等

ES模块之上是 Discovery、Scripting 和第三方插件。

Discovery 是 ES 的节点发现模块,不同机器上的ES节点要组成集群需要进行消息通信,集群内部需要选举master节点,这些工作都是由 Discovery 模块完成。支持多种发现机制,如 Zen 、EC2、gce、Azure。

Scripting用来支持在查询语句中插入javascript、python等脚本语言,scripting模块负责解析这些脚本,使用脚本语句性能稍低。ES也支持多种第三方插件。

再上层是ES的传输模块和JMX.传输模块支持多种传输协议,如 Thrift、memecached、http,默认使用http。JMX是java的管理框架,用来管理ES应用。

最上层是ES提供给用户的接口,可以通过RESTful接口和ES集群进行交互。

3Elasticsearch核心概念

1索引 index

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

2类型 type

在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。

3字段Field

相当于是数据表的字段,对文档数据根据不同属性进行的分类标识

4映射 mapping

mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等,这些都是映射里面可以设置的,其它就是处理es里面数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。

5文档 document

一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。

在一个index/type里面,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被赋予一个索引的 type。

6集群 cluster

一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。一个集群由一个唯一的名字标识,这个名字默认就是“elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群

7节点 node

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

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

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

8分片和复制 shards&replicas

一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。分片很重要,主要有两方面的原因:  1)允许你水平分割/扩展你的内容容量。  2)允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量。

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

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

复制之所以重要,有两个主要原因: 在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行。总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制的数量,但是你事后不能改变分片的数量。

默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。


五、ES的集群部署

第一步创建普通用户

注意ES不能使用root用户启动,必须使用普通用户安装启动。这里我们创建一个普通用户以及定义一些常规目录用于存放我们的数据文件以及安装包等

创建一个es专门的用户(必须

#使用root用户在三台机器执行以下命令

useradd es 
mkdir -p /export/servers/es
chown -R es /export/servers/es
passwd es

第二步:为普通用户es添加sudo权限

为了让普通用户有更大的操作权限,我们一般都会给普通用户设置sudo权限,方便普通用户的操作

三台机器使用root用户执行visudo命令然后为es用户添加权限

visudo
es      ALL=(ALL)       ALL

第三步:下载并上传压缩包,然后解压

将es的安v装包下载并上传到node01服务器的/home/es路径下,然后进行解压

使用es用户来执行以下操作(断开连接linux的工具,然后重新使用es用户连接三台linux服务器

node01服务器使用es用户执行以下命令

cd /home/es/
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.7.0.tar.gz
tar -zxf elasticsearch-6.7.0.tar.gz -C /export/servers/es/

第四步:修改配置文件

修改elasticsearch.yml

node01服务器使用es用户来修改配置文件

cd /export/servers/es/elasticsearch-6.7.0/config
mkdir -p /export/servers/es/elasticsearch-6.7.0/logs
mkdir -p /export/servers/es/elasticsearch-6.7.0/datas
rm -rf elasticsearch.yml
vim elasticsearch.yml
cluster.name: myes
node.name: node01
path.data: /export/servers/es/elasticsearch-6.7.0/datas
path.logs: /export/servers/es/elasticsearch-6.7.0/logs
network.host: 192.168.52.100
http.port: 9200
discovery.zen.ping.unicast.hosts: ["node01", "node02", "node03"]i
bootstrap.system_call_filter: false
bootstrap.memory_lock: false
http.cors.enabled: true
http.cors.allow-origin: "*"

修改 jvm.option

修改 jvm.option配置文件,调整 jvm 堆内存大小

node01使用 es 用户执行以下命令调整 jvm 堆内存大小,每个人根据自己服务器的内存大小来进行调整

cd /export/servers/es/elasticsearch-6.7.0/config
vim jvm.options
-Xms2g
-Xmx2g

第五步:将安装包分发到其他服务器上面

node01使用 es 用户将安装包分发到其他服务器上面去

cd /export/servers/es/
scp -r elasticsearch-6.7.0/ node02:$PWD
scp -r elasticsearch-6.7.0/ node03:$PWD

第六步:node02node03修改es配置文件

node02与node03也需要修改es配置文件

node02使用es用户执行以下命令修改es配置文件

cd /export/servers/es/elasticsearch-6.7.0/config
vim elasticsearch.yml
cluster.name: myes
node.name: node02
path.data: /export/servers/es/elasticsearch-6.7.0/datas
path.logs: /export/servers/es/elasticsearch-6.7.0/logs
network.host: 192.168.52.110
http.port: 9200
discovery.zen.ping.unicast.hosts: ["node01", "node02", "node03"]
bootstrap.system_call_filter: false
bootstrap.memory_lock: false
http.cors.enabled: true
http.cors.allow-origin: "*"

node03使用es用户执行以下命令修改配置文件

cd /export/servers/es/elasticsearch-6.7.0/config/
vim elasticsearch.yml
cluster.name: myes
node.name: node03
path.data: /export/servers/es/elasticsearch-6.7.0/datas
path.logs: /export/servers/es/elasticsearch-6.7.0/logs
network.host: 192.168.52.120
http.port: 9200
discovery.zen.ping.unicast.hosts: ["node01", "node02", "node03"]
bootstrap.system_call_filter: false
bootstrap.memory_lock: false
http.cors.enabled: true
http.cors.allow-origin: "*"

第七步修改系统配置解决启动时候的问题

由于现在使用普通用户来安装es服务,且es服务对服务器的资源要求比较多,包括内存大小,线程数等。所以我们需要给普通用户解开资源的束缚。

解决启动问题一普通用户打开文件的最大数限制

问题错误信息描述

max file descriptors [4096] for elasticsearch process likely too low, increase to at least [65536]

ES因为需要大量的创建索引文件,需要大量的打开系统的文件,所以我们需要解除linux系统当中打开文件最大数目的限制,不然ES启动就会抛错

三台机器使用es用户执行以下命令解除打开文件数据的限制

sudo vi /etc/security/limits.conf

添加如下内容: 注意*不要去掉了

* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096

解决启动问题二:普通用户启动线程数限制

问题错误信息描述

max number of threads [1024] for user [es] likely too low, increase to at least [4096]

修改普通用户可以创建的最大线程数

max number of threads [1024] for user [es] likely too low, increase to at least [4096]
原因:无法创建本地线程问题,用户最大可创建线程数太小
解决方案:修改90-nproc.conf 配置文件。

三台机器使用es用户执行以下命令修改配置文件

sudo vi /etc/security/limits.d/90-nproc.conf
找到如下内容:
* soft nproc 1024
#修改为
* soft nproc 4096

解决启动问题三:普通用户调大虚拟内存

错误信息描述:

max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]

调大系统的虚拟内存

原因:最大虚拟内存太小

每次启动机器都手动执行下。

三台机器执行以下命令,注意每次启动ES之前都要执行

sudo  sysctl -w vm.max_map_count=262144

备注:以上三个问题解决完成之后,重新连接secureCRT或者重新连接xshell生效 ,需要保存、退出、重新登录xshell才可生效。

第八步:启动ES服务

三台机器使用es用户执行以下命令启动es服务

nohup /export/servers/es/elasticsearch-6.7.0/bin/elasticsearch 2>&1 &

启动成功之后jsp即可看到es的服务进程,并且访问页面

http://node01:9200/?pretty

能够看到es启动之后的一些信息

注意:如果哪一台机器服务启动失败,那么就到哪一台机器的

/export/servers/es/elasticsearch-6.7.0/logs

这个路径下面去查看错误日志


六、node01服务器安装elasticsearch-head插件

由于es服务启动之后,访问界面比较丑陋,为了更好的查看索引库当中的信息,我们可以通过安装elasticsearch-head这个插件来实现,这个插件可以更方便快捷的看到es的管理界面

1 、node01机器安装nodejs

Node.js是一个基于 Chrome V8 引擎的 JavaScript 运行环境。

Node.js是一个Javascript运行环境(runtime environment),发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node.js 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。

安装步骤参考:https://www.cnblogs.com/kevingrace/p/8990169.html

第一步:下载安装包

node01机器执行以下命令下载安装包,然后进行解压

cd /home/es
wget https://npm.taobao.org/mirrors/node/v8.1.0/node-v8.1.0-linux-x64.tar.gz
tar -zxvf node-v8.1.0-linux-x64.tar.gz -C /export/servers/es/

第二步:创建软连接

node01执行以下命令创建软连接

sudo ln -s /export/servers/es/node-v8.1.0-linux-x64/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm

sudo ln -s /export/servers/es/node-v8.1.0-linux-x64/bin/node /usr/local/bin/node

第三步:修改环境变量

node01服务器添加环境变量

sudo vim /etc/profile
export NODE_HOME=/export/servers/es/node-v8.1.0-linux-x64
export PATH=:$PATH:$NODE_HOME/bin

修改完环境变量使用source生效

source /etc/profile

第四步:验证安装成功

node01执行以下命令验证安装生效

2 、node01机器安装 elasticsearch-head 插件

elasticsearch-head 这个插件是 es 提供的一个用于图形化界面查看的一个插件工具,可以安装上这个插件之后,通过这个插件来实现我们通过浏览器查看es当中的数据

安装 elasticsearch-head 这个插件这里提供两种方式进行安装,第一种方式就是自己下载源码包进行编译,耗时比较长,网络较差的情况下,基本上不可能安装成功

第二种方式就是直接使用我已经编译好的安装包,进行修改配置即可

1、第一种方式:在线安装elasticsearch-head插件(网速慢,不推荐

不做说明

2、第二种方式:直接使用提供的编译之后的源码包解压之后修改配置文件即可(强烈推荐

第一步:上传压缩包到 /home/es 路径下

将压缩包  elasticsearch-head-compile-after.tar.gz  上传到node01机器的 /home/es 路径下面去

第二步:解压安装包

node01执行以下命令解压安装包

第三步node01机器修改Gruntfile.js

修改 Gruntfile.js 这个文件:

​cd /export/servers/es/elasticsearch-head
vim Gruntfile.js
找到以下代码:
添加一行: hostname: '192.168.100.10',

connect: {
                        server: {
                              options: {
                                     hostname: '192.168.100.10',
                                     port: 9100,
                                     base: '.',
                                     keepalive: true
                                }
                        }
                }


​

第四步node01 机器修改 app.js

第一台机器修改app.js

cd /export/servers/es/elasticsearch-head/_site
vim app.js

更改前:http://localhost:9200
更改后:http://node01:9200

3node01机器启动 head 服务

node01启动 elasticsearch-head 插件

 cd /export/servers/es/elasticsearch-head/node_modules/grunt/bin/

进程前台启动命令

./grunt server

进程后台启动命令

nohup ./grunt server >/dev/null 2>&1 &


Running "connect:server" (connect) task
Waiting forever...
Started connect web server on http://192.168.52.100:9100

如何停止elasticsearch-head进程

执行以下命令找到 elasticsearch-head 的插件进程,然后使用kill  -9  杀死进程即可

netstat -nltp | grep 9100

kill -9 XXXX

 4、访问elasticsearch-head界面 

http://192.168.100.10:9100/


七、node01服务器安装Kibana

kibana的基本介绍

  • Kibana是一个开源的分析和可视化平台,设计用于和 Elasticsearch 一起工作;
  • 你用 Kibana 来搜索,查看,并和存储在 Elasticsearch 索引中的数据进行交互;
  • 你可以轻松地执行高级数据分析,并且以各种图标、表格和地图的形式可视化数据;
  • Kibana使得理解大量数据变得很容易。它简单的、基于浏览器的界面使你能够快速创建和共享动态仪表板,实时显示Elasticsearch查询的变化。

接着使用我们的 es 用户在 node01 服务器上面来实现我们的 kibana 的安装部署

第一步:下载资源上传服务器并解压

node01服务器使用 es 用户执行以下命令来下载安装包并解压

cd /home/es
在线下载
wget https://artifacts.elastic.co/downloads/kibana/kibana-6.7.0-linux-x86_64.tar.gz
tar -zxf kibana-6.7.0-linux-x86_64.tar.gz -C /export/servers/es/

第二步:修改配置文件

node01服务器使用 es 用户执行以下命令来修改配置文件

​
cd /export/servers/es/kibana-6.7.0-linux-x86_64/config/
vi kibana.yml

配置内容如下:

server.host: "node01"
elasticsearch.hosts: ["http://node01:9200"]

第三步:启动服务

node01服务器使用es用户执行以下命令启动kibana服务

cd /export/servers/es/kibana-6.7.0-linux-x86_64
nohup bin/kibana >/dev/null 2>&1 &

如何停止kibana进程:停止kibana服务进程

查看进程号

ps -ef | grep node

然后使用kill -9杀死进程即可

第四步:浏览器访问

浏览器地址访问kibana服务

http://node01:5601


 

八、使用kibana管理索引

curl是利用URL语法在命令行方式下工作的开源文件传输工具,使用curl可以简单实现常见的get/post请求。简单的认为是可以在命令行下面访问url的一个工具。在centos的默认库里面是有curl工具的,如果没有请yum安装即可。

curl

-X 指定 htt p的请求方法 有 HEAD GET POST PUT DELETE
-d 指定要传输的数据
-H 指定http请求头信息

1使用 Xput创建索引

1创建索引

在我们的kibana的dev tools当中执行以下语句

curl -XPUT http://node01:9200/blog01/?pretty

2插入文档

前面的命令使用  PUT  动词将一个文档添加到  /article(文档类型),并为该文档分配 ID 为1。URL  路径显示为index/doctype/ID(索引/文档类型/ID)。

curl -XPUT http://node01:9200/blog01/article/1?pretty -d  '{"id": "1", "title": "What is lucene"}'

问题:Content-Type header [application/x-www-form-urlencoded] is not supported

解决:

curl -XPUT http://node01:9200/blog01/article/1?pretty -d  '{"id": "1", "title": "What is lucene"}' -H "Content-Type: application/json"

原因:

此原因时由于ES增加了安全机制, 进行严格的内容类型检查,严格检查内容类型也可以作为防止跨站点请求伪造攻击的一层保护。 

3查询文档

curl -XGET http://node01:9200/blog01/article/1?pretty

问题:Content-Type header [application/x-www-form-urlencoded] is not supported

解决:

curl -XPUT http://node01:9200/blog01/article/1?pretty -d  '{"id": "1", "title": "What is lucene"}' -H "Content-Type: application/json"

curl -XGET http://node01:9200/blog01/article/1?pretty -H "Content-Type: application/json"

4更新文档

curl -XPUT http://node01:9200/blog01/article/1?pretty -d  '{"id": "1", "title": " What is elasticsearch"}'

问题:Content-Type header [application/x-www-form-urlencoded] is not supported

解决:

curl -XPUT http://node01:9200/blog01/article/1?pretty -d  '{"id": "1", "title": " What is elasticsearch"}' -H "Content-Type: application/json"

                                

5搜索文档

curl -XGET "http://node01:9200/blog01/article/_search?q=title:elasticsearch"

问题:Content-Type header [application/x-www-form-urlencoded] is not supported

解决:

curl -XGET "http://node01:9200/blog01/article/_search?q=title:'elasticsearch'&pretty" -H "Content-Type: application/json"

6删除文档

curl -XDELETE "http://node01:9200/blog01/article/1?pretty"

7删除索引

curl -XDELETE http://node01:9200/blog01?pretty

2返回值说明

1Hits

返回结果中最重要的部分是 hits ,它包含 total 字段来表示匹配到的文档总数,并且一个 hits 数组包含所查询结果的前十个文档。
在 hits 数组中每个结果包含文档的 _index 、 _type 、 _id ,加上 _source 字段。这意味着我们可以直接从返回的搜索结果中使用整个文档。这不像其他的搜索引擎,仅仅返回文档的ID,需要你单独去获取文档。
每个结果还有一个 _score ,它衡量了文档与查询的匹配程度。默认情况下,首先返回最相关的文档结果,就是说,返回的文档是按照 _score 降序排列的。在这个例子中,我们没有指定任何查询,故所有的文档具有相同的相关性,因此对所有的结果而言 1 是中性的 _score 。
max_score 值是与查询所匹配文档的 _score 的最大值。

2took

took 值告诉我们执行整个搜索请求耗费了多少毫秒

3Shard

_shards 部分 告诉我们在查询中参与分片的总数,以及这些分片成功了多少个失败了多少个。正常情况下我们不希望分片失败,但是分片失败是可能发生的。
如果我们遭遇到一种灾难级别的故障,在这个故障中丢失了相同分片的原始数据和副本,那么对这个分片将没有可用副本来对搜索请求作出响应。假若这样,Elasticsearch 将报告这个分片是失败的,但是会继续返回剩余分片的结果。

4timeout

timed_out 值告诉我们查询是否超时。默认情况下,搜索请求不会超时。 如果低响应时间比完成结果更重要,你可以指定 timeout 为 10 或者 10ms(10毫秒),或者 1s(1秒):
GET /_search?timeout=10ms
在请求超时之前,Elasticsearch 将会返回已经成功从每个分片获取的结果。

                             

3花式查询

在 kibana 提供的界面上进行操作。

POST /school/student/_bulk
{ "index": { "_id": 1 }}
{ "name" : "liubei", "age" : 20 , "sex": "boy", "birth": "1996-01-02" , "about": "i like diaocan he girl" }
{ "index": { "_id": 2 }}
{ "name" : "guanyu", "age" : 21 , "sex": "boy", "birth": "1995-01-02" , "about": "i like diaocan" }
{ "index": { "_id": 3 }}
{ "name" : "zhangfei", "age" : 18 , "sex": "boy", "birth": "1998-01-02" , "about": "i like travel" }
{ "index": { "_id": 4 }}
{ "name" : "diaocan", "age" : 20 , "sex": "girl", "birth": "1996-01-02" , "about": "i like travel and sport" }
{ "index": { "_id": 5 }}
{ "name" : "panjinlian", "age" : 25 , "sex": "girl", "birth": "1991-01-02" , "about": "i like travel and wusong" }
{ "index": { "_id": 6 }}
{ "name" : "caocao", "age" : 30 , "sex": "boy", "birth": "1988-01-02" , "about": "i like xiaoqiao" }
{ "index": { "_id": 7 }}
{ "name" : "zhaoyun", "age" : 31 , "sex": "boy", "birth": "1997-01-02" , "about": "i like travel and music" }
{ "index": { "_id": 8 }}
{ "name" : "xiaoqiao", "age" : 18 , "sex": "girl", "birth": "1998-01-02" , "about": "i like caocao" }
{ "index": { "_id": 9 }}
{ "name" : "daqiao", "age" : 20 , "sex": "girl", "birth": "1996-01-02" , "about": "i like travel and history" }

1、使用match_all做查询

GET /school/student/_search?pretty
{
    "query": {
        "match_all": {}
    }
}

问题:通过 match_all 匹配后,会把所有的数据检索出来,但是往往真正的业务需求并非要找全部的数据,而是检索出自己想要的;并且对于 es 集群来说,直接检索全部的数据,很容易造成GC现象。所以,我们要学会如何进行高效的检索数据

2、通过关键字段进行查询

GET /school/student/_search?pretty
{
    "query": {
         "match": {"about": "travel"}
     }
}

如果此时想查询喜欢旅游的,并且不能是男孩的,怎么办?

【这种方式是错误的,因为一个match下,不能出现多个字段值[match] query doesn't support multiple fields】,需要使用复合查询

3、bool的复合查询

当出现多个查询语句组合的时候,可以用 bool 来 包含。bool合并聚包含:must,must_not或者should, should表示or的意思

例子:查询非男性中喜欢旅行的人

GET /school/student/_search?pretty
{
"query": {
   "bool": {
      "must": { "match": {"about": "travel"}},
      "must_not": {"match": {"sex": "boy"}}
     }
  }
}

                        

4、bool的复合查询中的should

should 表示可有可无的(如果should匹配到了就展示,否则就不展示)

例子:

查询喜欢旅行的,如果有男性的则显示,否则不显示

GET /school/student/_search?pretty
{
"query": {
   "bool": {
      "must": { "match": {"about": "travel"}},
      "should": {"match": {"sex": "boy"}}         
     }
  }
}

5、term匹配

使用 term 进行精确匹配(比如数字,日期,布尔值或 not_analyzed的字符串(未经分析的文本数据类型))

语法
{ "term": { "age": 20 }}
{ "term": { "date": "2018-04-01" }}
{ "term": { "sex": “boy” }}
{ "term": { "about": "trivel" }}
例子:查询喜欢旅行的
GET /school/student/_search?pretty
{
"query": {
   "bool": {
      "must": { "term": {"about": "travel"}},
      "should": {"term": {"sex": "boy"}}         
     }}
}

6、使用terms匹配多个值

GET /school/student/_search?pretty
{
"query": {
   "bool": {
      "must": { "terms": {"about": ["travel","history"]}}          
     }
  }
}

term主要是用于精确的过滤比如说:”我爱你”

在 match 下面匹配可以为包含:我、爱、你、我爱等等的解析器

在 term 语法下面就精准匹配到:”我爱你”

7、Range过滤

Range过滤允许我们按照指定的范围查找一些数据:操作范围:gt::大于,gae::大于等于,lt::小于,lte::小于等于

例子:

查找出大于20岁,小于等于25岁的学生

GET /school/student/_search?pretty
{
"query": {
   "range": {
    "age": {"gt":20,"lte":25}
         }
      }
}

8、exists和 missing过滤

exists 和 missing 过滤可以找到文档中是否包含某个字段或者是没有某个字段

例子:

查找字段中包含age的文档

GET /school/student/_search?pretty
{
"query": {
   "exists": {
    "field": "age"  
         }
      }
}

9、bool的多条件过滤

用bool也可以像之前match一样来过滤多行条件:

must :: 多个查询条件的完全匹配,相当于 and 。
must_not :: 多个查询条件的相反匹配,相当于 not 。
should :: 至少有一个查询条件匹配, 相当于 or

例子:过滤出about字段包含travel并且年龄大于20岁小于30岁的同学

GET /school/student/_search?pretty
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "about": {
            "value": "travel"
          }
        }},{"range": {
          "age": { "gte": 20,"lte": 30
          }
        }}
      ]
    }
  }
}

10、查询与过滤条件合并

通常复杂的查询语句,我们也要配合过滤语句来实现缓存,用filter语句就可以来实现

例子:

查询出喜欢旅行的,并且年龄是20岁的文档

GET /school/student/_search?pretty
{
  "query": {
   "bool": {
     "must": {"match": {"about": "travel"}},     
     "filter": [{"term":{"age": 20}}]
     }
  }
}

4索引映射(mappings)管理

1为什么要映射

elasticsearch中的文档等价于 java 中的对象,那么在 java 对象中有字段(比如string、int、long等),同理在 elasticsearch 索引中的具体字段也是有类型的。

PUT /document/article/1
{
  "title" : "elasticsearchshi是是什么",
  "author" : "zhangsan",
  "titleScore" : 60
}

这种操作并没有指定字段类型,那么elasticsearch会自动根据数据类型的格式识别字段的类型;查看索引字段类型:GET /document/article/_mapping。可以发现titleScore的类型是long。

然后在插入一条数据:

PUT /document/article/2
{
  "title" : "elasticsearchshi是是什么",
  "author" : "zhangsan",
  "titleScore" : 66.666
}

查询数据:GET /document/article/2

我们会发现es能存入,并没有报错(注意),这其实是一个问题,因为如果后期elaticsearch对接java的时候,我们会写一个类对数据做封装,比如:

class Article{
     private String title;
     private String author;
     private String titleScore  //《什么类型合适》?如果使用 long 类型,那么后面肯定会有数据格式转换的异常 doublelong
}

所以,我们如果能提前知道字段类型,那么最好使用mapping的映射管理,提前指定字段的类型,防止后续的程序问题; 

DELETE  document
PUT document
{
  "mappings": {
    "article" : {
      "properties":
      {
        "title" : {"type": "text"} , 
        "author" : {"type": "text"} , 
        "titleScore" : {"type": "double"} 
      }
    }
  }
}
get document/article/_mapping

2基本命令

DELETE school

PUT school
{
  "mappings": {
    "logs" : {
      "properties": {"messages" : {"type": "text"}}
    }
  }

}

添加索引:school,文档类型类logs,索引字段为message ,字段的类型为text

GET /school/_mapping/logs

继续添加字段

POST /school/_mapping/logs
{
  "properties": {"number" : {"type": "text"}}
}

GET /school/_mapping/logs

3获取映射字段

语法:GET /{index}/_mapping/{type}/field/{field}

GET /school/_mapping/logs/field/number

5索引库配置管理(settings)

1 索引库配置

所谓的 settings 就是用来修改索引分片和副本数的;

比如有的重要索引,副本数很少甚至没有副本,那么我们可以通过 setting 来添加副本数

DELETE document
PUT document
{
  "mappings": {
    "article" : {
      "properties":
      {
        "title" : {"type": "text"} ,
        "author" : {"type": "text"} ,
        "titleScore" : {"type": "double"}
        
      }
    }
  }
}
GET /document/_settings

可以看到当前的副本数是1,那么为了提高容错性,我们可以把副本数改成2:

PUT /document/_settings
{
  "number_of_replicas": 2
}

副本可以改,分片不能改

PUT /document/_settings
{
  "number_of_shards": 3
}

2 零停机重新索引数据

实际生产,对于文档的操作,偶尔会遇到这种问题:

某一个字段的类型不符合后期的业务了,但是当前的索引已经创建了,我们知道 es 在字段的 mapping 建立后就不可再次修改 mapping 的值。

1新建索引库articles1,并添加数据

DELETE articles1
PUT articles1
{  
    "settings":{  
         "number_of_shards":3,  
         "number_of_replicas":1  
    },  
    "mappings":{  
         "article":{  
             "dynamic":"strict",  
             "properties":{  
                 "id":{"type": "text", "store": true},  
                 "title":{"type": "text","store": true}, 
                 "readCounts":{"type": "integer","store": true},  
                 "times": {"type": "text", "index": false}
             }  
         }  
    }  
}


PUT articles1/article/1
{
  "id" : "1",
  "title" : "世界1",
  "readCounts" : 2 , 
  "times" : "2018-05-01"
}

get articles1/article/1

2 新建索引库articles2

DELETE articles2
PUT articles2
{  
    "settings":{  
         "number_of_shards":5,  
         "number_of_replicas":1  
    },  
    "mappings":{  
         "article":{  
             "dynamic":"strict",  
             "properties":{  
                 "id":{"type": "text", "store": true},  
                 "title":{"type": "text","store": true}, 
                 "readCounts":{"type": "integer","store": true},  
                 "times": {"type": "date", "index": false}
             }  
         }  
    }  
}  

GET articles2/article/1

3拷贝数据并验证

​POST _reindex
{
  "source": {
    "index": "articles1"
  },
  "dest": {
    "index": "articles2"
  }
}

GET articles2/article/1

​

九、分页解决方案

1、导入数据

DELETE us
POST /_bulk
{ "create": { "_index": "us", "_type": "tweet", "_id": "1" }}
{ "email" : "[email protected]", "name" : "John Smith", "username" : "@john" }
{ "create": { "_index": "us", "_type": "tweet", "_id": "2" }}
{ "email" : "[email protected]", "name" : "Mary Jones", "username" : "@mary" }
{ "create": { "_index": "us", "_type": "tweet", "_id": "3" }}
{ "date" : "2014-09-13", "name" : "Mary Jones", "tweet" : "Elasticsearch means full text search has never been so easy", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "4" }}
{ "date" : "2014-09-14", "name" : "John Smith", "tweet" : "@mary it is not just text, it does everything", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "5" }}
{ "date" : "2014-09-15", "name" : "Mary Jones", "tweet" : "However did I manage before Elasticsearch?", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "6" }}
{ "date" : "2014-09-16", "name" : "John Smith",  "tweet" : "The Elasticsearch API is really easy to use", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "7" }}
{ "date" : "2014-09-17", "name" : "Mary Jones", "tweet" : "The Query DSL is really powerful and flexible", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "8" }}
{ "date" : "2014-09-18", "name" : "John Smith", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "9" }}
{ "date" : "2014-09-19", "name" : "Mary Jones", "tweet" : "Geo-location aggregations are really cool", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "10" }}
{ "date" : "2014-09-20", "name" : "John Smith", "tweet" : "Elasticsearch surely is one of the hottest new NoSQL products", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "11" }}
{ "date" : "2014-09-21", "name" : "Mary Jones", "tweet" : "Elasticsearch is built for the cloud, easy to scale", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "12" }}
{ "date" : "2014-09-22", "name" : "John Smith", "tweet" : "Elasticsearch and I have left the honeymoon stage, and I still love her.", "user_id" : 1 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "13" }}
{ "date" : "2014-09-23", "name" : "Mary Jones", "tweet" : "So yes, I am an Elasticsearch fanboy", "user_id" : 2 }
{ "create": { "_index": "us", "_type": "tweet", "_id": "14" }}
{ "date" : "2014-09-24", "name" : "John Smith", "tweet" : "How many more cheesy tweets do I have to write?", "user_id" : 1 }

2、size+from浅分页

按照一般的查询流程来说,如果我想查询前10条数据:

  • 1 客户端请求发给某个节点
  • 2 节点转发给个个分片,查询每个分片上的前10条
  • 3 结果返回给节点,整合数据,提取前10条
  • 4 返回给请求客户端

from定义了目标数据的偏移值,size定义当前返回的事件数目

GET /us/_search?pretty
{
  "from" : 0 , "size" : 5
}

GET /us/_search?pretty
{
  "from" : 5 , "size" : 5
}

这种浅分页只适合少量数据,因为随from增大,查询的时间就会越大,而且数据量越大,查询的效率指数下降

优点:from+size在数据量不大的情况下,效率比较高

缺点:在数据量非常大的情况下,from+size分页会把全部记录加载到内存中,这样做不但运行速递特别慢,而且容易让es出现内存不足而挂掉

3、scroll深分页

对于上面介绍的浅分页,当Elasticsearch响应请求时,它必须确定docs的顺序,排列响应结果。

如果请求的页数较少(假设每页20个docs), Elasticsearch不会有什么问题,但是如果页数较大时,比如请求第20页,Elasticsearch不得不取出第1页到第20页的所有docs,再去除第1页到第19页的docs,得到第20页的docs。

解决的方式就是使用scroll,scroll就是维护了当前索引段的一份快照信息--缓存(这个快照信息是你执行这个scroll查询时的快照)。

可以把 scroll 分为初始化和遍历两步: 1、初始化时将所有符合搜索条件的搜索结果缓存起来,可以想象成快照; 2、遍历时,从这个快照里取数据;

初始化

GET us/_search?scroll=3m
{ 
"query": {"match_all": {}},
 "size": 3
}

初始化的时候就像是普通的search一样

其中的scroll=3m代表当前查询的数据缓存3分钟

Size:3 代表当前查询3条数据

遍历

在遍历时候,拿到上一次遍历中的scrollid,然后带scroll参数,重复上一次的遍历步骤,知道返回的数据为空,就表示遍历完成

GET /_search/scroll
{
  "scroll" : "1m",
  "scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAPXFk0xN1BmSnlVUldhYThEdWVzZ19xbkEAAAAAAAAAIxZuQWVJU0VSZ1JzcVZtMGVYZ3RDaFlBAAAAAAAAA9oWTVZOdHJ2cXBSOU9wN3c1dk5vcWd4QQAAAAAAAAPYFk0xN1BmSnlVUldhYThEdWVzZ19xbkEAAAAAAAAAIhZuQWVJU0VSZ1JzcVZtMGVYZ3RDaFlB"
}

【注意】:每次都要传参数scroll,刷新搜索结果的缓存时间,另外不需要指定index和type(不要把缓存的时时间设置太长,占用内存

对比

浅分页,每次查询都会去索引库(本地文件夹)中查询pageNum*page条数据,然后截取掉前面的数据,留下最后的数据。 这样的操作在每个分片上都会执行,最后会将多个分片的数据合并到一起,再次排序,截取需要的。

深分页,可以一次性将所有满足查询条件的数据,都放到内存中。分页的时候,在内存中查询。相对浅分页,就可以避免多次读取磁盘。

十、三台机器安装IK分词器

我们在搜索的时候,都会对数据进行分词,英文的分词很简单,我们可以直接按照空格进行切分即可,但是中文的分词太过复杂,例如:夏天太热,能穿多少穿多少,冬天太冷,能穿多少穿多少。下雨地滑,还好我一把把车把把住了,才没有摔倒。人要是行,干一行行一行,一行行行行行等等的分词都是非常麻烦的,所以针对中文的分词,专门出了一个叫做IK的分词器来解决对中文的分词问题。

1安装

每台机器都要配置。配置完成之后,需要重启ES服务

将安装包上传到node01机器的/home/es路径下

cd /home/es
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.7.0/elasticsearch-analysis-ik-6.7.0.zip
# 将ik分词器的插件,上传到/home/es目录下 
cd /home/es
mkdir  /export/servers/es/elasticsearch-6.7.0/plugins/analysis-ik/
unzip elasticsearch-analysis-ik-6.0.0.zip -d /export/servers/es/elasticsearch-6.0.0/plugins/analysis-ik/

将安装包分发到其他机器上

node01机器执行以下命令进行安装包的分发

cd /export/servers/es/elasticsearch-6.0.0/plugins

scp -r analysis-ik/ node02:$PWD
scp -r analysis-ik/ node03:$PWD

# 三台机器都配置完成
# 配置完成之后,需要重启ES服务。

三台机器重启es服务

三台机器执行以下命令停止es服务

ps -ef|grep elasticsearch|grep bootstravelap |awk '{print $2}' |xargs kill -9


nohup /export/servers/es/elasticsearch-6.0.0/bin/elasticsearch >/dev/null 2>&1 &

2配置

delete iktest
PUT /iktest?pretty
{
    "settings" : {
        "analysis" : {
            "analyzer" : {
                "ik" : {
                    "tokenizer" : "ik_max_word"
                }
            }
        }
    },
    "mappings" : {
        "article" : {
            "dynamic" : true,
            "properties" : {
                "subject" : {
                    "type" : "text",
                    "analyzer" : "ik_max_word"
                }
            }
        }
    }
}

说明:ik带有两个分词器:

  • ikmaxword :会将文本做最细粒度的拆分;尽可能多的拆分出词语
  • 我|爱|我的|祖|国|祖国
  • ik_smart:会做最粗粒度的拆分;已被分出的词语将不会再次被其它词语占有
  • 我|爱|我|的|祖国

3查看分词效果

  GET _analyze?pretty
  {
    "analyzer": "ik_max_word",
    "text": "希拉里是个妹子"
  }

4插入测试数据

POST /iktest/article/_bulk?pretty
{ "index" : { "_id" : "1" } }
{"subject" : ""闺蜜"崔顺实被韩检方传唤 韩总统府促彻查真相" }
{ "index" : { "_id" : "2" } }
{"subject" : "韩举行"护国训练" 青瓦台:决不许国家安全出问题" }
{ "index" : { "_id" : "3" } }
{"subject" : "媒体称FBI已经取得搜查令 检视希拉里电邮" }
{ "index" : { "_id" : "4" } }
{"subject" : "村上春树获安徒生奖 演讲中谈及欧洲排外问题" }
{ "index" : { "_id" : "5" } }
{"subject" : "希拉里团队炮轰FBI 参院民主党领袖批其”违法”" }

查看分词器

对"希拉里和韩国"进行分词查询

ikmaxword分词后的效果:希|拉|里|希拉里|和|韩国

POST /iktest/article/_search?pretty
{
    "query" : { "match" : { "subject" : "希拉里和韩国" }},
    "highlight" : {
        "pre_tags" : ["<font color=red>"],
        "post_tags" : ["</font>"],
        "fields" : {
            "subject" : {}
        }
    }
}

5热词更新

查看分词效果

  GET _analyze?pretty

  {

    "analyzer": "ik_max_word",

    "text": "我在哪里"

  }

1node03配置Tomcat

使用es用户来进行配置tomcat,此处我们将tomcat装在node03机器上面即可

cd /home/es

tar -zxvf apache-tomcat-8.5.34.tar.gz -C /export/servers/es/

tomcat当中添加配置hot.dic

cd /export/servers/es/apache-tomcat-8.5.34/webapps/ROOT/

vi hot.dic

传智播客

# 启动tomcat

/export/servers/es/apache-tomcat-8.5.34/bin/startup.sh

浏览器访问

wget http://node03:8080/hot.dic

2 三台机器修改配置文件

三台机器都要修改es的配置文件(使用es用户来进行修改即可)

第一台机器node01修改es的配置

cd /export/servers/es/elasticsearch-6.0.0/plugins/analysis-ik/config

vim IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">

<properties>

        <comment>IK Analyzer 扩展配置</comment>

        <!--用户可以在这里配置自己的扩展字典 -->

        <entry key="ext_dict"></entry>

         <!--用户可以在这里配置自己的扩展停止词字典-->

        <entry key="ext_stopwords"></entry>

        <!--用户可以在这里配置远程扩展字典 -->

        <entry key="remote_ext_dict">http://node03:8080/hot.dic</entry>

        <!--用户可以在这里配置远程扩展停止词字典-->

        <!-- <entry key="remote_ext_stopwords">words_location</entry> -->

</properties>

修改完成之后拷贝到node02与node03机器上面去

node01执行以下命令进行拷贝

cd /export/servers/es/elasticsearch-6.0.0/plugins/analysis-ik/config

sudo scp IKAnalyzer.cfg.xml  node02:$PWD

sudo scp IKAnalyzer.cfg.xml  node03:$PWD

3 三台机器修改JDK权限

三台机器修改jdk的权限问题

第一台机器执行以下命令修改jdk的权限问题

#修改JDK安全设置
cd /export/servers/jdk1.8.0_141/jre/lib/security

sudo vim java.policy

添加以下四行配置

 permission java.net.SocketPermission "192.168.100.10:8080","accept";
 permission java.net.SocketPermission "192.168.100.10:8080","listen";
 permission java.net.SocketPermission "192.168.100.10:8080","resolve";
 permission java.net.SocketPermission "192.168.100.10:8080","connect";

修改完成之后拷贝到第二台和第三台机器

node01执行以下命令拷贝到第二台和第三台

cd /export/servers/jdk1.8.0_141/jre/lib/security

sudo scp java.policy  node02:$PWD

sudo scp java.policy  node03:$PWD

http://mahilion.blog.163.com/blog/static/1830872952012101225243655/

4、三台机器重新启动es

三台机器重新启动es服务,三台机器先使用kill -9杀死es的服务,然后再执行以下命令进行重启

cd /export/servers/es/elasticsearch-6.0.0/

nohup bin/elasticsearch >/dev/null 2>&1 &

查看我们的分词过程

  GET _analyze?pretty

  {

    "analyzer": "ik_max_word",

    "text": "我在哪里"

  }

十一、分片交互过程

1创建索引

首先:发送一个索引或者删除的请求给node1

其次:node1介绍到请求之后,会根据请求中携带的参数“文档id”判断出该文档应该存储在具体哪一个shard中

shard = hash(routing) % numberofprimary_shards

,比如shard0;其次就是node1通过元数据信息可以知道shard0在具体哪一个节点,于是node1会把请求转发给node3

最后:node3接收到请求之后会将请求并行的分发给shard0的所有replica shard之上,也就是存在于node 1和node 2中的replica shard;如果所有的replica shard都成功地执行了请求,那么将会向node 3回复一个成功确认,当node 3收到了所有replica shard的确认信息后,则最后向用户返回一个Success的消息。

2删除索引

该过程可以分为四个阶段来描述:

阶段1:客户端向node 1发送一个文档删除的请求。

阶段2:同样的node 1通过请求中文档的 _id 值判断出该文档应该被存储在shard 0 这个分片中,并且node 1知道shard 0的primary shard位于node 3这个节点上。因此node 1会把这个请求转发到node 3。

阶段3:node 3接收到请求后,在主分片上面执行删除请求

阶段4:如果node 3成功地删除了文档,node 3将会请求并行地发给其余所有的replica shard所在node中。这些node也同样操作删除,执行后则向node 3确认成功,当node 3接收到所有的成功确认之后,再向客户端发送一个删除成功的信息。

3查询索引

检索文档的时候,我们并不知道文档在集群中的哪个位置,所以一般情况下不得不去询问index中的每一个shard,然后将结果拼接成一个大的已排好序的汇总结果列表;

(1):客户端发送一个检索请求给node3,此时node3会创建一个空的优先级队列并且配置好分页参数from与size。

(2):node3将检所请求发送给index中的每一个shard(primary 和 replica),每一个在本地执行检索,并将结果添加到本地的优先级队列中;

(3):每个shard返回本地优先级序列中所记录的_id与**score值**,并发送node3。Node3将这些值合并到自己的本地的优先级队列中,并做全局的排序(node 3将它们合并成一条汇总的结果),返回给客户端。

发布了114 篇原创文章 · 获赞 143 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_35995514/article/details/104212411