栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

实时搜索引擎Elasticsearch

实时搜索引擎Elasticsearch

目录标题
    • 一、什么是Elasticsearch
    • 二、安装ElasticSearch
    • 三、搭建集群
    • (一)集群健康
    • (二)搭建集群
    • 四、文档元数据和数据
    • 五、创建文档——C
    • 六、获取文档——R
    • (一)返回文档全部数据
    • (二)返回部分文档数据
    • (三)返回纯数据文档
    • (四)返回多个文档
    • 七、判断文档是否存在——R
    • 八、更新文档——U
    • 九、删除文档——D
    • 十、乐观锁
    • 十一、批量操作
    • 十二、分页
    • 参考

一、什么是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
  1. ElasticSearch下载地址:
    https://www.elastic.co/downloads/elasticsearch

  2. 下载安装包后解压

  3. 解压后bash运行bin/elasticsearch


注意:可以一起安装ELK
elasticsearch (es) :通过搭建群集;存储日志数据,索引日志数据
logstash :收集日志,收集到了后给es存储
kibana :视图形式展现日志信息,更加人性化
版本控制:ELK在下载时,下载版本号一致的版本即可。

三、搭建集群 (一)集群健康

Elasticsearch 的集群监控信息中包含了许多的统计数据,其中最为重要的一项就是 集群健康 , 它在 status 字段中展示为 green 、 yellow 或者 red 。

GET /_cluster/health

status 字段是我们最关心的。
status 字段指示着当前集群在总体上是否工作正常。它的三种颜色含义如下:

  1. green
    所有的主分片和副本分片都正常运行。
  2. yellow
    所有的主分片都正常运行,但不是所有的副本分片都正常运行。
  3. 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"
}

更新部分数据:

  1. update 请求最简单的一种形式是接收文档的一部分作为 doc 的参数, 它只是与现有的文档进行合并。对象被合并到一起,覆盖现有的字段,增加新的字段。 例如,我们增加字段 tags 和 views 到我们的博客文章,如下所示:
POST /website/blog/1/_update
{
   "doc" : {
      "tags" : [ "testing" ],
      "views": 0
   }
}
  1. 假设我们需要在 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 参数:

  1. size
    显示应该返回的结果数量,默认是 10
  2. 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 个结果的原因。

参考

官方文档1

官方文档2

中文ES社区

Java 使用ES1
Java使用ES2

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/676547.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号