目录标题
一、什么是Elasticsearch
- 在解释什么是Elasticsearch之前,让我们来回顾一下我们每天都在网页上面重复做的一件事情–“搜索”。没错,当我们需要了解一个东西的时候,我们会不自觉的打开搜索网站,例如百度,360,搜狗等;或者当我们需要购买一件物品时,我们打开淘宝,京东,唯品会等购物网站,做的第一件事情,仍然还是搜索我们需要的物品的关键词。
- Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。
二、安装ElasticSearch
-
ElasticSearch下载地址:
https://www.elastic.co/downloads/elasticsearch -
下载安装包后解压
-
解压后bash运行bin/elasticsearch
注意:可以一起安装ELK
elasticsearch (es) :通过搭建群集;存储日志数据,索引日志数据
logstash :收集日志,收集到了后给es存储
kibana :视图形式展现日志信息,更加人性化
版本控制:ELK在下载时,下载版本号一致的版本即可。
三、搭建集群
(一)集群健康
Elasticsearch 的集群监控信息中包含了许多的统计数据,其中最为重要的一项就是 集群健康 , 它在 status 字段中展示为 green 、 yellow 或者 red 。
GET /_cluster/health
status 字段是我们最关心的。
status 字段指示着当前集群在总体上是否工作正常。它的三种颜色含义如下:
- green
所有的主分片和副本分片都正常运行。 - yellow
所有的主分片都正常运行,但不是所有的副本分片都正常运行。 - red
有主分片没能正常运行。
(二)搭建集群
当你在同一台机器
上启动了第二个节点时,只要它和第一个节点有同样的 cluster.name 配置,它就会自动发现集群并加入到其中。 但是在不同机器上
启动节点的时候,为了加入到同一集群,你需要配置一个可连接到的单播主机列表。 详细信息请查看最好使用单播代替组播。
注意:通过config目录下的elasticsearch.yml修改配置
四、文档元数据和数据
注意:在ES中以 '_' 开头的都是关键词。并且在{}中的一级参数也是关键词。只有_source{}里面的数据才是我们自己定义的参数
一个文档不仅仅包含它的数据 ,也包含 元数据 —— 有关 文档的信息。 三个必须的元数据元素如下:
_index
文档在哪存放(索引库)
_type
文档表示的对象类别(类型)
_id
文档唯一标识
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
}
五、创建文档——C
ES中创建和修改文档的语句是相同的
,如果已经存在文档那么会覆盖掉之前的来达到更新的效果。
当我们索引一个文档,怎么确认我们正在创建一个完全新的文档,而不是覆盖现有的呢?
请记住, _index 、 _type 和 _id 的组合可以唯一标识一个文档。所以,确保创建一个新文档的最简单办法是,使用索引请求的 POST 形式让 Elasticsearch 自动生成唯一 _id :
方式一:指定id
# PUT /{索引库}/{类型}/{id}
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "I am starting to get the hang of this...",
"date": "2014/01/02"
}
方式二:自动生成id
POST /website/blog/
{ ... }
方式三:参数指定这个是创建文档语句
PUT /website/blog/123?op_type=create
{ ... }
PUT /website/blog/123?op_type=create
{ ... }
如果创建新文档的请求成功执行,Elasticsearch 会返回元数据和一个 201 Created 的 HTTP 响应码。
另一方面,如果具有相同的 _index 、 _type 和 _id 的文档已经存在,Elasticsearch 将会返回 409 Conflict 响应码,以及如下的错误信息:
{
"error": {
"root_cause": [
{
"type": "document_already_exists_exception",
"reason": "[blog][123]: document already exists",
"shard": "0",
"index": "website"
}
],
"type": "document_already_exists_exception",
"reason": "[blog][123]: document already exists",
"shard": "0",
"index": "website"
},
"status": 409
}
六、获取文档——R
(一)返回文档全部数据
GET /website/blog/123?pretty
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
}
(二)返回部分文档数据
# title,text为属性。指定返回哪几个属性
GET /website/blog/123?_source=title,text
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry" ,
"text": "Just trying this out..."
}
}
(三)返回纯数据文档
如果你只想得到 _source 字段,不需要任何元数据,你能使用 _source 端点:
GET /website/blog/123/_source
{
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
(四)返回多个文档
Elasticsearch 的速度已经很快了,但甚至能更快。 将多个请求合并成一个,避免单独处理每个请求花费的网络延时和开销。 如果你需要从 Elasticsearch 检索很多文档,那么使用 multi-get 或者 mget API 来将这些检索请求放在一个请求中,将比逐个文档请求更快地检索到全部文档。
mget API 要求有一个 docs 数组作为参数,每个元素包含需要检索文档的元数据
, 包括 _index 、 _type 和 _id 。如果你想检索一个或者多个特定的字段,那么你可以通过 _source 参数来指定这些字段的名字
:
例如:
GET /_mget
{
"docs" : [
{
"_index" : "website",
"_type" : "blog",
"_id" : 2
},
{
"_index" : "website",
"_type" : "pageviews",
"_id" : 1,
"_source": "views"
}
]
}
响应:
{
"docs" : [
{
"_index" : "website",
"_id" : "2",
"_type" : "blog",
"found" : true,
"_source" : {
"text" : "This is a piece of cake...",
"title" : "My first external blog entry"
},
"_version" : 10
},
{
"_index" : "website",
"_id" : "1",
"_type" : "pageviews",
"found" : true,
"_version" : 2,
"_source" : {
"views" : 2
}
}
]
}
七、判断文档是否存在——R
如果只想检查一个文档是否存在–根本不想关心内容—那么用 HEAD 方法来代替 GET 方法。 HEAD 请求没有返回体,只返回一个 HTTP 请求报头:
curl -i -XHEAD http://localhost:9200/website/blog/123
八、更新文档——U
在 Elasticsearch 中文档是 不可改变 的,不能修改它们。相反,如果想要更新现有的文档,需要 重建索引 或者进行替换, 我们可以使用相同的 index API 进行实现,在 索引文档 中已经进行了讨论。
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "I am starting to get the hang of this...",
"date": "2014/01/02"
}
更新部分数据:
- update 请求最简单的一种形式是接收文档的一部分作为 doc 的参数, 它只是与现有的文档进行合并。对象被合并到一起,覆盖现有的字段,增加新的字段。 例如,我们增加字段 tags 和 views 到我们的博客文章,如下所示:
POST /website/blog/1/_update
{
"doc" : {
"tags" : [ "testing" ],
"views": 0
}
}
- 假设我们需要在 Elasticsearch 中存储一个页面访问量计数器。 每当有用户浏览网页,我们对该页面的计数器进行累加。但是,如果它是一个新网页,我们不能确定计数器已经存在。 如果我们尝试更新一个不存在的文档,那么更新操作将会失败。
在这样的情况下,我们可以使用 upsert 参数,指定如果文档不存在就应该先创建它:
POST /website/pageviews/1/_update
{
"script" : "ctx._source.views+=1",
"upsert": {
"views": 1
}
}
九、删除文档——D
删除文档的语法和我们所知道的规则相同,只是使用 DELETE 方法:
DELETE /website/blog/123
十、乐观锁
在我们获取文档时,发现每个文档都是有一个版本号的。ES通过比较版本号来判断数据是否已经被别人修改。
{
"_index" : "website",
"_type" : "blog",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry",
"text": "Just trying this out..."
}
}
在更新时携带一个版本号,如果文档的版本号与携带的一致,才进行更新。
PUT /website/blog/1?version=1
{
"title": "My first blog entry",
"text": "Starting to get the hang of this..."
}
十一、批量操作
与 mget 可以使我们一次取回多个文档同样的方式, bulk API 允许在单个步骤中进行多次 create 、 index 、 update 或 delete 请求。 如果你需要索引一个数据流比如日志事件,它可以排队和索引数百或数千批次。
格式:
{ action: { metadata }}\n
{ request body }\n
{ action: { metadata }}\n
{ request body }\n
...
这种格式类似一个有效的单行 JSON 文档 流 ,它通过换行符(\n)连接到一起。注意两个要点:
每行一定要以换行符(\n)结尾, 包括最后一行 。这些换行符被用作一个标记,可以有效分隔行。
这些行不能包含未转义的换行符,因为他们将会对解析造成干扰。这意味着这个 JSON 不 能使用 pretty 参数打印。
action/metadata 行指定 哪一个文档 做 什么操作 。
action 必须是以下选项之一:
create
如果文档不存在,那么就创建它。详情请见 创建新文档。
index
创建一个新文档或者替换一个现有的文档。详情请见 索引文档 和 更新整个文档。
update
部分更新一个文档。详情请见 文档的部分更新。
delete
删除一个文档。详情请见 删除文档。
metadata 应该指定被索引、创建、更新或者删除的文档的 _index 、 _type 和 _id 。
例子:
POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }} \n
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}\n
{ "title": "My first blog post" }\n
{ "index": { "_index": "website", "_type": "blog" }}\n
{ "title": "My second blog post" }\n
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }\n
{ "doc" : {"title" : "My updated blog post"} } \n
响应:
{
"took": 4,
"errors": false,
"items": [
{ "delete": {
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 2,
"status": 200,
"found": true
}},
{ "create": {
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 3,
"status": 201
}},
{ "create": {
"_index": "website",
"_type": "blog",
"_id": "EiwfApScQiiy7TIKFxRCTw",
"_version": 1,
"status": 201
}},
{ "update": {
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 4,
"status": 200
}}
]
}
值得注意的是,如果批处理量太大的话。效率反而会降低
幸运的是,很容易找到这个 最佳点 :通过批量索引典型文档,并不断增加批量大小进行尝试。 当性能开始下降,那么你的批量大小就太大了。一个好的办法是开始时将 1,000 到 5,000 个文档作为一个批次, 如果你的文档非常大,那么就减少批量的文档个数。
密切关注你的批量请求的物理大小往往非常有用,一千个 1KB 的文档是完全不同于一千个 1MB 文档所占的物理大小。 一个好的批量大小在开始处理后所占用的物理大小约为 5-15 MB。
十二、分页
和 SQL 使用 LIMIT 关键字返回单个 page 结果的方法相同,Elasticsearch 接受 from 和 size 参数:
- size
显示应该返回的结果数量,默认是 10 - from
显示应该跳过的初始结果数量,默认是 0
GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10
注意:不要深度分页
理解为什么深度分页是有问题的,我们可以假设在一个有 5 个主分片的索引中搜索。 当我们请求结果的第一页(结果从 1 到 10 ),每一个分片产生前 10 的结果,并且返回给 协调节点 ,协调节点对 50 个结果排序得到全部结果的前 10 个。
现在假设我们请求第 1000 页—结果从 10001 到 10010 。所有都以相同的方式工作除了每个分片不得不产生前10010个结果以外。 然后协调节点对全部 50050 个结果排序最后丢弃掉这些结果中的 50040 个结果。
可以看到,在分布式系统中,对结果排序的成本随分页的深度成指数上升。这就是 web 搜索引擎对任何查询都不要返回超过 1000 个结果的原因。
参考
output参考:https://www.elastic.co/guide/en/logstash/current/plugins-outputs-elasticsearch.html
https://www.liujiajia.me/2018/11/28/logstash-save-different-logs-to-each-index/
注意logstash是默认使用内存队列,如果异常关闭可能会丢失数据,可以将数据持久化到磁盘(使用持久队列)
https://www.elastic.co/guide/en/logstash/current/persistent-queues.html#configuring-persistent-queues
解析Logstash 日志字段
https://www.cnblogs.com/dogfei/p/15092375.html
https://blog.csdn.net/zjcjava/article/details/99258682 重点
input file插件参考:https://www.cnblogs.com/JetpropelledSnake/p/9889275.html#_label2
解析日志:https://blog.csdn.net/zjcjava/article/details/99258682
根据log4j2输出格式生成grok-》match:http://grokconstructor.appspot.com/do/translator