飞天班第38节:ElasticSearch实战-1

2020/05/23

1、入门

ElasticSearch概述

原来我们基于数据库搜索:select * from xxx where xx=xxx,使用sql查询

大数据量下,索引失效了,就十分的慢,真正的大数据搜索都不会直接使用SQL查询,而是将数据导入到搜索引擎中,通过搜索引擎查询数据。

ElasticSearch(下面简称ES) 现在主流用的是6.x和7.x版本,如何用它和它的原理思想最重要。

第一个版本:2010年2月,开源在github上

官网下载:https://www.elastic.co/cn/downloads/elasticsearch

文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/7.x/getting-started.html

与Solr的比较

Solr简介

  • Apache下的顶级开源项目,使用java开发,基于Lucene封装的全文搜索服务器。

  • 提供的功能:大量的配置,索引进行了优化。

  • 是独立运行的服务器

  • 使用的方式:Post发送一个请求xml文档,添加、删除、更新,Get请求进行查询

ES简介

  • 是一个实时分布式搜索和分析引擎,在大数据领域使用十分广泛,比如百度搜索高亮,商品搜索
  • 实时搜索,效率十分高,使用倒排索引
  • 是一个基于Apache Lucene的开源搜索引擎

Lucene简介

  • 是一个开源的全文检索引擎工具包,查询引擎、索引引擎、文本分析。现在很少直接使用Lucene来实现全文检索了

全文检索

  • Baidu,Google,GitHub 都是通过从互联网上提取的各个网站的信息(网页文字),将这些信息建立到数据库中的。

数据来源

  • 爬虫,主动收集
  • 数据库中的内容
  • 清洗完毕的数据
  • 搞懂数据是如何存储和操作的

性能对比

1、当单纯的对已有数据进行搜索时,Solr更快。

2、当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势。

3、随着数据量的增加,Solr的搜索效率会变得更低,而Elasticsearch却没有明显的变化。

综上所述,Solr的架构不适合实时搜索的应用,而ES更适合

4、实际生产环境测试

下图为将搜索引擎从Solr转到Elasticsearch以后的平均查询速度有了50倍的提升。

小结:

1、ES开箱即用,Solr相对复杂一点

2、Solr需要独立部署在tomcat上,可以实现集群和分片,自身不支持集群结构,需要zookeeper来进行集群的支持提供服务注册,进行分布式索引查询,也是可以自己实现故障转移的(3组节点,每组2个solr,互为主从),ES自带集群管理,分布式搜索。

3、Solr支持的数据格式XML、JSON,ES仅支持JSON

4、Solr官方提供的功能更多,ES注重核心功能,拥有良好的插件机制,高级功能可以使用第三方插件。

5、Solr对已有数据查询更快,索引更新时查询很慢,ES建立索引快,实时查询比较快

6、Solr生态和用户较大,ES相对来说较少,ES版本更新快,很多人还在用旧版本6.x

ES的核心概念

Lucene是一个Java语言开发的开源全文检索引擎工具包,用Netty封装成服务,使用JSON访问就是ES了。

ES内置了分布式集群(多节点)和分布式索引(数据分片)的管理。使用ES的搜索系统管理架构图如下:

核心术语:

1、索引index

​ ES将数据存储到索引中,用sql领域的术语来类比,索引就像数据库,可以向索引写入文档和读取文档,索引是具有某些类似特征的文档集合。

2、文档document

​ ES索引中一条一条的数据,相当于数据库表里的一行一行的数据

3、映射Mappings

​ 相当于表结构定义,定义字段内容信息

4、类型type

​ 文档的类型(分组),允许一个索引存储多种文档类型,7.x版本后默认为doc。

​ ES6.x,一个文档只能包含一个映射类型

​ ES7.x,映射类型默认是_doc,

​ ES8.x,将完成删除type

5、节点node

​ 单个ES服务实例称为节点,很多时候部署一个ES节点就足以应付大多数简单应用,但是考虑到容错性和数据的膨胀,单机无法应用这些状况。

6、集群cluster

​ 集群是一组具有相同cluster.name的节点集合,集群状态通过绿、黄、红来标识

  • 绿色,一切都很好,集群功能齐全
  • 黄色,所有数据均可用,但尚未分配一些副本
  • 红色,某些数据由于某种原因不可用,集群功能不齐全,这个时候要尽快修复

7、分片shard

  • 数据分片的概念,需要进行水平扩展服务节点只需要加入新的机器到集群中即可,允许分片跨节点分布,从而提供性能和吞吐量。

  • 集群的每个数据节点都是HA的

    主分片:承担数据写入访问的作用

    replica备份分片:除了做备份以外,还承担了读数据的水平负载作用(可执行搜索),创建索引时要定义正确数量的分片和副本分片。创建索引后,也可以动态更改副本分片数。

8、NRT (Near Real Time)

​ ES中新的文档(doc)被加入后可查询的时间间隔非常微弱,接近实时

Mysql ES
数据库(database) 索引(index)
表(table) types (7.x后默认为doc)
行(rows) 文档(documents)
字段(columns) 字段(fields)

物理设计,一个集群至少包含一个节点,一个节点就是一个es进程,节点可以有多个索引,如创建一个索引

这个索引有5个主分片,每个主分片有一个副本分片,分布在不同的节点内,某个节点挂了,数据也不至于丢失

安装ES

去官网下载,也可以用docker安装,这里我使用第一种方式

windows安装

1、解压安装包即可使用

bin: 启动文件
config: 配置文件
		log4j: 日志配置
		jvm: java虚拟机的配置
		es.yml: es的配置文件
lib: 相关类库jar包
logs: 日志
modules: 功能模块
plguins: 放置插件使用,如ik中文分词器,拼音分词器

2、由于ES默认占有的内存资源很大,所以需要修改jvm参数

启动ES前一定要配置好jdk环境变量

3、双击启动即可

4、查看启动日志

启动时会加载模块

5、访问 http://localhost:9200

linux安装

# linux下,不能用root启动es,所以我直接创建一个用户esuser来安装es
[root@helloworld ~]# adduser esuser
# 下载
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.6.1-linux-x86_64.tar.gz
# 1、切换esuser,上传ElasticSearch到服务器,解压
[root@helloworld ~]# su esuser
[esuser@helloworld ~]$ pwd
/home/esuser
[esuser@helloworld ~]$ rz
[esuser@helloworld ~]$ tar -zxvf elasticsearch-7.6.1-linux-x86_64.tar.gz
[esuser@helloworld elasticsearch-7.6.1]$ mkdir data
# 2、修改配置文件,注意留空格
[esuser@helloworld config]$ vi elasticsearch.yml 
cluster.name: jude-es # 给集群设置一个名字,如果是集群,所有在这个集群中的节点集群名都要一样
node.name: es-node-1 # 如果是集群,集群中每个节点的名字都不能一样
path.data: /home/esuser/elasticsearc-7.6.1/data
path.logs: /home/esuser/elasticsearc-7.6.1/logs
network.host: 0.0.0.0 # 不限制ip访问 ES,生产环境应该要设置可以访问的ip
http.port: 9200 # 访问 服务端口,节点通信的端口是9300
cluster.initial_master_nodes: ["es-node-1"] # master节点服务发现,和上面的节点名一致
# 改小java的堆内存,这个自己设置,默认是1g内存
[esuser@helloworld config]$ vi jvm.options
-Xms512m
-Xmx512m
# 3、修改sysctl.conf文件,需要切回root用户
[root@helloworld bin]# vi /etc/sysctl.conf
vm.max_map_count=262145
# 修改后刷新生效
[root@helloworld bin]# sysctl -p
# 修改 /etc/security/limits.conf,文件尾部添加
[root@helloworld ~]# vi /etc/security/limits.conf
esuser soft nofile 65536
esuser hard nofile 65536
esuser nproc 2048
esuser nproc 4096
# 4、启动,需要使用esuser用户,到elasticsearch的bin目录下执行
[esuser@helloworld bin]$ ./elasticsearch # 先在线启动确认没有报错
[esuser@helloworld bin]$ ./elasticsearch -d # 后台启动

安装 ES Head

ES本身没有界面控制,我们使用第三方工具来测试查看

elasticSearch-head 需要nodejs环境,在自己本机安装就行了

下载地址:https://github.com/mobz/elasticsearch-head

Running with built in server
    git clone git://github.com/mobz/elasticsearch-head.git
    cd elasticsearch-head
    npm install
    npm run start

    open http://localhost:9100/

配置ES的可以跨域访问

# 在elasticsearch.yaml里加入
http.cors.enabled: true
# 开放所有ip访问,线上这样设置不安全,建议head与elasticsearch在同一台服务器上
http.cors.allow-origin: "*"	
# 重启elasticsearch

连接成功

ES设置用户密码访问

# 1、修改配置文件,开启x-pack验证
[esuser@helloworld config]$ vi elasticsearch.yml 
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true

# 2、

2、倒排索引

ES使用的是一种倒排索引的结构,

Redis在查询的时候:key-value?是通过key来找到的value,是否可以通过value来找key?通过value找到和这个value相似度极高的内容?不可以,所以需要全文搜索引擎,引出倒排索引概念

倒排索引(Inverted Index):比如通过歌词来查歌名,通过内容检索名称,而这个名称在系统中其实就是一个索引,通过歌来找歌词这是正排索引

比如拿课程学习举例:

文档编号 文档内容

1 艾编程架构师之路

2 艾编程Java成长之路 (分词:艾编程 Java 成长 之路)

3 ES成长学习入门

搜索的分词 这个分词在哪个文档中出现 文档编号:次数:位置

成长 2,3 2:1:<3>,3:1:<2>

ES的索引流程:建立索引->分片->集群中不同的节点上,每个分片还有一个副本分片。

每个分片保存了一些倒排索引词条->词条对应的文档记录

3、ELK

ELK是三个技术的总和(ElasticSearch、Logstash、Kibana)

ElasticSearch 是一个基于Lucene、分布式、通过Restful Api进行交互的实时搜索平台

Logstash 是ELK的中央数据流引擎,作用是将收集不同的数据(文件、数据库、MQ),需要通过它过滤

Kibana 将这些数据进行可视化的展示出来,提供实时分析功能

安装Kibana

官网地址:https://www.elastic.co/cn/downloads/kibana

ES和Kibana的版本必须一致

window安装

下载后直接解压

启动

linux安装

# es 和 kibana放在同一目录下,也不能root用户启动kibana
[esuser@helloworld ~]$ ls
elasticsearch-7.6.1  kibana-7.6.1-linux-x86_64.tar.gz
# 1、解压
[esuser@helloworld ~]$ tar -zxvf kibana-7.6.1-linux-x86_64.tar.gz
# 改名字
[esuser@helloworld ~]$ mv kibana-7.6.1-linux-x86_64 kibana-7.6.1
# 2、修改kibana的yaml配置,
[esuser@helloworld config]$ cd kibana-7.6.1
[esuser@helloworld config]$ vi kibana.yml
server.port: 5601 # 默认端口5601,可以不修改
server.host: "0.0.0.0" # 开放ip访问,默认localhost
elasticsearch.hosts: ["http://localhost:9200"] # es实例节点,默认localhost:9200
i18n.locale: "zh-CN"  # 汉化
# 3、启动,cd到kibana的bin目录
[esuser@helloworld bin]$ ./kibana  # 在线运行
nohup kibana > kibana.log 2>&1 & # 后台运行
# 注意,云服务器防火墙和安全组要开放5601端口,

启动后,ES会多了几个kibana的索引

访问:http://localhost:5601/app/kibana#/home

开放工具

建一个索引,包含数据

查看elasticsearch-head,多了一个索引index_customer

4、IK中文分词器

分词:将一个完成的词或者语句,拆分为一个一个关键字(词条),搜索的时候就会进行关键字查找搜索。其实ES在添加文档的时候,就会对文档内容按指定的分词器进行拆分了。

安装

要与ES版本对应

github地址: https://github.com/medcl/elasticsearch-analysis-ik/releases

window安装

1、解压到es插件目录中

2、重启ES观察是否加载成功

# 通过命令查询
[esuser@helloworld bin]$ ./elasticsearch-plugin list
ik

linux安装

#安装unzip
yum -y install unzip
# 1、下载完解压到elasticsearch的plugin/ik目录下
[esuser@helloworld ~]$ unzip elasticsearch-analysis-ik-7.6.1.zip  -d /home/esuser/elasticsearch-7.6.1/plugins/ik
[esuser@helloworld ~]$ cd elasticsearch-7.6.1/plugins/ik
[esuser@helloworld ik]$ ls
commons-codec-1.9.jar    config                               httpclient-4.5.2.jar  plugin-descriptor.properties
commons-logging-1.2.jar  elasticsearch-analysis-ik-7.6.1.jar  httpcore-4.4.4.jar    plugin-security.policy
# 2、重启elasticsearch
# 新增分词器后,先加的记录是不能被匹配出来的,要后加的记录才能匹配,因为文档在新增的时候就进行了分词,可以重建索引,对所有的文档记录重新分词,但相对会损耗些资源。

使用kibana测试ik分词器

ik分词器提供了两种算法:

  • ik_smart 最少切分,发现只有一个词

    在ik分词器的词库里,“中国共产党”是一个词,所以就可以最少拆分出一个词来,但是”艾编程”并不在ik分词器的词库里,也就是说它不是一个词,所以拆分出“艾”和“编程”两个词(最少)。怎么把“艾编程”当做一个词,自定义词库。

  • Ik_max_word 最细粒度划分,穷尽词库

自定义词库

在ik分词器的配置中ik/config,有很多dic文件,保存了大量的关键字(词条),就是拆分的依据

点击其中一个看看

可以看到很多个词语。

1、定义自己的.dic,然后放入自己的词

[esuser@helloworld config]$ vi my.dic
# 添加 “艾编程”
[esuser@helloworld config]$ cat my.dic 
艾编程

2、配置到IKAnalyzer.cfg.xml中

3、重启ES,测试“艾编程”

[esuser@helloworld config]$ ps -ef|grep elastic
[esuser@helloworld config]$ kill

发现“艾编程”已是一个可识别的词了。

5、基础操作

Rest风格

Method url风格 描述
PUT/POST localhost:9200/索引/类型名称/文档id 创建文档(指定id)
POST localhost:9200/索引/类型名称 创建文档(随机id)
POST localhost:9200/索引/类型名称/文档id/_update 修改文档
DELETE localhost:9200/索引/类型名称/文档id 删除文档
GET localhost:9200/索引/类型名称/文档id 通过id查询文档
POST localhost:9200/索引/类型名称/文档id/_search 查询所有数据

Post Directory