0%

Elasticsearch 核心技术与实战

Elasticsearch 核心技术与实战

下载地址

https://www.elastic.co/cn/downloads/elasticsearch

github

https://github.com/geektime-geekbang/geektime-ELK

下载说明:

下载安装

根据服务器的内核进行下载

1
2
3
[root@ecs ~]# arch
x86_64

image-20201215103150818

参考地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/targz.html

1
2
3
4
5
6
[root@ecs es]# shasum -a 512 -c elasticsearch-7.10.1-linux-x86_64.tar.gz.sha512
-bash: shasum: command not found
# 需要安装
[root@ecs es]# yum install perl-Digest-SHA
[root@ecs es]# shasum -a 512 -c elasticsearch-7.10.1-linux-x86_64.tar.gz.sha512
elasticsearch-7.10.1-linux-x86_64.tar.gz: OK

启动 es

1
2
3
[root@ecs elasticsearch-7.10.1]# bin/elasticsearch
uncaught exception in thread [main]
java.lang.RuntimeException: can not run elasticsearch as root

提示报错
原因:
  为了安全不允许使用 root 用户启动
解决:
  es5 之后的都不能使用添加启动参数或者修改配置文件等方法启动了,必须要创建用户

添加用户

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@ecs soft]# adduser elasticsearch
# 需要输入两次密码
[root@ecs soft]# passwd elasticsearch
[root@ecs soft]# cd es/
[root@ecs es]# chown -R elasticsearch elasticsearch-7.10.1
[root@ecs es]# su elasticsearch

# 正常启动
[elasticsearch@ecs es]$ cd elasticsearch-7.10.1/
[elasticsearch@ecs elasticsearch-7.10.1]$ bin/elasticsearch
[2020-12-15T11:02:42,069][INFO ][o.e.c.s.ClusterApplierService] [ecs] master node changed {previous [], current [{ecs}{ThIV-dkxQES598Qp2Oim3w}{EoqNpUBaTnO-wSjE675U0A}{127.0.0.1}{127.0.0.1:9300}{cdhilmrstw}{ml.machine_memory=3811565568, xpack.installed=true, transform.node=true, ml.max_open_jobs=20}]}, term: 1, version: 1, reason: Publication{term=1, version=1}
[2020-12-15T11:02:42,107][INFO ][o.e.h.AbstractHttpServerTransport] [ecs] publish_address {127.0.0.1:9200}, bound_addresses {[::1]:9200}, {127.0.0.1:9200}
[2020-12-15T11:02:42,107][INFO ][o.e.n.Node ] [ecs] started

启动报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[2020-12-15T11:35:40,298][INFO ][o.e.b.BootstrapChecks    ] [ecs] bound or publishing to a non-loopback address, enforcing bootstrap checks
ERROR: [2] bootstrap checks failed
[1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
[2]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured
ERROR: Elasticsearch did not exit normally - check the logs at /data/soft/es/elasticsearch-7.10.1/logs/elasticsearch.log
[2020-12-15T11:35:40,326][INFO ][o.e.n.Node ] [ecs] stopping ...
[2020-12-15T11:35:40,343][INFO ][o.e.n.Node ] [ecs] stopped
[2020-12-15T11:35:40,344][INFO ][o.e.n.Node ] [ecs] closing ...
[2020-12-15T11:35:40,354][INFO ][o.e.n.Node ] [ecs] closed

# elasticsearch用户拥有的内存权限太小,至少需要262144
解决:
切换到root用户
执行命令:
sysctl -w vm.max_map_count=262144
查看结果:
sysctl -a|grep vm.max_map_count
显示:vm.max_map_count = 262144
上述方法修改之后,如果重启虚拟机将失效,所以:
解决办法:
在 /etc/sysctl.conf文件最后添加一行
[root@ecs soft]# vi /etc/sysctl.conf
vm.max_map_count=262144
保存后执行
sysctl -p
即可永久修改

启动异常 2

1
2
3
4
5
6
7
8
[2020-12-15T11:41:46,790][INFO ][o.e.b.BootstrapChecks    ] [ecs] bound or publishing to a non-loopback address, enforcing bootstrap checks
ERROR: [1] bootstrap checks failed
[1]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured
ERROR: Elasticsearch did not exit normally - check the logs at /data/soft/es/elasticsearch-7.10.1/logs/elasticsearch.log
[2020-12-15T11:41:46,838][INFO ][o.e.n.Node ] [ecs] stopping ...
[2020-12-15T11:41:46,851][INFO ][o.e.n.Node ] [ecs] stopped
[2020-12-15T11:41:46,851][INFO ][o.e.n.Node ] [ecs] closing ...
[2020-12-15T11:41:46,862][INFO ][o.e.n.Node ] [ecs] closed

解决方案:

elasticsearchconfig 目录下,修改 elasticsearch.yml 配置文件,将下面的配置加入到该配置文件中:

ip 替换 host1 等,多节点请添加多个 ip 地址,单节点可写按默认来 #配置以下三者,最少其一 #[discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] cluster.initial_master_nodes: [“node-1”] #这里的 node-1 为 node-name 配置的值

1
cluster.initial_master_nodes: ["node-1"]

通过 IP:Port 进行访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@ecs elasticsearch-7.10.1]# curl http://127.0.0.1:9200/
{
"name" : "ecs",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "ROb635dFT767Bw39N_BcFw",
"version" : {
"number" : "7.10.1",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "1c34507e66d7db1211f66f3513706fdf548736aa",
"build_date" : "2020-12-05T01:00:33.671820Z",
"build_snapshot" : false,
"lucene_version" : "8.7.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}

在开发机上运行多个 elasticsearch 实例

1
2
3
./elasticsearch -E node.name=node1 -E cluster.name=test -E path.data=node1_data -d
./elasticsearch -E node.name=node2 -E cluster.name=test -E path.data=node2_data -d
./elasticsearch -E node.name=node3 -E cluster.name=test -E path.data=node3_data -d

安装插件

1
2
[elasticsearch@ecs bin]$ ./elasticsearch-plugin list
future versions of Elasticsearch will require Java 11; your Java version from [/usr/java/jdk1.8.0_192-amd64/jre] does not meet this requirement

原因:说明这个版本对应的 jdk 应该是 java11。我们环境中的 jdk 是 java8。其实新版的 es 是自带了 jdk 的。但是和我们环境变量的冲突了。
解决方案:修改启动文件,添加如下修改

1
2
3
4
5
6
7
8
9
10
11
12
vi bin/elasticsearch
# 指定jdk11
export JAVA_HOME=/data/soft/es/elasticsearch-7.10.1/jdk
export PATH=$JAVA_HOME/bin:$PATH


#添加jdk判断
if [ -x "$JAVA_HOME/bin/java" ]; then
JAVA="/data/soft/es/elasticsearch-7.10.1/jdk"
else
JAVA=`which java`
fi

安装插件

1
2
3
4
5
6
7
8
9
10
[root@ecs bin]# ./elasticsearch-plugin install analysis-icu
-> Installing analysis-icu
-> Downloading analysis-icu from elastic
[=================================================] 100%  
-> Installed analysis-icu
[root@ecs bin]# ./elasticsearch-plugin list
# 重新启动 elasticsearch 查看安装插件
[root@ecs bin]# curl http://127.0.0.1:9200/_cat/plugins
ecs analysis-icu 7.10.1
[root@ecs bin]#

Elastic Stack 生态圈

image-20210112180026007

启动 logstash

下载最 MovieLens 最小测试数据集:https://grouplens.org/datasets/movielens/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[root@ecs bin]# cat logstash.conf 
input {
file {
path => "/usr/local/logstash-7.10.1/files/movies.csv"
start_position => "beginning"
sincedb_path => "/dev/null"
}
}
filter {
csv {
separator => ","
columns => ["id","content","genre"]
}

mutate {
split => { "genre" => "|" }
remove_field => ["path", "host","@timestamp","message"]
}

mutate {

split => ["content", "("]
add_field => { "title" => "%{[content][0]}"}
add_field => { "year" => "%{[content][1]}"}
}

mutate {
convert => {
"year" => "integer"
}
strip => ["title"]
remove_field => ["path", "host","@timestamp","message","content"]
}

}
output {
elasticsearch {
hosts => "http://localhost:9200"
index => "movies"
document_id => "%{id}"
}
stdout {}
}

启动导入数据

1
2
3
4
5
6
7
8
9
10
11
12
[root@ecs bin]# ./logstash -f logstash.conf 
Using JAVA_HOME defined java: /usr/local/elasticsearch-7.10.1/jdk
WARNING, using JAVA_HOME while Logstash distribution comes with a bundled JDK
Unrecognized VM option 'UseConcMarkSweepGC'
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

# 修改config/jvm.options,注释掉以下这个配置即可。

#-XX:+UseConcMarkSweepGC
#-XX:CMSInitiatingOccupancyFraction=75
#-XX:+UseCMSInitiatingOccupancyOnly

基本概念

索引、文档、REST API

image-20210113154019447

image-20210113154435215

image-20210113154446712

image-20210113154504446

image-20210113154526739

image-20210113154539658

image-20210113154752770

集群、节点、分片、副本

image-20210113155153011

image-20210113155219984

image-20210113155254971

文档基本 CRUD 和批量操作

image-20210113155436630

image-20210113155458375

image-20210113155508512

image-20210113155517352

image-20210113155532943

倒排索引

搜索引擎

  • 正排索引:文档 ID 到文档内容和单词的关联。
  • 倒排索引:单词到文档 ID 的关系。

image-20210113162736816

通过 Analyzer 进行分词

Analysis 与 Analyzer

  • Analysis - 文本分析是把全文本转换一系列单词 (term /token) 的过程,也叫分词

  • Analysis 是通过 Analyzer 来实现的

    • 可使用 Elasticsearch 内置的分析器 / 或者按需定制化分析器
  • 除了在数据写入时转换词条,匹配 Query 语句时候也需要用相同的分析器对查询语句进行分析

image-20210113163737912

Elasticsearch 的内置分词器

  • Standard Analyzer — 默认分词器,按词切分,小写处理
  • Simple Analyzer — 按照非字母切分 (符号被过滤),小写处理
  • Stop Analyzer — 小写处理,停用词过滤 (the, a, is)
  • Whitespace Analyzer — 按照空格切分,不转小写
  • Keyword Analyzer — 不分词,直接将输入当作输出
  • Patter Analyzer — 正则表达式,默认 \W+ (非字符分隔)
  • Language — 提供了 30 多种常见语言的分词器
  • Customer Analyzer — 自定义分词器

中文分词器

  • ICU Analyzer

  • 需要安装 plugin Elasticsearch-plugin install analysis-icu

  • 提供了 Unicode 的支持,更好的支持亚洲语言。

  • IK 支持自定义词库,支持热更新分词字典

  • THULAC 清华大学自然语言处理和社会人文计算实验室的一套中文分词器。

Search API 概览

  • URI Search

    • 在 URL 中查询参数

      image-20210113170144304

  • Request Body Search

    • 使用 Elasticsearch 提供的,基于 JSON 格式的更加完备的 Query Domain Specific Language (DSL)

image-20210113170154309

衡量相关性

Information Retrieval

  • Precision (查准率)- 尽可能返回较少的无关文档

  • Recall (查全率)- 尽量返回较多的相关文档

  • Ranking - 是否能够按照相关度进行排序?

Elasticsearch 聚合分析简介

什么是聚合 (Aggregation)

  • Elasticsearch 除搜索以外,提供的针对 ES 数据进行统计分析的功能

    • 实时性高

    • Hadoop (T+1)

  • 通过聚合,我们会得到一个数据的概览,是分析和总结全套的数据,而不是寻找单个文档

    • 尖沙咀和香港岛的客房数量
    • 不同的价格区间,可预定的经济型酒店和五星级酒店的数量
  • 高性能,只需要一条语句,就可以从 Elasticsearch 得到分析结果

    • 无需在客户端自己去实现分析逻辑

深入搜索

搜索和算分

  • 结构化搜索与非结构化搜索

    • Term 查询和基于全文本 Match 搜索的区别

    • 对于需要做精确匹配的字段,需要做聚合分析的字段,字段类型设置为 Keyword

  • Query Context v.s Filter Context

    • Filter Context 可以避免算分,并且利用缓存
    • Bool 查询中 Filter 和 Must Not 都属于 Filter Context
  • 搜索的算分

    • TF-IDF / 字段 Boosting
  • 单字符串多字段查询: multi-match

    • Best_Field / Most Fields / Cross_Field
  • 提高搜索的相关性

    • 多语言:设置子字段和不同的分词器提升搜索的效果
    • Search Template 分离代码逻辑和搜索 DSL
    • 多测试,监控及分析用户的搜索语句和搜索效果

聚合 / 分页

  • 聚合

    • Bucket / Metric / Pipeline
  • 分页

    • From & Size / Search After / Scroll API
    • 要避免深度分页,对于数据导出等操作,可以使用 Scroll AP

Elasticsearch 的分布式模型

  • 文档的分布式存储
    • 文档通过 hash 算法,route 并存储到相应的分片
  • 分片及其内部的工作机制
    • Segment/ Transaction Log / Refresh / Merge
  • 分布式查询和聚合分析的内部机制
    • Query Then Fetch; IDF 不是基于全局,而是基于分片计算,因此,数据量少的时候,算分不准
    • 增加”shard size” 可以提高 Terms 聚合的精准度

数据建模及重要性

  • 数据建模
    • ES 如何处理管理关系 / 数据建模的常见步骤 / 建模的最佳实践
  • 建模相关的工具
    • Index Template / Dynamic Template / Ingest Node / Update By Query / Reindex / Index Alias
  • 最佳实践
    • 避免过多的字段 / 避免 wildcard 查询 / 在 Mapping 中设置合适的字段

保护你的数据

集群身份认证与用户鉴权

  • 如何使用 X-Pack Security 保护你的数据
  • Elasticsearch 中 RBAC 的机制和默认创建的用户和角色
  • 配置 Elasticsearch 和 Kibana 开启身份认证和用户监权
  • 使用 Native Realm, 通过 API 和 Kibana 管理用户分组和权限

集群内部间的安全通信

  • 为什么要加密通讯

    • 加密数据 — 避免数据抓包,敏感信息泄露
    • 验证身份 — 避免 Impostor Node
    • Data / Cluster State
  • 创建 Certificate Authority (CA) 和节点的 Certificates

  • 配置 Elasticsearch 节点间通信加密

集群与外部间的安全通信

配置使用 HTTPS 协议

image-20210113180159871

水平扩展 Elasticsearch 集群

常见的集权部署方式

节点类型

  • 不同角色的节点
    • Master eligible / Data / Ingest / Coordinating/ Machine Learning
  • 在开发环境中,一个节点可承担多种角色
  • 在生产环境中
    • 根据数据量,写入和查询的吞吐量,选择合适的部署方式
    • 建议设置单一角色的节点 (dedicated node)

image-20210113180859820

Hot&Warm 架构与 ShardFiltering

什么是 Hot & Warm ArchitectureHot & Warm Architecture

以古时

数据通常不会有 Update 操作;适用于 Time based 索引数据 (生命周期管理) , 同时数据量比较大的场景。

引入 Warm 节点,低配置大容量的机器存放老数据,以降低部署成本

两类数据节点,不同的硬件配置

Hot 节点 (通常使用 SSD) : 索引有不断有新文档写入。通常使用 SSD

Warm 节点 (通常使用 HDD) : 索引不存在新数据的写入;同时也不存在大量的数据查询