文章目录
- 引擎(搜索引擎)
- Solr查询快,但更新索引时慢、插入删除慢
- Elasticsearch建立索引快、查询慢
- Elasticsearch VS 数据库:模糊查询
- 为什么可以实现快速的“模糊匹配”/“相关性查询”? =》分词 + 倒排索引
- ELK(ES + Kibana + Logstash )简介
- Elasticsearch简介
- Lucene
- Kibana
- Logstash
- ELK安装配置
- 安装ES
- docker安装
- 安装kibana
- Logstash
- ES文件夹内容
- ES常见术语
- ES架构(Master-slave 架构)
- 集群cluster
- 节点Node(运行着Elasticsearch进程的机器)
- 种类
- 分片
- 作用
- ES流程
- 写入
- 路由
- Warning
- 更新和删除
- 查询
- 途径
- 三阶段
- 索引
- 正向索引 VS 倒排索引
- 分词器
- 英文分词器
- 中文分词器
- 分词器组成部分
- ES数据结构
- ES开箱使用
- 数据类型
- ES RESTful API
- CRUD
- 添加
- 指定字段索引(创建规则)并映射字段类型
- 获取建立的规则
- 删除
- 修改
- put覆盖
- 使用post的update
- 查询
- 简单条件查询
- 查询匹配match
- 多条件查询(bool)
- 匹配数组:query
- 精确查询item(完整词查询,不可分)
- 高亮查询highlight
- 自定义前后缀
- 查询DSL(条件语句)
- 指定搜索的字段`fields`
- 过滤
- 无需查询即可进行过滤
- 过滤器
- bool查询
- must:返回的文档必须满足must子句的条件,并且参与计算分值
- filter:返回的文档必须满足filter子句的条件。但是不会像Must一样,参与计算分值。
- should
- must_not
- text VS keyword
- get _cat/xxx获取当前更多信息
- 常用命令
- problem
- 跨域访问(跨端口)导致集群无法连接
- 汉化Kibana
引擎(搜索引擎)
Solr查询快,但更新索引时慢、插入删除慢
Elasticsearch建立索引快、查询慢
常用于日志收集(分析)系统、实时警报
应用场景:
- 维基百科:全文检索、高亮、搜索推荐。
- The Guardian (国外新闻网站):用户行为日志(点击、浏览、收藏、评论) +社交网络数据(对某某新闻的相关看法)、数据分析提供给文章作者以便了解公众反馈。
- Stack Overflow :结合全文搜索与地理位置查询,以及more-like-this功能来找到相关的问题和答案。
- GitHub:使用Elasticsearch检索1300亿行的代码。
- 电商网站:检索商品、商品价格监控网站(发送降价通知消息给用户)。
- BI系统、商业智能、Business Intelligence:BI分析一下某某区域最近3年的用户消费金额的趋势以及用户群体的组成构成。
- 站内搜索(电商,招聘,门户,等等),IT系统搜索(OA,CRM,ERP,等等),数据分析(ES热门的一个使用场景)。
Elasticsearch VS 数据库:模糊查询
-
数据库的
select * from user where name like 'xxx'
:1. 不走索引,数据库量很大时,查询慢。2. 往往会返回大量的数据。3.用户输入的内容可能并不准确。 -
Elasticsearch优势
- 模糊搜索速度很快: 写入数据到Elasticsearch的时候会进行分词。
- 搜索到的数据可以根据评分排序,过滤掉大部分的内容。
- 能匹配有相关性的记录,没有那么准确的关键字也能搜出相关的结果。
为什么可以实现快速的“模糊匹配”/“相关性查询”? =》分词 + 倒排索引
ELK(ES + Kibana + Logstash )简介
Elasticsearch简介
Elasticsearch是面向文档的一种数据库,这意味着其不再需要行列式的表格字段约束。
ES会存储整个构造好的数据或文档,然而不仅仅是储存数据,这使得文档中每个数据可以被标识,进而可以被检索。在ES中,执行index,search,sort或过滤文档等操作都不是传统意义上的行列式的数据。
ES从根本上对数据的不同思考方式也正是他能应对复杂数据结构的全文检索的原因之一。
Lucene
Elastic Search 中代码几乎全部是为搜索服务器服务的。真正处理倒排索引、具体搜索算法的,则Lucene 核心引擎。
- Lucene是一套用于全文检索和搜寻的开源程序库,由Apache软件基金会支持和提供。
- Lucene是一套信息检索工具包(jar包),并不是现成的搜索引擎产品,但可以用来制作搜索引擎产品。
- Lucene包含:索引结构、读写索引的工具、排序、搜索规则、工具类、…
Kibana
Kibana是一个针对Elasticsearch的开源分析及可视化平台 ,用来搜索、查看交互存储在Elasticsearch索引中的数据。 使用Kibana,可以通过各种图表进行高级数据分析及展示。Kibana让海量数据更容易理解。它操作简单,基于浏览器的用户界面可以快速创建仪表板( dashboard )实时显示Elasticsearch查询动态。设置Kibana非常简单。无需编码或者额外的基础架构,几分钟内就可以完成Kibana安装并启动Elasticsearch索引监测。
Logstash
Logstash是ELK的中央数据流引擎,用于从不同目标(文件/数据存储/MQ)收集的不同格式数据,经过过滤后支持输出到不同目的地(文件/MQ/redis/elasticsearch/kafka等)。
ELK安装配置
安装ES
下载:https://www.elastic.co/cn/downloads/elasticsearch
docker安装
# docker安装
sudo apt install docker
# 拉取
docker pull elasticsearch:7.14.2
# 查看镜像是否拉取到本地
docker images
# 运行
# -d : 后台运行
# -p : 指定宿主机与docker启动容器的端口映射
# --name : 为ES容器别名
# -e : 指定为单节点集群模式
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" elasticsearch:7.14.2
# 访问
curl http://localhost:9200/
- 其它配置:
ES_JAVA_OPTS
:配置JVM参数,会覆盖JAVA_OPTS中配置的相同参数。最主要的作用是指定 -Xmx 最大堆大小和 -Xms 最小堆大小(分配JVM的最小和最大内存,取决于硬件物理内存的大小,建议均设为物理内存的一半)。- server:一定要作为第一个参数,在多个CPU时性能佳
- Xms:初始Heap大小,使用的最小内存,cpu性能高时此值应设的大一些
- Xmx:java heap最大值,使用的最大内存
-v
:挂载数据卷--privileged=true
:让docker有root权限启动容器
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /home/xxx/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /home/xxx/elasticsearch/data:/usr/share/elasticsearch/data \
-v /home/xxx/elasticsearch/plugins:/usr/share/elasticsearch/plugins elasticsearch:7.14.2
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" \
-v /home/xxx/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
elasticsearch:7.14.2
安装kibana
# 拉取(与ES版本保持一致)
docker pull kibana:7.14.2
# 运行
# -e : 指定环境变量配置, 提供汉化
# --link : 建立两个容器之间的关联, kibana 关联到 es
docker run -d --name kibana --link elasticsearch:elasticsearch \
-e "I18N_LOCALE=zh-CN" -p 5601:5601 kibana:7.14.2
# 查看日志
docker logs kibana
# 访问
# http://localhost:5601/app/dev_tools#/console
进入Kibana首页选择DevTools(URL: http://localhost:5601/app/kibana#/dev_tools/console)即可输入命令向ES发出请求。
Logstash
ES文件夹内容
文件名 | 备注 |
---|---|
data | 索引数据 |
config | elastic-search的全局设置和用户具体设置(JVM,数据路径,日志路径、端口设置等) |
bin | 可执行文件,启动elasticsearch |
jdk.app | 自带的JDK |
plugins | 插件(第三方的分词器等) |
modules | elastic search自带的一些模块 |
lib | 相关jar包 |
logs | 日志 |
config:
文件名 | 备注 |
---|---|
log4j2.properties | 日志配置文件 |
jvm.options java | 虚拟机配置文件 |
elasticsearch.yml | ES配置文件(默认端口:9200) |
ES常见术语
名称 | 释义 | 备注 |
---|---|---|
Index | 文档在哪个索引存放: 相当于数据库db(Table) | |
Document | 数据库的一行记录row | Elasticsearch是面向文档的,使用JSON作为序列化格式存储整个对象。 |
Type(废除,默认类型 _doc 代替) | 文档对象类型:相当于数据库Table | 一个Index下支持多个Type =》Table Type只是Index中的虚拟逻辑分组,不同的Type应该有相似的结构。 |
Field | 数据库的Column | |
Mapping | 数据库的Schema | |
_id | 文档唯一标识 | |
_version | 数据版本 | |
DSL | ES读取API |
Elasticsearch(一般为集群)中可以包含多个索引(对应数据库) ,每个索引中可以包含多个类型(对应表) ,每个类型下又包含多个文档(对应行),每个文档中又包含多个字段(对应列)。
ES架构(Master-slave 架构)
ElasticSearch 是分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个实例。单个实例称为一个节点(node),一组节点构成一个集群(cluster)。
分片是底层的工作单元,文档保存在分片内,分片又被分配到集群内的各个节点里,每个分片仅保存全部数据的一部分。
集群cluster
一个集群是一些运行 Elastic Search 的节点服务器(node)的总称。
- 从技术上讲,一台服务器就可以是一个集群(可以跑起来多个node节点)。
节点Node(运行着Elasticsearch进程的机器)
一个Elasticsearch集群有多个Elasticsearch节点:一个主节点Master Node,多个从节点。如果主节点挂了,会选举出一个新的主节点。
- Master Node:主要负责维护索引元数据、负责切换主分片和副本分片身份等工作。
- 每个Node包含 主分片&副本分片。
一个集群中,可能包含一个或多个节点。这些节点受到集群的管理。你可以向一个集群中增加或者删除一些节点(扩容或者减容),也可以查询节点的信息(比如这个节点的 CPU 使用状况如何等等)。
https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html
种类
- 主节点master node:负责各种沟通协作节点的工作,一个集群必须有至少一个。
- 数据节点data node:搜索和数据存储。
- 写入节点ingest node:负责文档写入。
分片
分片(各节点并行,提高系统吞吐量):一个Index(数据库表)的数据我们可以分发到不同的Node上进行存储(1个Index、4个Node :设置4个分片)。
数据写入到主分片,副本分片会复制主分片的数据,读取的时候主分片和副本分片都可以读。
如果某个节点挂了,Master Node就会把对应的副本分片提拔为主分片,数据就不会丢。
作用
如果一个Index的数据量太大,只有一个分片,那只会在一个节点上存储,随着数据量的增长,一个节点未必能把一个Index存储下来。
多个分片,在写入或查询的时候就可以并行操作(从各个节点中读写数据,提高吞吐量)。
- 数据分片
- 分片sharding:分布式服务中常见的一个手段
- 把数据拆成一个个独立的单元,放到不同服务器上,再在程序里把这些数据组织起来。
- 当你的数据量越来越多时,因为一个节点装不下你的数据,你会开始需要做分片,做所谓的横向扩展。
- 副本分片(replica)和系统健壮性(Robust)
- 把同样的数据放在多个服务器
- 查询集群健康状态
ES流程
写入
-
客户端写入一条数据,Elasticsearch集群由节点来处理这次请求。
-
集群上的每个节点都是coordinating node(协调节点),协调节点表明这个节点可以做路由(请求转发)。
- coodinate(协调)节点通过hash算法可以计算出是在哪个主分片上,然后路由到对应的节点。
shard = hash(document_id) %(num_of_primary_shards)
- coodinate(协调)节点通过hash算法可以计算出是在哪个主分片上,然后路由到对应的节点。
-
主分片写完后,会将数据并行发送到副本集节点上,等到所有的节点写入成功就返回ack给协调节点,协调节点返回ack给客户端,完成一次的写入。
路由
- 数据写入内存缓冲区。
- 数据写到translog缓冲区:为防止节点宕机、内存中的数据丢失。
- 每隔1s从buffer刷新到文件系统缓存区,生成segment文件,数据才可以被检索到)。
- 清空memory buffer。
- 每隔5s,translog从buffer刷到磁盘中,生成日志文件。。
- 文件大到一定程度或者超过了30分钟,会触发commit操作,将内存中的segement文件异步刷到磁盘中,完成持久化操作。
Warning
- Elasticsearch写入的数据需要1s才能查询到。
- Elasticsearch某个节点如果挂了,可能会造成5s的数据丢失。
更新和删除
-
给对应的doc记录打上【.del】标识。
- 删除操作:打上delete状态。
- 更新操作:把原来的doc标志为delete,然后重新新写入一条数据。
-
足够多的segement文件存在时会合并成一个segement文件。合并时,把带有delete状态的doc给物理删除掉。
查询
途径
-
根据ID查询doc(实时)
1.1 检索内存的Translog文件
1.2 检索硬盘的Translog文件
1.3 检索硬盘的Segement文件 -
根据query(搜索词)去查询匹配的doc(写入后1s才能查,segement文件是每隔一秒才生成一次的)
2.1 同时查询内存和硬盘的Segement文件
public TopDocs search(Query query, int n);
public Document doc(int docID);
三阶段
- QUERY_AND_FETCH(查询完就返回整个Doc内容):只适合于只需要查一个分片的请求。
-
QUERY_THEN_FETCH
- 协调节点向目标分片发送查询的命令(转发搜索请求到主分片或者副本分片上)。
- 每个分片将搜索(过滤、排序等)结果 doc id 返回给协调节点。
- 协调节点将得到数据节点返回的doc id 聚合。然后将目标数据分片,发送抓取命令(希望拿到整个Doc记录)。
- 协调节点根据 doc id 去各个节点上拉取实际的 document 数据,最终返回给客户端。
- DFS_QUERY_THEN_FETCH(先算词出现频率和文档频率得分,再查询)
索引
正向索引 VS 倒排索引
- 正向索引:书的章节目录就是正向索引,通过章节名称就找到对应的页码。
-
倒排索引:先对目录分词,对待查找的词找到对应记录。
分词器
英文分词器
- Standard Analyzer 。按词切分,将词小写
- Simple Analyzer。按非字母过滤(符号被过滤掉),将词小写
- WhitespaceAnalyzer。按照空格切分,不转小写
- ….
中文分词器
- IK
分词器组成部分
Character Filters(文本过滤器,去除HTML)
Tokenizer(按照规则切分,比如空格)
TokenFilter(将切分后的词进行处理,比如转成小写)
ES数据结构
-
Term Dictionary:分词后的词(自动排序)
- 由于词的数量过多,无法存入内存 =》Term Index(占用空间小,放入内存,检索快)
-
Term Index:存储词的前缀,每个节点是一个字母。
- 以FST(Finite State Transducers)保存:非常节省内存、空间占用小、查询速度快。
-
PostingList(自动压缩):每个词的对应记录(文档ID)。
- Frame Of Reference(FOR)编码技术对数据压缩,节约磁盘空间。
- Roaring Bitmaps(压缩位图索引):节省空间和快速得出文档ID交并集操作的结果。
ES开箱使用
数据类型
数据类型 | |
---|---|
字符串类型 | text、keyword |
数值类型 | long、integer、short、byte、double、float、half float、scaled float |
日期类型 | date |
布尔值类型 | boolean |
二进制类型 | binary |
ES RESTful API
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
- 部件名作用VERB:HTTP方法 \ 谓词
GET
、POST
、PUT
、HEAD
或者DELETE
。 - PROTOCOL:http 或者 https(如果你在 Elasticsearch 前面有一个 https 代理)
- HOST:ES集群中任意节点的主机名,或者用 localhost 代表本地机器上的节点。
- PORT:运行 Elasticsearch HTTP 服务的端口号,默认是 9200 。
- PATH:API 的终端路径(例如 _count 将返回集群中文档数量)。
- Path 可能包含多个组件,例如:_cluster/stats 和 _nodes/stats/jvm 。
- QUERY_STRING:任意可选的查询字符串参数 (例如 ?pretty 将格式化地输出 JSON 返回值,使其更容易阅读)
- BODY:一个 JSON 格式的请求体 (如果请求需要的话)
# 计算集群中文档的数量
curl -X GET 'http://localhost:9200/_count?pretty' -d '
{
"query": {
"match_all": {}
}
}
'
# Kibana中
GET /_count?pretty
{
"query": {
"match_all": {}
}
}
- pretty:美化输出(_source字段不会被美化,它的样子与我们输入的一致。)
CRUD
添加
PUT\POST /索引名/类型名(新版本逐步废弃,默认类型_doc代替)/文档ID
{
请求体
}
往索引为 db(SQL数据库), 类型为 user(SQL Table) 的数据库中插入一条 id 为 1(SQL row?) 的一条数据(拥有 username/password/age 三个属性的实体)。
POST /db/user/1
{
"username": "wmyskxz1",
"password": "123456",
"age": "22"
}
PUT /test3/_doc/1
{
"name": "流柚",
"age": 18,
"birth": "1999-10-10"
}
PS:PUT如果漏了一些信息,原始信息就会丢失,故现在一般使用POST来更新索引。
指定字段索引(创建规则)并映射字段类型
PUT /test2
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age":{
"type": "long"
},
"birthday":{
"type": "date"
}
}
}
}
获取建立的规则
GET test2
删除
DELETE /db/user/1
修改
put覆盖
PUT /db/user/1
{
"username": "wmyskxz3",
"password": "123456",
"age": "22"
}
使用post的update
- version不会改变
- 不会丢失字段
- 注意doc
POST /test3/_doc/1/_update
{
"doc":{
"name" : "post修改,version不会加一",
"age" : 2
}
}
查询
GET /db/user/1
GET <index>/<type>/_search
简单条件查询
GET /test3/_doc/_search?q=name:流柚
查询匹配match
- match:匹配
- _source:过滤字段
- sort:排序
- from:索引开始
- size:限制显示个数
GET /blog/user/_search
{
"query":{
"match":{
"name":"流"
}
},
"_source": ["name","desc"],
"sort": [
{
"age": {
"order": "asc"
}
}
],
"from": 0,
"size": 1
}
多条件查询(bool)
- must: 相当于 and
- should: 相当于 or
- must_not: 相当于 not (… and …)
- filter:过滤条件
- range:按范围过滤
GET /blog/user/_search
{
"query":{
"bool": {
"must": [
{
"match":{
"sex": "女"
}
},
{
"match": {
"name": "流"
}
}
],
"filter": {
"range": {
"age": {
"gte": 1,
"lte": 100
}
}
}
}
}
}
匹配数组:query
多关键字查(空格隔开) :match 会使用分词器解析(先分析文档,然后进行查询)
GET /blog/user/_search
{
"query":{
"match":{
"name":"流 水"
}
}
}
精确查询item(完整词查询,不可分)
term 直接通过 倒排索引 指定词条查询
GET /blog/user/_search
{
"query":{
"term":{
"name":"流 水"
}
}
}
高亮查询highlight
GET blog/user/_search
{
"query": {
"match": {
"name":"流"
}
},
"highlight": {
"fields": {
"name": {}
}
}
}
自定义前后缀
GET blog/user/_search
{
"query": {
"match": {
"name":"流"
}
},
"highlight": {
"pre_tags": "<p class='key' style='color:red'>",
"post_tags": "</p>",
"fields": {
"name": {}
}
}
}
查询DSL(条件语句)
ElasticSearch自己基于JSON的域特定语言,可以在其中表达查询和过滤器。
GET /_search
{
"query": {
//Query DSL here
"query_string": {
"query": "kill"
}
}
}
命令行请求:
curl -X GET 'http://localhost:9200/db/user/_search?q=kill&pretty'
或
curl -X GET 'http://localhost:9200/db/user/_search?pretty' -d '
{
"query" : {
"query_string": {
"query": "kill"
}
}
}
'
指定搜索的字段fields
fields:可用于指定要搜索的字段列表。如果不使用“fields”字段,ElasticSearch查询将默认自动生成的名为 “_all” 的特殊字段,来基于所有文档中的各个字段匹配搜索。
GET /_search
{
"query": {
"query_string": {
"query": "ford",
"fields": [
"title"
]
}
}
}
过滤
-
filtered
(废除)
过滤的查询:具有两个属性query
和filter
。
GET /_search
{
"query": {
"filtered": {
"query": {
"query_string": {
"query": "drama"
}
},
"filter": {
# //Filter to apply to the query
"term": {"year": 1962}
}
}
}
}
条件过滤器:term
无需查询即可进行过滤
- (废除)
GET /_search
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"term": {
"year": 1962
}
}
}
}
}
- 使用常数分数查询
GET /_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"year": 1962
}
}
}
}
}
过滤器
bool查询
Bool查询对应Lucene中的BooleanQuery,它由一个或者多个子句组成,每个子句都有特定的类型。
must:返回的文档必须满足must子句的条件,并且参与计算分值
filter:返回的文档必须满足filter子句的条件。但是不会像Must一样,参与计算分值。
should
must_not
text VS keyword
text:支持分词、全文检索,支持模糊、精确查询,不支持聚合、排序操作。最大支持的字符长度无限制,适合大字段存储。
keyword:不进行分词,直接索引,支持模糊、精确匹配,支持聚合、排序操作。keyword类型的最大支持的长度为32766个UTF-8类型的字符,可以通过设置ignore_above指定自持字符长度,超过给定长度后的数据将不被索引,无法通过term精确匹配检索返回结果。
GET _analyze
{
"analyzer": "keyword",
"text": ["测试liu"]
}// keyword不会分词,即 测试liu
GET _analyze
{
"analyzer": "standard",
"text": ["测试liu"]
}// 分为 测 试 liu
GET _analyze
{
"analyzer":"ik_max_word",
"text": ["测试liu"]
}// 分为 测试 liu
get _cat/xxx获取当前更多信息
GET _cat/indices
GET _cat/aliases
GET _cat/allocation
GET _cat/count
GET _cat/fielddata
GET _cat/health
GET _cat/indices
GET _cat/master
GET _cat/nodeattrs
GET _cat/nodes
GET _cat/pending_tasks
GET _cat/plugins
GET _cat/recovery
GET _cat/repositories
GET _cat/segments
GET _cat/shards
GET _cat/snapshots
GET _cat/tasks
GET _cat/templates
GET _cat/thread_pool
常用命令
- 集群的健康状态:
GET _cluster/health
- 查询集群中节点的信息:
GET /_cat/nodes
、GET /_cat/nodes?v
(?v 让kibana 输出逻辑模式即verbose模式的首字母)
problem
跨域访问(跨端口)导致集群无法连接
配置es,打开elasticsearch.yml文件,在最后一行加入(注意yalm语法,冒号后要加一个空格)
http.cors.enabled: true
http.cors.allow-origin: "*"
重启es。
汉化Kibana
在Kibana目录下的config中修改Kibana.yml文件,最后一行加上
i18n.locale: "zh-CN"
重启。
docker 安装 elasticsearch & kibana, 杜绝报错
elasticsearch初学终极教程 - 第二章: 把Elastic Search在本地跑起来
什么是 Elasticsearch?一篇搞懂
终于有人把Elasticsearch原理讲透了!
搜索引擎入门
教程
官方教程
ElasticSearch 快速上手学习入门教程
书
Elastic社区
集群配置文章来源:https://uudwc.com/A/ZOpx
【狂神说Java】ElasticSearch7.6.x最新完整教程通俗易懂
狂神说笔记之ElasticSearch文章来源地址https://uudwc.com/A/ZOpx