ElasticSearch学习笔记

本文是对ElasticSearch组件初步学习的一个知识总结,包括如下章节的内容:

  • 概述
  • 快速上手
  • 逻辑概念
  • 用户接口
  • 关于ELKB

预备知识:

1、本文对ElasticSerach的介绍会涉及与关系数据库的对比,为了更好地学习,可提前对关系数据库的基本概念有所了解。
2、ElasticSerach的数据存储采用JSON的数据格式,为了更好地学习,可提前对JSON的概念有所了解。
3、ElasticSerach对外提供的是RESTful Api访问接口,为了更好地学习,可提前对RESTful的概念有所了解。

一、概述

ElasticSerach(下面简称ES)是一个基于Lucene(一个开源全文搜索引擎)构建的开源、分布式可扩展的实时搜索和分析引擎。它还可以作为一个分布式实时文件存储系统。
ES是目前全文搜索引擎的首选,它可以快速地储存、搜索和分析海量数据。维基百科、Stack Overflow、Github 等系统都采用它。
ES采用java语言开发,对外提供了 RESTful API 的操作接口,开箱即用。

Elasticsearch 于2010年提交到 GitHub。其版本发布情况如下:
1、2010年2月8日推出了 V0.4.0 的发行版本,2010年2月12日推出 V1.0.0 版本,2016年2月2日推出 V1.7.5 版本, 此为 1.X 最终版本,不再更新。
2、2015年10月28日推出 V2.0.0 版本,2017年7月25日推出 V2.4.6 版本,此为 2.X 最终版本,不再更新。
3、2016年10月26日推出 V5.0.0 版本,2018年2月20日推出 V5.6.8 版本,此并不是 5.X 的最终版本,还在更新中……
4、2017年11月14日推出 V6.0.0 版本,2018年2月20日推出 V6.2.2 版本。
……

下一个版本是7.x,已经有测试版可以下载。

本文示例所有的版本是elasticsearch-5.6.9。

二、快速上手

ES虽然是一个强大的分布式系统,但其易用性设计的非常好,安装和使用都很简单,下面我们来快速体验下。

(一)安装

ES需要java环境,最好是java8,需要设置JAVA_HOME环境变量。ES的安装非常简单,开箱即用,首先我们可以从官网www.elastic.co下载相应的二进制版本,对于Windows操作系统,可下载zip文件,对于linux操作系统,可下载tar文件。

下载二进制包后,解压到任何一个目录下。如果不做任何配置,则采用默认的配置启动ES。运行ES安装目录下的bin目录的elasticsearch脚本(windows下为elasticsearch.bat)则可以以单实例的方式启动ES。在linux系统中启动ES有可能会报错误,这在下面会详细介绍。

我们这里是启动的ES的单个实例,ES可以以集群的方式运行(即在多台机器上启动多个ES实例)。因为单节点模式和集群模式从使用角度看并没有太多的区别,所以本文介绍的都是基于ES在单节点方式运行的。集群的方式在后续的文章中介绍。

启动ES后,下面就可以利用ES提供的RESTful API去使用它。我们可以在浏览器或任何web工具中输入 http://localhost:9200 地址,得到如下的信息(ES系统的基本信息):

{
  "name" : "H12K5tk",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "2RAwSskjQh6xDxLrDHBTtQ",
  "version" : {
    "number" : "5.6.9",
    "build_hash" : "877a590",
    "build_date" : "2018-04-12T16:25:14.838Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.1"
  },
  "tagline" : "You Know, for Search"
}

返回的是本节点(ES实例的)name,以及ES集群的一些基本信息,如集群名,版本信息等。

(二)启动错误

在Linux系统中启动ES,可能会报一些错误,导致启动失败。下面是一些常见的错误与解决方案(这也是本文在Centos7系统中启动ES碰到的问题)。

1、错误1:max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
错误很好理解,就是指es进程可允许打开的最大文件数只有4096,太小了,需要提升到65536。因为ES需要打开很多文件,最大4096个不够,需要调整操作系统中的配置。
在Linux的系统中对于进程(Process)会有一些限制(limit),限制有很多种,常见的如对打开文件(Open Files)最大数量的限制。在linux中这些限制是分为软限制(soft limit)和硬限制(hard limit)两类。它们的区别就是软限制可以在程序的进程中自行改变(突破限制),而硬限制则不行(除非程序进程有root权限)。
使用ulimit 命令可以分别查看软限制和硬限制,区别是在查看的参数前加 S 或 H。例如,查看打开文件数限制(参数是n):

#查看软限制
ulimit -Sn
#查看硬限制
ulimit -Hn

改变这个限制的办法是修改/etc/security/limits.conf文件,增加配置,如在配置文件中增加如下信息:

*     soft    nofile    65536
*     hard    nofile   65536

注意,最前面的 * 代表这个设置对所有进程都有效,如果只对指定进程有效,将*改为具体的进程名。

2、错误2:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
这个错误是指Linux进程的vma大小不足,需要提高。这可以修改/etc/sysctl.conf文件,增加配置vm.max_map_count=262144,如:

vm.max_map_count=262144

修改配置文件后,执行 命令sysctl -p 让生效(注意,一定要执行),如:

[hadoop@master bin]$ sudo sysctl -p
[sudo] password for hadoop:
vm.max_map_count = 262144

另外,在操作系统配置文件被修改后,最好重新登录,确保新的终端能获取到修改后的信息。

(三)访问ES

因为ES对外提供了RESTful的访问接口,所以我们可以用任意一种web client工具来访问ES,最简单的如linux下的curl程序,还可以用如Postman这样的工具(Postman是一个非常有用的 Http Client 工具,可用来测试 Web 服务),也可以在浏览器上安装插件,如chrome中的Sense插件(该插件可以很方便的操作ES)。

当然我们可以利用第三方http client库自己编写代码来访问ES。不过ES自身也提供了JAVA API来操作ES,这个在后面介绍。

下面我们使用RESTful API来举例使用ES。一个完整的REST请求包括如下三部分:
1、操作类型,如GET,PUT,POST,DELETE等
2、URL部分,如http://localhost:9200/blogs/blog/1
3、请求正文内容。对于GET请求,没有单独的请求正文内容,请求信息都包含在URL中。对于PUT,POST等操作,可以带正文内容,正文内容采用josn的格式,具体下面例子会看到。

ES的REST请求的返回内容的格式绝大部分都是JOSN格式的。也就是说请求和响应的内容都是JSON格式,这样有较好的一致性。

下面来看具体的例子:

1、插入数据
往ES中插入数据,可以执行如下的操作:

PUT  http://localhost:9200/blogs/blog/1
{
    "title": "es info",
    "content": "about elasticsearch",
    "author": "jack",
    "year":2018
}

这里执行的是http的PUT操作,url后面跟着的json格式内容是请求的正文,即保存到ES中的数据。关于该url和json内容的含义我们在后面介绍,这里只需知道这样一个简单的http的PUT请求就把一条json数据保存到ES中。上述操作我们可以在如Postman这样的工具中进行。
该请求成功后服务器返回的信息如下:

{
  "_index": "blogs",
  "_type": "blog",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}

上面响应信息的格式也是josn格式,其中字段的含义我们后面再介绍。

2、查询数据
上面往ES中插入了一条数据,下面我们可以利用http的GET操作来获取刚才插入的数据。http请求如下:

GET  http://localhost:9200/blogs/blog/1

该请求成功后服务器返回的信息如下:

{
  "_index": "blogs",
  "_type": "blog",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "title": "es info",
    "content": "about elasticsearch",
    "author": "jack",
    "year": 2018
  }
}

3、修改数据
当文档已经存在时,如果要修改文档的内容,可执行与插入数据一样的PUT操作,如:

PUT  http://localhost:9200/blogs/blog/1
{
    "title": "es info",
    "content": "about elasticsearch",
    "author": "tom",
    "year":2018
}

该请求成功后服务器返回的信息如下:

{
  "_index": "blogs",
  "_type": "blog",
  "_id": "1",
  "_version": 2,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": false
}

可以看出,返回的josn内容中,相比插入操作,有这几个字段的内容发生了变化:

"_version" : 2,
"result" : "updated",
"created" : false

可以看到,记录的 Id 没变,但是版本(version)从1变成2,操作类型(result)从created变成updated,created字段变成false,因为这次不是新建记录,而是修改操作。

这时如果我们执行

GET  http://localhost:9200/blogs/blog/1

查询操作,会看到返回的Document数据是修改后的数据。

ES文档的版本号是有用的,我们在修改数据时,可以传入一个版本号。这样当在一个客户端读取和更新文档的间隔中,有另外客户端更新了数据。如果这个客户端的更新操作传入了版本号(前面读取的版本号),这时因为传入的版本号和当期实际的版本号不一致,就会操作失败。这样就防止可能的数据冲突。这也是ES采用乐观并发控制(OCC)机制的体现。

加入版本号进行更新,只需在url后面加上version参数,如:

PUT http://localhost:9200/blogs/blog/1?version=2

4、删除操作
通过DELETE操作,可以删除ES中的数据。HTTP请求如下:

DELETE  http://localhost:9200/blogs/blog/1

该请求成功后服务器返回的信息如下:

{
  "found": true,
  "_index": "blogs",
  "_type": "blog",
  "_id": "1",
  "_version": 2,
  "result": "deleted",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  }
}

如果我们这时去执行GET操作,如

GET http://localhost:9200/blogs/blog/1

该请求成功后服务器返回的信息如下:

{
  "_index": "blogs",
  "_type": "blog",
  "_id": "1",
  "found": false
}

从响应的结果可以看出,没有查到数据。

5、搜索操作
下面我们来看下ES最强大的搜索操作,首先我们来先插入2条数据,包括前面插入和被删除的数据。

PUT  http://localhost:9200/blogs/blog/1
{
    "title": "es info",
    "content": "about elasticsearch",
    "author": "jack",
    "year":2018
}

PUT  http://localhost:9200/blogs/blog/2
{
    "title": "zk info",
    "content": "about zookeeper",
    "author": "jack",
    "year":2018
}

下面我们来执行根据给定的字符串进行查找,只要数据中有包含给定字符串的内容就认为匹配上,查询命令如下:

POST http://localhost:9200/_search
{
    "query": {
        "query_string": {
            "query": "elasticsearch"
        }
    }
}

返回的结果如下:

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 10,
    "successful": 10,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.26742277,
    "hits": [
      {
        "_index": "blogs",
        "_type": "blog",
        "_id": "1",
        "_score": 0.26742277,
        "_source": {
          "title": "es info",
          "content": "about elasticsearch",
          "author": "jack",
          "year": 2018
        }
      }
    ]
  }
}

可以看出,搜索到了数据。我们可以试着改变上面查询条件中"query"参数的值,来观察结果的变化。

上面的搜索是搜索整个json数据中的信息,我们也可以只搜索指定json字段中的内容。如:

POST http://localhost:9200/_search
{
    "query": {
        "query_string": {
            "query": "jack",
            "fields": ["author"]
        }
    }
}

上面的REST语句表示只在字段author中查找存在jack字符串的数据。字段通过查询条件中的filelds参数指定,可以看出,同时可指定多个字段。 对比关系数据库,ES的搜索操作有点类似关系数据库中带like子句的select语句。

可以看出,利用ES的RESTful Api进行操作还是比较简单的,当然我们只是列举了几个最基本的操作。上面通过举例让我们站在用户的角度对ES有了个初步的认识,下面章节继续展开更为详细的介绍。

(四)远程访问

上面例子中我们都是在本地利用REST接口访问ES的,即web客户端运行在ES实例所在的机器上,所以url中用的是localhost。 如果需要支持对ES的远程访问,可以修改ES安装目录的config/elasticsearch.yml文件,去掉network.host的注释,将它的值改成0.0.0.0,然后重新启动 ES。配置文件中信息如:

network.host: 0.0.0.0

上面配置,设成0.0.0.0让任何一台机器都可以访问。线上服务不要这样设置,要设成具体的 IP,如:

network.host: 192.168.0.1

三、逻辑概念

我们上面的例子使用了 http://localhost:9200/blogs/blog/1 这样的ulr来进行数据的插入、查询及搜索和删除操作。抛开操作的方式,感觉和关系数据库的操作有类似的地方。这其实也是正常的,因为数据库也是用来进行数据存储和分析(查找)的,所以从功能上说肯定有很多类似的地方。我们知道关系数据库有数据库、表、记录、字段等概念,为了更好地理解ES的逻辑架构,我们在介绍ES的一些重要概念的时候会对比关系数据库中的一些概念。

(一)索引(Index)

ES数据管理的顶层单位就叫做 Index(索引)。它不是关系数据库中索引的概念,是单个数据库的同义词,即可以把它等价于关系数据库中的单个数据库。Index的名称必须小写。

既然Index是ES管理数据的顶层单位,肯定先需要有索引,才能进行后续的数据存储等操作,类似关系数据库中得首先有数据库一样。可前面的操作我们并没有看到创建Index的操作。是不是ES启动后有一个默认的Index呢?

其实情况是这样的,上面的REST请求 http://localhost:9200/blogs/blog/1 中的 blogs就是一个索引名,当我们执行数据插入操作时,如果url中指定的索引不存在,则ES会自动创建该索引。就如我们前面的例子,我们插入数据时,索引blogs并不存在,所以ES按照默认的设置自动创建了blogs索引。

我们可以单独创建一个索引,操作如下:

PUT  http://localhost:9200/topics

上面操作通过http的PUT操作,创建了一个名称为topics的索引。
操作成功后的响应信息如下:

{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "topics"
}

我们可以查看到ES中的所有索引,操作如下:

GET  http://localhost:9200/_cat/indices?v

响应结果如下:

health  status  index  uuid  pri  rep  docs.count  docs.deleted  store.size   pri.store.size
yellow  open   blogs  hM...  5    1      2          0         10.2kb      10.2kb
yellow  open   topics  hV...  5    1      0          0         810b        810b

结果以表格的形式显示,第一行为表头。因为前面的操作我们已经创建了blogs索引,加上刚创建的topics索引,所以我们看到结果有2条记录。

通过DELETE操作,我们可以删除指定的索引,如下面操作:

DELETE  http://localhost:9200/topics

操作成功的响应结果如下:

{
  "acknowledged": true
}

这表示删除索引成功,如果我们这时再去查找所有索引,会发现topics索引没有了。

(二)类型(Type)

在索引中,可以定义一个或多个类型(type),类型是索引的逻辑分区,是同一索引中有公共字段的文档的集合。比如在一个博客系统中,我们可以将用户数据放到一种类型中,将文章数据放到一种类型中,将对文章的评论信息放到一种类型中。

类型不需要单独创建,在插入数据(如上面的例子)会自动创建。对于 http://localhost:9200/blogs/blog/1 这个url,其中的blog就是类型(type)名。

相对关系数据库来说,类型可以类比成关系数据库中的表。
需要注意的是,根据规划,Elastic 6.x 版只允许每个 Index 包含一个 Type,7.x 版将会彻底移除 Type。

所以我们在实际使用中,不用过多考虑Type的作用。

(三)文档(Document)

Document是Index中的单条记录,它就像关系数据库中表中的记录(行)。Document 使用 JSON 格式表示,如上面插入数据时的url后面跟的请求数据:

PUT http://localhost:9200/blogs/blog/1
{
    "title": "es info",
    "content": "about elasticsearch",
    "author": "jack",
    "year":2018
}

ES的每个存储在Index中的Document都有一个类型(type)和一个唯一的ID。这个ID可以用户在创建文档时显示指定,如上面url最后的1,也可以由ES自动生成(后面会介绍)。

JSON数据是一种半结构化的数据格式,它由一个个的字段组成,字段有字段名、字段的值,和字段类型,比如上面的title字段就是一个字符串类型,year字段就是一个整数类型。JSON数据的字段类型不需要显示定义,由字段的内容推断出来,比如字符串是要放到引号中,整数则不能。

同一个 Index 里面的 Document(即使是位于同一个Type下),不要求有相同的结构(即相同的字段和字段类型),但是最好保持相同,这样有利于提高搜索效率。需要注意的是,同一个字段名的字段,不能在这个文档中是字符串类型,而在另外一个字符串中是数组类型。举个例子,上面举例中我们插入了如下的数据:

PUT http://localhost:9200/blogs/blog/1
{
    "title": "es info",
    "content": "about elasticsearch",
    "author": "jack",
    "year":2018
}

这时如果插入如下数据:

PUT http://localhost:9200/blogs/blog/2
{
    "title": "es info",
    "content": "about elasticsearch",
    "author": "jack",
    "year": "2018年"
}

也就是这里插入的year字段值是个字符串,则时ES的响应就会报错,报类型不一致的错误,因为前面插入的数据已经让ES把year字段认作为整型数据。但如果我们写成 "year": "2018" 这样的格式,虽然看上去year字段是字符串类型,但因为实际数据是整数,则不会报错。

因为即使是同一个Type下的Docuemnt也不要求有相同的数据模型,所以逻辑上Type与关系数据库的表对应,实际意义差别还是挺大的。在关系数据库下,表中的每条记录数据模型都是严格相同的。

(四)字段(Field)

上面已经提到了字段,字段就是Docuemnt对应的json内容的字段。一个Docuemnt可以包括零个或多个字段,字段可以是一个简单的值(如字符串、整数、日期),也可以是一个数组或对象的嵌套结构。每个字段都对应一个数据类型,如整数、字符串、数组、对象等。

(五)映射(mapping)

mapping是类似于数据库中的表结构定义,主要作用如下:

  • 定义index下的字段名
  • 定义字段类型,比如数值型、浮点型、布尔型等
  • 定义倒排索引相关的设置,比如是否索引、记录position等。
  • 设置分词器等

与表结构不同的是,关系数据库的表的结构必须事先通过create table语句来明确。而映射既可以显示的通过命令来事先定义,也可以在存储文档(插入数据)时由ES来自动识别。如我们上面的例子,并没有显示的去定义Index的mapping信息。

可以通过 GET http://localhost:9200/_mapping 来查看Index的mapping信息。

(六)主键(ID)

ES中的每个Document都有一个唯一的ID(在type下唯一),也就是说 index/type/id必须是唯一的。
我们可以插入数据时显示的指定ID,如前面的操作:

PUT  http://localhost:9200/blogs/blog/1

也可以也ES系统自动生成,注意这时就不能用PUT操作,要用POST操作,如下面操作:

POST  http://localhost:9200/blogs/blog
{
    "title": "es info",
    "content": "about elasticsearch",
    "author": "jack",
    "year":"2018"
}

上面请求中url的最后没有指定要插入的Document的ID,操作成功后的响应信息如下:

{
  "_index": "blogs",
  "_type": "blog",
  "_id": "AWeXZiyTS_34KbUEtT3A",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}

可以看出,响应信息中带回来了ES自动生成的ID值。

(七)与关系数据库对比

为了更好的理解ES的一些概念,结合上面的介绍,下表将ES中的一些概念与关系数据库(如MYSQL)中的一些概念做了对比。

ElasticSerach Mysql
Index Database
Type Table
Document Row
Field Column
Mapping Schema
Everything is indexed Index(表的索引)
ID Primary Key
Query DSL SQL
PUT/POST http://.... insert into ....
GET http://.... select * from ...
POST http://... (搜索操作) selcct * from... like ...
PUT http://.... update .....
DELETE http://.... delete from...

四、用户接口

ES提供了多种客户端(API)方式来让用户操作ES,下面我们来分别做下概要的介绍。

(一)监听端口信息

ES实例启动后,默认会启动两个监听端口,默认端口号分别是9200和9300。在windows下,可以用 netstat -an | findstr "LISTENING" 命令去显示当前系统所有正在监听的端口。在linux下,可用执行命令netstat -nlp来查看,另外可以执行命令netstat -nlp|grep :9200 查看监听指定端口的进程信息。

其中9200是为http服务所提供的端口,我们上面所有例子的REST请求中都带了9200这个值。

其中9300是ES集群中各个节点相互通讯使用,节点之间的交互采用其原生的传输 协议(基于TCP协议)。

(二)RESTful API

ES对外提供了RESTful API,这是基于http的。所以,包含java在内的,所有其他编程语言都可以使用 RESTful API 接口编写自己的web客户端程序通过端口 9200 和 Elasticsearch 进行通信。你可以用你喜爱的一些现成的 web 客户端工具访问 Elasticsearch,如curl工具,Postman工具等。

(三)Java REST API

ES提供了两个Java RESTful client版本,分别是:

1、低级别的Rest Api(Java Low Level REST Client)
用户需要自己编写代码来处理请求JSON串,以及解析响应JSON串。这类Api的好处是兼容所有的ES版本。该API是从ES5.0开始提供的。

2、高级别的Rest Api(Java High Level REST Client)
基于低级别的Api,增加了编写请求JSON串、解析响应JSON串等相关Api,目的是以java面向对象的方式来进行请求和响应的处理。这类Api要求使用的版本与ES服务端版本保持一致。

Java High Level REST Client是在ES6.0版本才开始提供的。

(四)非Java REST API

Elasticsearch 为以下语言提供了官的REST Api --Groovy、JavaScript、.NET、 PHP、 Perl、 Python 和 Ruby。

(五)Java API for传输协议(不推荐使用)

上面提到,ES的实例(节点)之间通讯采用原生的传输 协议(基于TCP协议),默认的端口是9300。ES提供了基于传输协议的Java Api来访问ES,有两种Api:

一种称为节点客户端(Node client),这种api编写的java程序会以集群中的一个节点(不保存数据的节点)加入到集群中,因集群对它是感知的,它的运行可能会对集群造成影响。

另一种称为传输客户端(Transport client),这种api编写的程序以远程连接的方式连接到ES集群,不会加入到集群,类似传统的C/S架构。

这两种Api编写的Java客户端都是通过 9300 端口并使用Elasticsearch 的原生传输 协议和集群交互。
需要说明的是,Node client方式从ES5.0版本开始就不再支持。Transport client也不推荐使用。

ES官方推荐用户使用REST API来操作ES。

五、关于ELKB

先说下ELK,ELK是一个流行的日志系统解决方案,注意,ELK不是一个软件名,而是一个解决方案的缩写,即Elasticsearch+Logstash+Kibana(ELK Stack)这三个软件的集合。

这几个都是开源的java产品,但是众所周知,java的东西很吃内存和CPU,Logstash在作为收集日志的Agent时,就显得太过臃肿了。后来官方在logstash-forwarder的基础上推出了beat系列,里面包括四个系统,分别是:

1、Packetbeat(搜集网络流量数据);
2、Topbeat(搜集系统、进程和文件系统级别的 CPU 和内存使用情况等数据);
3、Filebeat(搜集文件数据),Filebeat占用资源少,适合于在各个服务器上搜集日志后传输给Logstash;
4、Winlogbeat(搜集 Windows 事件日志数据)。

所以Filebeat也就这样加入了“日志收集分析”的团队里,所以虽然大家还是习惯性的叫ELK,其实准确的说法已经是ELKB了。

ELKB中的几个软件的分工如下:

1、Elasticsearch:分布式搜索和分析引擎,具有高可伸缩、高可靠和易管理等特点。基于 Apache Lucene 构建,能对大容量的数据进行接近实时的存储、搜索和分析操作。通常被用作某些应用的基础搜索引擎,使其具有复杂的搜索功能。

2、Logstash:数据收集额外处理和数据引擎。它支持动态的从各种数据源搜集数据,并对数据进行过滤、分析、丰富、统一格式等操作,然后存储到用户指定的位置。

3、Kibana:数据分析和可视化平台。通常与 Elasticsearch 配合使用,对其中数据进行搜索、分析和以统计图表的方式展示。

4、Filebeat:ELK 协议栈的新成员,在需要采集日志数据的服务器上安装 Filebeat,并指定日志目录或日志文件后,Filebeat 就能读取数据,迅速发送到 Logstash 进行解析,亦或直接发送到 Elasticsearch 进行集中式存储和分析。

本文只是对ELKB的基本概念做个介绍,关于LKB这几个软件的详细信息及ELKB四个软件之间如何配合来解决日志问题本文不做介绍。

你可能感兴趣的:(ElasticSearch学习笔记)