一.Elasticsearch7.x简介
1.1概述
Elasticsearch官网:https://www.elastic.co/cn/products/elasticsearch 。
Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,能够达到实时、稳定、可靠、快速搜索。也可以看做是布式的实时文件存储,每个字段都能被索引并可被搜索。
目前大多数公司把Elasticsearch作为elk日志系统中日志数据储存和实时搜索工具。这一部分用户,他们注重的是数据的实时写入,在大量日志数据产生时,不堆积。另一部分公司,把Elasticsearch作为全文搜索工具,一次会在几千万上亿条数据中进行搜索、聚合,对数据写入效率要求不高,注重的是搜索效率。
1.2 什么是全文搜索
什么是全文搜索引擎?
百度百科中的定义:
全文搜索引擎是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。
从定义中我们已经可以大致了解全文检索的思路了,为了更详细的说明,我们先从生活中的数据说起。
我们生活中的数据总体分为两种:结构化数据 和 非结构化数据。
- 结构化数据: 指具有固定格式或有限长度的数据,如数据库,元数据等。
- 非结构化数据: 非结构化数据又可称为全文数据,指不定长或无固定格式的数据,如邮件,word文档等。
当然有的地方还会有第三种:半结构化数据,如XML,HTML等,当根据需要可按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。
根据两种数据分类,搜索也相应的分为两种:结构化数据搜索和非结构化数据搜索。
对于结构化数据,我们一般都是可以通过关系型数据库(mysql,oracle等)的 table 的方式存储和搜索,也可以建立索引。
对于非结构化数据,也即对全文数据的搜索主要有两种方法:顺序扫描法,全文检索。
顺序扫描:通过文字名称也可了解到它的大概搜索方式,即按照顺序扫描的方式查询特定的关键字。
例如给你一张报纸,让你找到该报纸中“RNG”的文字在哪些地方出现过。你肯定需要从头到尾把报纸阅读扫描一遍然后标记出关键字在哪些版块出现过以及它的出现位置。
这种方式无疑是最耗时的最低效的,如果报纸排版字体小,而且版块较多甚至有多份报纸,等你扫描完你的眼睛也差不多了。
全文搜索:对非结构化数据顺序扫描很慢,我们是否可以进行优化?把我们的非结构化数据想办法弄得有一定结构不就行了吗?将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这种方式就构成了全文检索的基本思路。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
还以读报纸为例,我们想关注最近英雄联盟S8全球总决赛的新闻,假如都是 RNG 的粉丝,如何快速找到 RNG 新闻的报纸和版块呢?全文搜索的方式就是,将所有报纸中所有版块中关键字进行提取,如"EDG","RNG","FW","战队","英雄联盟"等。然后对这些关键字建立索引,通过索引我们就可以对应到该关键词出现的报纸和版块。注意区别目录搜索引擎。
1.3 为什么要用全文搜索搜索引擎
为什么要用搜索引擎?我们的所有数据在数据库里面都有,而且 Oracle、SQL Server 等数据库里也能提供查询检索或者聚类分析功能,直接通过数据库查询不就可以了吗?确实,我们大部分的查询功能都可以通过数据库查询获得,如果查询效率低下,还可以通过建数据库索引,优化SQL等方式进行提升效率,甚至通过引入缓存来加快数据的返回速度。如果数据量更大,就可以分库分表来分担查询压力。
那为什么还要全文搜索引擎呢?我们主要从以下几个原因分析:
-
数据类型
全文索引搜索支持非结构化数据的搜索,可以更好地快速搜索大量存在的任何单词或单词组的非结构化文本。
例如 Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。 -
索引的维护
一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。进行全文检索需要扫描整个表,如果数据量大的话即使对SQL的语法优化,也收效甚微。建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。
什么时候使用全文搜索引擎:
- 搜索的数据对象是大量的非结构化的文本数据。
- 文件记录量达到数十万或数百万个甚至更多。
- 支持大量基于交互式文本的查询。
- 需求非常灵活的全文搜索查询。
- 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
- 对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。
1.4 Lucene vs Solr vs ElasticSearch
现在主流的搜索引擎大概就是:Lucene,Solr,ElasticSearch。
它们的索引建立都是根据倒排索引的方式生成索引,何谓倒排索引?
维基百科
倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。
Elasticsearch是一个开源(Apache 2许可证),是一个基于Apache Lucene库构建的RESTful搜索引擎。
Elasticsearch是在Solr之后几年推出的。它提供了一个分布式,多租户能力的全文搜索引擎,具有HTTP Web界面(REST)和无架构JSON文档。Elasticsearch的官方客户端库提供Java,Groovy,PHP,Ruby,Perl,Python,.NET和Javascript。
分布式搜索引擎包括可以划分为分片的索引,并且每个分片可以具有多个副本。每个Elasticsearch节点都可以有一个或多个分片,其引擎也可以充当协调器,将操作委派给正确的分片。
Elasticsearch可通过近实时搜索进行扩展。
Solr与Elasticsearch差异清单:
特征 | Solr/SolrCloud | Elasticsearch |
---|---|---|
社区和开发者 | Apache 软件基金和社区支持 | 单一商业实体及其员工 |
节点发现 | Apache Zookeeper,在大量项目中成熟且经过实战测试 | Zen内置于Elasticsearch本身,需要专用的主节点才能进行分裂脑保护 |
碎片放置 | 本质上是静态,需要手动工作来迁移分片,从Solr 7开始 - Autoscaling API允许一些动态操作 | 动态,可以根据群集状态按需移动分片 |
高速缓存 | 全局,每个段更改无效 | 每段,更适合动态更改数据 |
分析引擎性能 | 非常适合精确计算的静态数据 | 结果的准确性取决于数据放置 |
全文搜索功能 | 基于Lucene的语言分析,多建议,拼写检查,丰富的高亮显示支持 | 基于Lucene的语言分析,单一建议API实现,高亮显示重新计算 |
DevOps支持 | 尚未完全,但即将到来 | 非常好的API |
非平面数据处理 | 嵌套文档和父-子支持 | 嵌套和对象类型的自然支持允许几乎无限的嵌套和父-子支持 |
查询DSL | JSON(有限),XML(有限)或URL参数 | JSON |
索引/收集领导控制 | 领导者安置控制和领导者重新平衡甚至可以节点上的负载 | 不可能 |
机器学习 | 内置 - 在流聚合之上,专注于逻辑回归和学习排名贡献模块 | 商业功能,专注于异常和异常值以及时间序列数据 |
1.5 Elasticsearch 7.x 新特性
学习技术栈得看版本,那么 Elasticsearch 7.x 有什么好的特性呢?
ES 7.0 是 2019 年 4 月份发布的,底层是 Lucene 8.0。其他还有需要了解的是:
- 废除单个索引下多 Type 的支持
- ES Security 免费使用
- ECK – ES Operator on K8s
- 新功能:New Cluster coordination
- 新功能:完整的 High Level REST Client
- 新功能:Script Score Query
- 性能:默认 Primary Shard 数从 5 到 1 ,避免 Over Sharding;性能优化更快的 Top K
二.Elasticsearch 7.x安装与启动(Windows)
2.1 下载 Elasticsearch 7.4.0
下载地址:https://www.elastic.co/cn/downloads/elasticsearch
1571476306687.png如图,下载对应需要的 ES 。我这边是 Windows,所以直接下载了 Windows的版本。另外 ES 支持 Docker 方式启动。另外,ES 7.x 不需要本地 JDK 环境支持:
- ES 5,安装需要 JDK 8 以上
- ES 6.5,安装需要 JDK 11 以上
- ES 7.2.1,内置了 JDK 12
下载完后,ES 文件目录结构如下图所示:
1571476365096.pngElasticsearch 7.4.0 目录结构如下:
- bin :脚本文件,包括 ES 启动 & 安装插件等等
- config : elasticsearch.yml(ES 配置文件)、jvm.options(JVM 配置文件)、日志配置文件等等
- jdk: 内置的 JDK,JAVA_VERSION="12.0.1"
- lib : 类库
- logs : 日志文件
- modules : ES 所有模块,包括 X-pack 等
- plugins : ES 已经安装的插件。默认没有插件
具体看看关键的 jvm.options JVM 配置文件,默认配置如下:
-Xms1g
-Xmx1g
ES 默认安装后设置的堆内存是 1 GB,对于任何业务来说这个设置肯定是少了。那设置多少?
推荐:如果足够的内存,也尽量不要 超过 32 GB。即每个节点内存分配不超过 32 GB。 因为它浪费了内存,降低了 CPU 的性能,还要让 GC 应对大内存。如果你想保证其安全可靠,设置堆内存为 31 GB 是一个安全的选择。
上述推荐,理由来自《堆内存:大小和交换编辑》:https://www.elastic.co/guide/cn/elasticsearch/guide/current/heap-sizing.html
2.2 启动 Elasticsearch 7.4.0
启动方式很简单,在 ES 根目录下面,执行启动脚本文件:
cd elasticsearch-7.4.0/bin
elasticsearch
运行完后,会出现下面的日志:
1571476890166.png 1571476916190.png日志中有两个信息需要注意:
- 本机环境是 JDK 8 ,它会提醒后面版本需要 JDK 11 支持。但它是向下兼容的
- 表示本机 ES 启动成功 [DESKTOP-9U6FM10] started
2.3 验证是否启动成功
打开浏览器,输入 http://localhost:9200/ 地址,然后可以得到下面的信息:
1571477056271.png{
"name" : "DESKTOP-9U6FM10",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "x35OuAezQiSjHAZaJdzuhg",
"version" : {
"number" : "7.4.0",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "22e1767283e61a198cb4db791ea66e3f11ab9910",
"build_date" : "2019-09-27T08:36:48.569419Z",
"build_snapshot" : false,
"lucene_version" : "8.2.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
重点几个关注下即可:
-
name : 默认启动的时候指定了 ES 实例名称,name 为 BYSocketdeMacBook-Pro-2.local
-
cluster_name : 默认名为 elasticsearch
-
version :版本信息
同样通过 http://localhost:9200/_cat/nodes?v 地址,可以看到当前节点信息,如下:
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
127.0.0.1 27 46 6 dilm * DESKTOP-9U6FM10
2.4 单机集群多个 ES 实例安装
单机多个 ES 实例,形成一个 ES 单机伪集群,启动脚本如下:
bin/elasticsearch -E node.name=node01 -E cluster.name=bysocket_es_cluster -E path.data=node01_data -d
bin/elasticsearch -E node.name=node02 -E cluster.name=bysocket_es_cluster -E path.data=node02_data -d
bin/elasticsearch -E node.name=node03 -E cluster.name=bysocket_es_cluster -E path.data=node03_data -d
命令简单解释如下:
- node.name : ES 节点名称,即实例名
- cluster.name : ES 集群名称
- path.data : 指定了存储文档数据目录
执行完脚本后,需要等一会 ES 启动,也可以查看 logs 看看执行情况。
打开浏览器,输入 http://localhost:9200/_cat/nodes?v 地址,可以看到启动情况:node01 为当前 master 节点
1571477914558.png2.5 ElasticSearch7.x—head插件安装
2.5.1 下载head插件,地址:https://github.com/mobz/elasticsearch-head
2.5.2 解压到非es安装目录的任意目录
2.5.3 下载并安装node.js
2.5.4 安装grunt
elasticsearch-head-master]# npm install -g grunt-cli
elasticsearch-head-master]# npm install
2.5.5 运行
进入head插件解压目录,cmd输入npm install
将安装的grunt安装到本地,
安装成功后执行grunt server
2.5.6 浏览器访问: http://localhost:9100/
1571492720208.png2.5.7 修改es配置文件:elasticsearch.yml
http.cors.enabled: true
http.cors.allow-origin: "*"
2.5.8 重启es与head插件,再次访问: http://localhost:9100/
1571493180655.png三.Elasticsearch 7.x安装与启动(Linux)
在linux下安装elasticsearch:
- 下载压缩包, 并解压
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.9.3-linux-x86_64.tar.gz
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.9.3-linux-x86_64.tar.gz.sha512
shasum -a 512 -c elasticsearch-7.9.3-linux-x86_64.tar.gz.sha512
tar -xzf elasticsearch-7.9.3-linux-x86_64.tar.gz
cd elasticsearch-7.9.3/
- 修改配置文件: $ES_HOME/config/elasticsearch.yml, 主要修改es数据路径和es日志路径, 已经网络和端口
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
#
path.data: /home/esdata
#
# Path to log files:
#
path.logs: /home/log/eslog
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 10.10.1.11
#
# Set a custom port for HTTP:
#
http.port: 9200
- 修改$ES_HOME/config/jvm.options, 根据机器性能修改es内存
# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space
-Xms2g
-Xmx2g
- 以守护者模式启动elasticsearch
./bin/elasticsearch -d
- 访问页面(ip+默认端口):
http://10.10.1.11:9200
如果能访问则安装成功!
在linux下安装kibana:
1. 下载压缩包, 并解压
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.9.3-linux-x86_64.tar.gz
tar -xzf kibana-7.9.3-linux-x86_64.tar.gz
2.修改配置文件 kibana-7.9.3-linux-x86_64/config/kibana.yml, 主要配置elasticsearch相关:
# The URLs of the Elasticsearch instances to use for all your queries.
elasticsearch.hosts: ["http://10.10.1.11:9200"]
# 如果生产环境es设置了密码, 使用此配置
elasticsearch.username: "elastic"
elasticsearch.password: "<password>"
# Supported languages are the following: English - en , by default , Chinese - zh-CN .
i18n.locale: "zh-CN"
- 以守护者模式启动kibana:
./bin/kibana -d
- 访问页面(ip+默认端口):
http://10.10.1.11:5601
如果能访问则安装成功!
额外配置(根据机器性能适当调整):
- 设置虚拟内存大小:vim /etc/sysctl.conf, 官方建议设置为此值
vm.max_map_count= 262144
- #禁用内存与硬盘交换 (防止内存不够,交换到磁盘,这样会把ES的速度拉下来):vim /etc/sysctl.conf
vm.swappiness = 1
- 设置文件句柄数: vim /etc/security/limits.conf, 可以参考如下配置:
root soft nofile 65535
root hard nofile 65535
* soft nofile 65535
* hard nofile 65535
(非必须)配置elasticsearch密码
- 修改配置文件: $ES_HOME/config/elasticsearch.yml, 并重新启动es
xpack.security.enabled: true
xpack.license.self_generated.type: basic
xpack.security.transport.ssl.enabled: true
- 进入elasticsearch/bin目录, 执行, 按提示修改密码, 注: 测试发现只有用户:elastic拥有全部权限, 其他用户需要自行配置权限
./elasticsearch-setup-passwords interactive
- 配置完成之后, 所有对elasticsearch的请求, 都需要配置用户名密码, 如kibana
四.Elasticsearch文档、索引和 REST API
索引(Index)、类型(Type)、文档(Document)
- 索引Index是含有相同属性的文档集合。索引在ES中是通过一个名字来识别的,且必须是英文字母小写,且不含中划线(-);可类比于 MySQL 中的 database ;在 7.0中,由于类型(Type)的移除,我们可以理解为,一个索引就是一张 table。
- 一个索引中可以定义一个或多个类型Type,文档必须属于一个类型;可类比于 MySQL 中的 table;
- 文档Document是可以被索引的基本数据单位。文档是Elasticsearch中最小的数据存储单位。可类比于 MySQL 中 一个table 中的一行记录
注意事项:
从ES6.0开始,官方便不建议一个索引中创建多个类型;在ES7.0中,更是移除了类型(Type)这个概念。为什么呢?
在Elasticsearch索引中,不同类型(Type)中具有相同名称的字段在内部由相同的Lucene字段支持。一个index中多个Type在Lucene中会有许多问题。具体的可以参考官方说明:Removal of mapping types
更多细节可以参考: https://mp.weixin.qq.com/s/O8Pvd8OHBDXiBUrGbprmJQ
五.Elasticsearch配置
5.1 ES的集群配置
ES的集群配置(都是修改ES的配置文件elasticsearch.yml)主要分为:主节点配置和从节点配置。
配置主节点jack_master:
# 配置分布式主节点
# 集群名
cluster.name: jack
# 节点名
node.name: jack_master
# 是否为主节点
node.master: true
# 绑定IP
network.host: 127.0.0.1
然后再次解压ES安装包到其他目录,每解压一个出来就可以配置一个ES的从节点,比如这里是解压两次就可以配置2个从节点,分别修改它们的配置文件让它们加入到集群jack
中:
配置从节点jack_slave1
:
# 配置从节点的信息
# 集群名一定要和主节点所在集群名一致,默认集群按名字匹配
cluster.name: jack
# 节点名
node.name: jack_slave1
# 绑定IP
network.host: 127.0.0.1
# 默认端口是9200,如果不配置就会和主节点端口冲突
http.port: 8100
# 用于寻找集群,不加这个配置这个节点是游离在集群之外的
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]
配置从节点jack_slave2
:
# 配置从节点的信息
# 集群名一定要和主节点所在集群名一致,默认集群按名字匹配
cluster.name: jack
# 节点名
node.name: jack_slave2
# 绑定IP
network.host: 127.0.0.1
# 默认端口是9200,如果不配置就会和主节点端口冲突
http.port: 8200
# 用于寻找集群,不加这个配置这个节点是游离在集群之外的
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]
就照着上面的步骤ES可以轻松实现扩容,启动的时候注意节点启动顺序,先主节点再从节点
5.2 ES配置
ES有很好的默认值,所以只需要很少的配置,可以使用Cluster Update Settings API在正在运行的群集上更改大多数设置。主要是指本地的一些配置,借助于配置文件进行配置,主要分为3块:
elasticsearch.yml,ES的配置文件;
jvm.options,ES的JVM配置文件;
log4j2.properties,ES的日志配置文件;
关于配置文件的路径,默认是解压缩包的解压路径$ES_HOME/config,但是具体的配置路径可以通过ES_PATH_CONF环境变量来改变,比如:
ES_PATH_CONF=/path/to/my/config ./bin/elasticsearch
ES的配置文件是yaml格式,下面是配置data和logs目录的方法:
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
环境变量还可以使用${...}这样的形式配置,比如:
node.name: ${HOSTNAME}
network.host: ${ES_NETWORK_HOST}
ES配置文件中,可配置的参数有(汇总,来源于网络):
# es集群名,默认是elasticsearch,es会自动发现在同一网段下的es,如果在同一网段下有多个集群,就可以用这个属性来区分不同的集群
cluster.name: elasticsearch
# 节点名,默认随机指定一个name列表中名字,该列表在es的jar包中config文件夹里name.txt文件中,6.4.0版本中好像已经没有这个文件了
node.name: "Franz Kafka"
# 候选资格,表示该节点是否有资格被选举成为master,默认是true,es默认集群中的第一台机器为master,如果这台机挂了就会重新选举master
node.master: true
# 表示该节点是否存储索引数据,默认为true
node.data: true
# 设置索引分片个数,默认为5
index.number_of_shards: 5
# 设置索引副本个数,默认为1
index.number_of_replicas: 1
# 设置ES配置文件的存储路径,默认是es根目录下的config文件夹下
path.conf: /path/to/conf
# 设置索引数据的存储路径,默认是es根目录下的data文件夹下,可以设置多个存储路径,用逗号隔开,例:path.data: /path/to/data1,/path/to/data2
path.data: /path/to/data
# 设置临时文件的存储路径,默认是es根目录下的work文件夹
path.work: /path/to/work
# 设置日志文件的存储路径,默认是es根目录下的logs文件夹
path.logs: /path/to/logs
# 设置插件的存放路径,默认是es根目录下的plugins文件夹
path.plugins: /path/to/plugins
# 设置ES可以是否可以锁定内存,因为当jvm开始swapping时es的效率会降低,所以要保证它不swap,可以把ES_MIN_MEM和ES_MAX_MEM两个环境变量设置成同一个值,并且保证机器有足够的内存分配给es。同时也要允许ES的进程可以锁住内存,linux下可以通过`ulimit -l unlimited`命令
bootstrap.mlockall: true
# 设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0
network.bind_host: 192.168.0.1
# 设置其它节点和该节点交互的ip地址(真实IP),如果不设置它会自动判断
network.publish_host: 192.168.0.1
# 这个参数是用来同时设置bind_host和publish_host上面两个参数
network.host: 192.168.0.1
# 设置节点间交互的tcp端口,默认是9300
transport.tcp.port: 9300
# 设置是否压缩tcp传输时的数据,默认为false,不压缩
transport.tcp.compress: true
# 设置对外服务的http端口,默认为9200
http.port: 9200
# 设置内容的最大容量,默认100mb
http.max_content_length: 100mb
# 是否使用http协议对外提供服务,默认为true,开启
http.enabled: false
# gateway的类型,默认为local即为本地文件系统,可以设置为本地文件系统,分布式文件系统,hadoop的HDFS,和amazon的s3服务器,其它文件系统的设置方法下次再详细说
gateway.type: local
# 设置集群中N个节点启动时进行数据恢复,默认为1
gateway.recover_after_nodes: 1
# 设置初始化数据恢复进程的超时时间,默认是5分钟
gateway.recover_after_time: 5m
# 设置这个集群中节点的数量,默认为2,一旦这N个节点启动,就会立即进行数据恢复
gateway.expected_nodes: 2
# 初始化数据恢复时,并发恢复线程的个数,默认为4
cluster.routing.allocation.node_initial_primaries_recoveries: 4
# 添加删除节点或负载均衡时并发恢复线程的个数,默认为4
cluster.routing.allocation.node_concurrent_recoveries: 2
# 设置数据恢复时限制的带宽,如入100mb,默认为0,即无限制
indices.recovery.max_size_per_sec: 0
# 来限制从其它分片恢复数据时最大同时打开并发流的个数,默认为5
indices.recovery.concurrent_streams: 5
# 设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点。默认为1,对于大的集群来说,可以设置大一点的值(2-4)
discovery.zen.minimum_master_nodes: 1
# 设置集群中自动发现其它节点时ping连接超时时间,默认为3秒,对于比较差的网络环境可以高点的值来防止自动发现时出错
discovery.zen.ping.timeout: 3s
# 设置是否打开多播发现节点,默认是true
discovery.zen.ping.multicast.enabled: false
# 设置集群中master节点的初始列表,可以通过这些节点来自动发现新加入集群的节点
discovery.zen.ping.unicast.hosts: ["host1", "host2:port", "host3[portX-portY]"]
5.3 ES的JVM配置
ES的java虚拟机设置,很少需要手动配置,如果需要改动,绝大部分是改动堆的大小,设置JVM首选方式是配置jvm.options文件,这个配置文件包含了一系列分隔线分隔的JVM参数,使用的是一种特殊的语法,具体规则如下:
仅包含空格的行将被忽略;
以#开头的行被视作注释;
以-开头的行被视作JVM选项,这个选项独立于JVM而应用,如-Xmx2g;
以数字开头后面接-:符号的,也被视作JVM选项,但仅在JVM的版本大于等于这个数字时才使用,如8-:-Xmx2g(大于等于JDK8版本才适用);
以数字开头后面接:-符号的,也被视作JVM选项,但仅在JVM版本和数字相同时才适用,如8:-Xmx2g(仅适用于JDK8);
以数字开头后接-数字:的,也被视作JVM想象,但仅在JVM版本在这两个数字区间内,如8-9:-Xmx2g;
除此之外的所有行都不生效;
5.4 ES的安全配置
ES中有些配置是敏感的,仅通过系统文件权限来保护是不够的,为此,Elasticsearch提供了一个密钥库和elasticsearch-keystore工具来管理密钥库中的设置。这些设置就像elasticsearch.yml中的常规配置一样,需要在集群中的每个节点进行指定,目前,所有安全设置都是基于特定于节点的设置,每个节点上的值必须相同。
5.5 ES的日志配置
ES采用log4j 2作日志管理,log4j 2可以使用log4j2.properties文件进行配置,ES就暴露出三个属性:{sys:es.logs.cluster_name}(解析为集群名,在默认配置中用作日志文件名的前缀)和${sys:es.logs.node_name}(如果通过node.name显式的设置了节点名称,将解析为节点名),可以在配置文件中引用来确定日志文件的位置。
加设置ES的根目录是/var/log/elasticsearch,集群名为production,下面是ES中log4j 2的部分配置:
# 配置RollingFile的附加器
appender.rolling.type = RollingFile
appender.rolling.name = rolling
# %ES_Home%/节点名.log就是日志文件的路径和名字,即/var/log/elasticsearch/production.log
appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%.-10000m%n
# 滚动日志到/var/log/elasticsearch/production-yyyy-MM-dd-i.log,日志将在每个卷上压缩,i递增
appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}-%i.log.gz
appender.rolling.policies.type = Policies
# 使用基于时间的滚动策略
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
# 每1天滚动日志
appender.rolling.policies.time.interval = 1
# 在日界上对齐卷(而不是每隔二十四小时滚动)
appender.rolling.policies.time.modulate = true
# 使用基于大小的滚动策略
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
# 256 MB后滚动日志
appender.rolling.policies.size.size = 256MB
# 滚动日志时使用删除操作
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.fileIndex = nomax
appender.rolling.strategy.action.type = Delete
appender.rolling.strategy.action.basepath = ${sys:es.logs.base_path}
# 仅删除与文件模式匹配的日志
appender.rolling.strategy.action.condition.type = IfFileName
# 该模式仅删除主日志
appender.rolling.strategy.action.condition.glob = ${sys:es.logs.cluster_name}-*
# 仅在我们累积了太多压缩日志时才删除
appender.rolling.strategy.action.condition.nested_condition.type = IfAccumulatedFileSize
# 压缩日志的大小条件为2 GB
appender.rolling.strategy.action.condition.nested_condition.exceeds = 2GB
【注意】可以使用.gz替换appender.rolling.filePattern属性中的.zip(使用zip格式压缩滚动日志),如果删除.gz扩展名,则日志将不会在滚动时进行压缩。
如果想指定时间段内保留日志文件,可以使用带有删除操作的翻转策略。
# 配置DefaultRolloverStrategy
appender.rolling.strategy.type = DefaultRolloverStrategy
# 配置删除操作以处理翻转
appender.rolling.strategy.action.type = Delete
# Elasticsearch日志的基本路径
appender.rolling.strategy.action.basepath = ${sys:es.logs.base_path}
# 处理翻转时应用的条件
appender.rolling.strategy.action.condition.type = IfFileName
# 从基本路径中删除文件(和全局${sys:es.logs.cluster_name}-*匹配的),这只需要删除已滚动的Elasticsearch日志,但不能删除已弃用和慢速日志
appender.rolling.strategy.action.condition.glob = ${sys:es.logs.cluster_name}-*
# 应用于与glob匹配的文件的嵌套条件
appender.rolling.strategy.action.condition.nested_condition.type = IfLastModified
# 保留日志七天
appender.rolling.strategy.action.condition.nested_condition.age = 7D
六. ElasticSearch的基本CRUD和postman调用一些常用的api
- ES是面向文档的,文档中存储的数据结构,与面向对象的数据结构是一样的,基于这种文档数据结构,es可以提供复杂的索引,全文检索,分析聚合等功能
- es的document用json数据格式来表达.
es提供了一套api,叫做cat api,可以查看es中各种各样的数据:
-
1.查看集群的健康状态:get请求: http://localhost:9200/_cat/health?v
-
2.快速查看有那些索引;get请求:http://localhost:9200/_cat/indices
-
3.简单的索引操作:
添加:PUT请求: http://localhost:9200/cyytest/
- 4.删除索引:DELETE: http://localhost:9200/cyytest/
- 5.创建文档: POST,article:就是文档name
_id是由系统自动生成的,在添加的时候可以加在请求路径的后面
- 6.查询文档 GET方式: http://localhost:9200/cyytest/article/2
-
7.替换文档内容-POST(修改body中的内容即可) :http://localhost:9200/cyytest/article/2
1571565010556.png
- 8.修改文档内容 -POST: http://localhost:9200/cyytest/article/2/_update
1571565256031.png
七. SpringBoot 整合 es
创建 springboot 项目
首先创建一个 springboot 项目,然后引入high level client
的依赖,pom 文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cyy.es</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<elasticsearch.version>7.4.0</elasticsearch.version>
</properties>
<!--注意:如果使用了parent那么需要在此定义es版本号,因为spring-boot-start-parent中已经定义了es相关依赖的版本号
,high-level-client中的部分依赖会被覆盖成低版本的,导出出现莫名其妙的错误-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>>${elasticsearch.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>>${elasticsearch.version}</version>
</dependency>
<!--<!– https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-client –>-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>>${elasticsearch.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
注意:这里有一个依赖的大坑,要注意!
如果定义了,就必须在
中指定部分依赖的版本,否则会因为依赖版本不对出现各种莫名其妙的错误,上面注释中已经指出。
创建 util/EsUtil.java 工具类
主要功能函数如下:
预创建 index
虽然 es 在插入数据时会自动根据字段类型来创建字段定义,但是自动创建并不总是和需要相符的,比如想让某个字段不分词,或者使用其他的分词器。所以在代码中先判断 index(es7 中已经废弃了 mapping,也就是一个 index 相当于一个表)是否存在,如果不存在就创建 index.
主要代码如下:
//被@PostConstruct注释的方法将会在对应类注入到Spring后调用,确保index的生成
@PostConstruct
public void init() {
try {
if (client != null) {
client.close();
}
client = new RestHighLevelClient(RestClient.builder(new HttpHost(host, port, scheme)));
if (this.indexExist(INDEX_NAME)) {
return;
}
CreateIndexRequest request = new CreateIndexRequest(INDEX_NAME);
request.settings(Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 2));
request.mapping(CREATE_INDEX, XContentType.JSON);
CreateIndexResponse res = client.indices().create(request, RequestOptions.DEFAULT);
if (!res.isAcknowledged()) {
throw new RuntimeException("初始化失败");
}
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
插入或者更新一个对象
通过指定 id,如果此 id 存在那么就是更新,否则是插入。
public void insertOrUpdateOne(String index, EsEntity entity) {
IndexRequest request = new IndexRequest(index);
request.id(entity.getId());
request.source(JSON.toJSONString(entity.getData()), XContentType.JSON);
try {
client.index(request, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
批量插入
high level client 提供了方便的批量操作接口,如下所示:
public void insertBatch(String index, List<EsEntity> list) {
BulkRequest request = new BulkRequest();
list.forEach(item -> request.add(new IndexRequest(index).id(item.getId())
.source(JSON.toJSONString(item.getData()), XContentType.JSON)));
try {
client.bulk(request, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
批量删除
和上面一样同样用到了BulkRequest
public <T> void deleteBatch(String index, Collection<T> idList) {
BulkRequest request = new BulkRequest();
idList.forEach(item -> request.add(new DeleteRequest(index, item.toString())));
try {
client.bulk(request, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
搜索
通过构建SearchSourceBuilder
查询参数
public <T> List<T> search(String index, SearchSourceBuilder builder, Class<T> c) {
SearchRequest request = new SearchRequest(index);
request.source(builder);
try {
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
List<T> res = new ArrayList<>(hits.length);
for (SearchHit hit : hits) {
res.add(JSON.parseObject(hit.getSourceAsString(), c));
}
return res;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
delete by query
es 插入数据容易,删除就比较麻烦了,特别是根据条件删除。
public void deleteByQuery(String index, QueryBuilder builder) {
DeleteByQueryRequest request = new DeleteByQueryRequest(index);
request.setQuery(builder);
//设置批量操作数量,最大为10000
request.setBatchSize(10000);
request.setConflicts("proceed");
try {
client.deleteByQuery(request, RequestOptions.DEFAULT);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
可通过测试类com.fanxb.esdemo.service.BookServiceTest
查看运行结果。
八. Elasticsearch Top5典型应用场景
8.1 记录和日志分析
对于熟悉Elasticsearch的人来说,这个应该不足为奇。围绕Elasticsearch构建的生态系统使其成为最容易实施和扩展日志记录解决方案之一。我们平台上的许多用户都没有什么不同,他们利用这一点来将日志记录添加到他们的主要用例中,或者将我们纯粹用于日志记录。
从Beats,Logstash到Ingest Nodes,Elasticsearch为您提供了大量的选项,可以在任何地方获取数据并将其索引化。然后,使用Kibana工具使您能够创建丰富的仪表板和分析,而Curator使得您自动化管理索引的生命周期。
8.2 采集和组合公共数据
与日志数据一样,Elastic Stack拥有大量工具,可以轻松抓取和索引远程数据。此外,与大多数文档存储一样,非严格的模式使Elasticsearch可以灵活地接收多个不同的数据源,并能使得这些数据可以管理和搜索。
您可以查看的一个很酷的例子是我们的Twitter连接器(如下图所示),它允许您设置在Twitter上看到的主题标签,然后采集这些主题标签的相关推文并在Kibana中进行分析。我们在核心Elastic Stack组件上构建了该产品,并添加了一些额外的部件以帮助它扩展。
8.3 全文搜索
毫无疑问,作为Elasticsearch的核心功能,全文搜索在此列表中占据重要位置。令人惊讶的是,我们的客户群中的全文检索的应用远远超出了传统的企业搜索或电子商务。
从欺诈检测/安全到协作等,我们的用户已经证明Elasticsearch的搜索功能强大,灵活,并且包含大量工具以使搜索更容易; Elasticsearch有自己的查询DSL、内置的自动补全功能等等。
8.4 事件数据和指标
Elasticsearch还可以很好地处理时间序列数据,如指标(metrics )和应用程序事件。这是另一个巨大的Beats生态系统允许您轻松获取常见应用程序数据的区域。无论您使用何种技术,Elasticsearch都有很好的机会获取开箱即用的指标和事件…,添加该功能非常简单
8.5 数据可视化
凭借大量的图表选项,地理数据的平铺服务和时间序列数据的TimeLion,Kibana是一款功能强大且易于使用的可视化工具。对于上面的每个用例,Kibana都会处理一些可视化组件。
一旦您对各种数据提取工具感到满意,您就会发现Elasticsearch + Kibana将成为您可视化数据的首选工具。
虽然并非每个用例都是如此,但这Top5是我们服务中统计出的最典型应用。 Elasticsearch和Elastic Stack的其他部分已被证明是非常通用的,正如您在上面所看到的,有多种方法可以将Elasticsearch集成到您今天所做的事情中并获得额外的洞察力。对我而言,这是Elasticsearch最酷的部分,它能够增强您已经使用的技术,而不仅仅是另一个数据库来存储您的数据。
网友评论