ES系列8-ElasticSearch搜索及持久化变更

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES系列8-ElasticSearch搜索及持久化变更相关的知识,希望对你有一定的参考价值。

参考技术A   随着按段(per-segment)搜索的发展,一个新的文档从索引到可被搜索的延迟显著降低了。新文档在几分钟之内即可被检索,但这样还是不够快。磁盘在这里成为了瓶颈。提交(Commiting)一个新的段到磁盘需要一个fsync来确保段被物理性地写入磁盘,这样在断电的时候就不会丢失数据。但是fsync操作代价很大;如果每次索引一个文档都去执行一次的话会造成很大的性能问题。

  我们需要的是一个更轻量的方式来使一个文档可被搜索,这意味着fsync要从整个过程中被移除。在Elasticsearch和磁盘之间是文件系统缓存。像之前描述的一样,在内存索引缓冲区中的文档会被写入到一个新的段中。但是这里新段会被先写入到文件系统缓存—这一步代价会比较低,稍后再被刷新到磁盘—这一步代价比较高。不过只要文件已经在缓存中,就可以像其它文件一样被打开和读取了。

  Lucene允许新段被写入和打开,使其包含的文档在未进行一次完整提交时便对搜索可见。这种方式比进行一次提交代价要小得多,并且在不影响性能的前提下可以被频繁地执行。

  在 Elasticsearch 中,写入和打开一个新段的轻量的过程叫做refresh。默认情况下每个分片会每秒自动刷新一次。这就是为什么我们说 Elasticsearch是近实时搜索:文档的变化并不是立即对搜索可见,但会在一秒之内变为可见。

  这些行为可能会对新用户造成困惑:他们索引了一个文档然后尝试搜索它,但却没有搜到。这个问题的解决办法是用refresh API执行一次手动刷新:/usersl_refresh

  尽管刷新是比提交轻量很多的操作,它还是会有性能开销。当写测试的时候,手动刷新很有用,但是不要在生产环境下每次索引一个文档都去手动刷新。相反,你的应用需要意识到Elasticsearch 的近实时的性质,并接受它的不足。

  并不是所有的情况都需要每秒刷新。可能你正在使用Elasticsearch索引大量的日志文件,你可能想优化索引速度而不是近实时搜索,可以通过设置refresh_interval ,降低每个索引的刷新频率。

  refresh_interval可以在既存索引上进行动态更新。在生产环境中,当你正在建立一个大的新索引时,可以先关闭自动刷新,待开始使用该索引时,再把它们调回来。

  如果没有用fsync把数据从文件系统缓存刷(flush)到硬盘,我们不能保证数据在断电甚至是程序正常退出之后依然存在。为了保证Elasticsearch 的可靠性,需要确保数据变化被持久化到磁盘。在动态更新索引,我们说一次完整的提交会将段刷到磁盘,并写入一个包含所有段列表的提交点。Elasticsearch 在启动或重新打开一个索引的过程中使用这个提交点来判断哪些段隶属于当前分片。

  即使通过每秒刷新(refresh)实现了近实时搜索,我们仍然需要经常进行完整提交来确保能从失败中恢复。但在两次提交之间发生变化的文档怎么办?我们也不希望丢失掉这些数据。  Elasticsearch 增加了一个translog ,或者叫事务日志,在每一次对Elasticsearch进行操作时均进行了日志记录。
整个流程如下:

  translog 提供所有还没有被刷到磁盘的操作的一个持久化纪录。当Elasticsearch启动的时候,它会从磁盘中使用最后一个提交点去恢复己知的段,并且会重放translog 中所有在最后一次提交后发生的变更操作。

  translog 也被用来提供实时CRUD。当你试着通过ID查询、更新、删除一个文档,它会在尝试从相应的段中检索之前,首先检查 translog任何最近的变更。这意味着它总是能够实时地获取到文档的最新版本。

  执行一个提交并且截断translog 的行为在 Elasticsearch被称作一次flush。分片每30分钟被自动刷新(flush),或者在 translog 太大的时候也会刷新。

  你很少需要自己手动执行flush操作,通常情况下,自动刷新就足够了。这就是说,在重启节点或关闭索引之前执行 flush有益于你的索引。当Elasticsearch尝试恢复或重新打开一个索引,它需要重放translog中所有的操作,所以如果日志越短,恢复越快。

  translog 的目的是保证操作不会丢失,在文件被fsync到磁盘前,被写入的文件在重启之后就会丢失。默认translog是每5秒被fsync刷新到硬盘,或者在每次写请求完成之后执行(e.g. index, delete, update, bulk)。这个过程在主分片和复制分片都会发生。最终,基本上,这意味着在整个请求被fsync到主分片和复制分片的translog之前,你的客户端不会得到一个200 OK响应。

  在每次请求后都执行一个fsync会带来一些性能损失,尽管实践表明这种损失相对较小(特别是 bulk 导入,它在一次请求中平摊了大量文档的开销)。

  但是对于一些大容量的偶尔丢失几秒数据问题也并不严重的集群,使用异步的 fsync还是比较有益的。比如,写入的数据被缓存到内存中,再每5秒执行一次 fsync 。如果你决定使用异步translog 的话,你需要保证在发生 crash 时,丢失掉 sync_interval时间段的数据也无所谓。请在决定前知晓这个特性。如果你不确定这个行为的后果,最好是使用默认的参数“index.translog.durability”: “request”来避免数据丢失。

  由于自动刷新流程每秒会创建一个新的段,这样会导致短时间内的段数量暴增。而段数目太多会带来较大的麻烦。每一个段都会消耗文件句柄、内存和 cpu运行周期。更重要的是,每个搜索请求都必须轮流检查每个段;所以段越多,搜索也就越慢。

  Elasticsearch通过在后台进行段合并来解决这个问题。小的段被合并到大的段,然后这些大的段再被合并到更大的段。

  段合并的时候会将那些旧的已删除文档从文件系统中清除。被删除的文档(或被更新文档的旧版本)不会被拷贝到新的大段中。

  启动段合并不需要你做任何事。进行索引和搜索时会自动进行。

  合并大的段需要消耗大量的 I/O 和 CPU 资源,如果任其发展会影响搜索性能。 Elasticsearch在默认情况下会对合并流程进行资源限制,所以搜索仍然有足够的资源很好地执行。

ELK(分布式大数据搜索和日志挖掘及可视化)之核心elasticsearch(ES)


问题向导:
(1)什么是ELK,有什么作用?
(2)elasticsearch(ES)简介。

(3)基本操作与详细介绍

(4)elasticsearch(ES)与solr的简单对比


1、ELK介绍

通常,日志被分散的储存不同的设备上。如果你管理数十上百台服务器,你还在使用依次登录每台机器的传统方法查阅日志。这样是不是感觉很繁琐和效率低下。当务之急我们使用集中化的日志管理,例如:开源的syslog,将所有服务器上的日志收集汇总。

集中化管理日志后,日志的统计和检索又成为一件比较麻烦的事情,一般我们使用grep、awk和wc等Linux命令能实现检索和统计,但是对于要求更高的查询、排序和统计等要求和庞大的机器数量依然使用这样的方法难免有点力不从心。

开源实时日志分析ELK平台能够完美的解决我们上述的问题,ELK由ElasticSearch、Logstash和Kiabana三个开源工具组成。官方网站:https://www.elastic.co/products

Elasticsearch是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。

Logstash是一个完全开源的工具,他可以对你的日志进行收集、过滤,并将其存储供以后使用(如,搜索)。

Kibana 也是一个开源和免费的工具,它Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助您汇总、分析和搜索重要数据日志。

2、核心elasticsearch(ES)简介

Elasticsearch是一个实时的分布式搜索和分析引擎。它可以帮助你用前所未有的速度去处理大规模数据。

它可以用于全文搜索,结构化搜索以及分析,当然你也可以将这三者进行组合。

Elasticsearch是一个建立在全文搜索引擎 Apache Lucene™ 基础上的搜索引擎,可以说Lucene是当今最先进,最高效的全功能开源搜索引擎框架。

但是Lucene只是一个框架,要充分利用它的功能,需要使用JAVA,并且在程序中集成Lucene。需要很多的学习了解,才能明白它是如何运行的,Lucene确实非常复杂。

Elasticsearch使用Lucene作为内部引擎,但是在使用它做全文搜索时,只需要使用统一开发好的API即可,而不需要了解其背后复杂的Lucene的运行原理。

当然Elasticsearch并不仅仅是Lucene这么简单,它不但包括了全文搜索功能,还可以进行以下工作:

  •     分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。

  •     实时分析的分布式搜索引擎。

  •     可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。


ElasticSearch(简称ES)是面向文档(document oriented),意味它可以存储整个对象或者文档,除了存储,还会索引每个文档的内容使之可以被搜索。


Elasticsearch中,文档归属于一种 类型(type) ,而这些类型存在于 索引(index)中,类比传统关系型数据库:

Relational DB -> Databases -> Tables -> Rows -> Columns

关系型数据库       数据库      表        行         列  

Elasticsearch -> Indices   -> Types  -> Documents -> Fields


3.1、ES安装


ES由java语言实现,运行环境依赖java。ES 1.x版本,官方推荐使用jdk1.7+的环境,建议使用oracle jdk1.8;ES可以去官网下载,本文使用elasticsearch-1.6.0.tar.gz。


(1) 解压elasticsearch-1.6.0.tar.gz,sudo tar -zvxf elasticsearch-1.6.0.tar.gz,在当前路径生成目录:elasticsearch-1.6.0;

(2) 配置ES。这里只做最简单的配置,修改ES_HOME/config/elasticsearch.yml文件, 相关配置参数(可以使用默认的)

#集群名称
cluster.name: elasticsearch

#节点名称
node.name: "node1"

#节点是否存储数据
node.data: true

#索引分片数
index.number_of_shards: 5

#索引副本数
index.number_of_replicas: 1

#数据目录存放位置
path.data: /data/elasticsearch/data

#日志数据存放位置
path.logs: /data/elasticsearch/log

#索引缓存
index.cache.field.max_size: 500000

#索引缓存过期时间
index.cache.field.expire: 5m

(3) 启动ES。进入ES安装目录,执行命令:bin/elasticsearch -d -Xms512m -Xmx512m,然后在浏览器输入http://ip:9200/,查看页面信息,是否正常启动。status=200表示正常启动了。


./bin/elasticsearch


也可以在终端测试

开启后你就可以使用另一个终端窗口来进行测试了:

curl 'http://localhost:9200/?pretty'

你应该看到如下提示:

"status"200"name""Shrunken Bones""version": { "number""1.4.0""lucene_version":"4.10" }, "tagline""You Know, for Search" }



3.2、面向文档

Elasticsearch 是 面向文档型数据库,这意味着它存储的是整个对象或者 文档,它不但会存储它们,还会为他们建立索引,这样你就可以搜索他们了。你可以在 Elasticsearch 中索引、搜索、排序和过滤这些文档。不需要成行成列的数据。这将会是完全不同的一种面对数据的思考方式,这也是为什么 Elasticsearch 可以执行复杂的全文搜索的原因。

JSON

Elasticsearch使用 JSON (或称作JavaScript Object Notation ) 作为文档序列化的格式。JSON 已经被大多数语言支持,也成为 NoSQL 领域的一个标准格式。它简单、简洁、易于阅读。

把这个 JSON 想象成一个用户对象:

"email""john@smith.com""first_name""John""last_name""Smith""about": { "bio":"Eco-warrior and defender of the weak""age"25"interests": [ "dolphins""whales" ] },"join_date""2014/05/01", }



3.3、索引实例

这个项目的第一步就是存储员工的数据。这样你就需要一个“员工档案”的表单,这样每个文档都代表着一个员工。在 Elasticsearch 中,存储数据的行为就叫做 索引(indexing) ,但是在我们索引数据前,我们需要决定将数据存储在哪里。

在 Elasticsearch 中,文档属于一种 类型(type),各种各样的类型存在于一个 索引 中。你也可以通过类比传统的关系数据库得到一些大致的相似之处:

关系数据库 ⇒ 数据库 ⇒ 表 ⇒ 行 ⇒ 列(Columns) 


Elasticsearch ⇒ 索引 ⇒ 类型 ⇒ 文档 ⇒ 字段(Fields)

一个 Elasticsearch 集群可以包含多个 索引(数据库),也就是说其中包含了很多 类型(表)。这些类型中包含了很多的 文档(行),然后每个文档中又包含了很多的 字段(列)。


GET /megacorp/employee/1

响应的内容中包含一些文档的元信息,John Smith的原始JSON文档包含在_source字段中。

"_index" : "megacorp""_type" : "employee""_id" : "1""_version" : 1"found" : true,"_source" : { "first_name" : "John""last_name" : "Smith""age" : 25"about" : "I love to go rock climbing""interests": [ "sports""music" ] } }


GET请求非常简单——你能轻松获取你想要的文档。让我们来进一步尝试一些东西,比如简单的搜索!

我们尝试一个最简单的搜索全部员工的请求:

GET /megacorp/employee/_search使用DSL语句查询

查询字符串搜索便于通过命令行完成特定(ad hoc)的搜索,但是它也有局限性(参阅简单搜索章节)。Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。

DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。我们可以这样表示之前关于“Smith”的查询:

GET /megacorp/employee/_search { "query" : { "match" : { "last_name" : "Smith" } } }


到目前为止搜索都很简单:搜索特定的名字,通过年龄筛选。让我们尝试一种更高级的搜索,全文搜索——一种传统数据库很难实现的功能。

我们将会搜索所有喜欢“rock climbing”的员工:

GET /megacorp/employee/_search { "query" : { "match" : { "about" : "rock climbing" } } }

你可以看到我们使用了之前的match查询,从about字段中搜索"rock climbing",我们得到了两个匹配文档:

{ ... "hits": { "total"2"max_score"0.16273327"hits": [ { ... "_score"0.16273327,<1> "_source": { "first_name": "John", "last_name": "Smith", "age": 25, "about": "I love to go rock climbing", "interests": [ "sports", "music" ] } }, { ... "_score": 0.016878016, <2>"_source": { "first_name": "Jane", "last_name": "Smith", "age": 32, "about": "I like to collect rock albums", "interests": [ "music" ] } } ] } }

3.4、倒排索引

Elasticsearch使用一种叫做倒排索引(inverted index)的结构来做快速的全文搜索。倒排索引由在文档中出现的唯一的单词列表,以及对于每个单词在文档中的位置组成。


例如,我们有两个文档,每个文档content字段包含:

  1. The quick brown fox jumped over the lazy dog

  2. Quick brown foxes leap over lazy dogs in summer

为了创建倒排索引,我们首先切分每个文档的content字段为单独的单词(我们把它们叫做词(terms)或者表征(tokens))(译者注:关于terms和tokens的翻译比较生硬,只需知道语句分词后的个体叫做这两个。),把所有的唯一词放入列表并排序,结果是这个样子的:

Term Doc_1 Doc_2
Quick
X
The X
brown X X
dog X
dogs
X
fox X
foxes
X
in
X
jumped X
lazy X X
leap
X
over X X
quick X
summer
X
the X

3.5、分布式

Elasticsearch致力于隐藏分布式系统的复杂性。以下这些操作都是在底层自动完成的:

  • 将你的文档分区到不同的容器或者分片(shards)中,它们可以存在于一个或多个节点中。

  • 将分片均匀的分配到各个节点,对索引和搜索做负载均衡。

  • 冗余每一个分片,防止硬件故障造成的数据丢失。

  • 将集群中任意一个节点上的请求路由到相应数据所在的节点。

  • 无论是增加节点,还是移除节点,分片都可以做到无缝的扩展和迁移。


4、与solr简单区别

ElasticSearch(简称ES)是一个分布式、Restful的搜索及分析服务器,设计用于分布式计算;能够达到实时搜索,稳定,可靠,快速。和Apache Solr一样,它也是基于Lucence的索引服务器,而ElasticSearch对比Solr的优点在于:

  •     轻量级:安装启动方便,下载文件之后一条命令就可以启动。

  •     Schema free:可以向服务器提交任意结构的JSON对象,Solr中使用schema.xml指定了索引结构。

  •     多索引文件支持:使用不同的index参数就能创建另一个索引文件,Solr中需要另行配置。

  •     分布式:Solr Cloud的配置比较复杂。

其他比较

  •     Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;

  •     Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;

  •     Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;

  •     Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch。


长按关注每天干货分享:



以上是关于ES系列8-ElasticSearch搜索及持久化变更的主要内容,如果未能解决你的问题,请参考以下文章

Win10安装ElasticSearch笔记

ElasticSearch的Gateway及存储原理

ES(六) ElasticSearch搜索原理

搜索引擎ElasticSearchV5.4.2系列三之ES使用

从零搭建ES搜索服务基本概念及环境搭建

linux环境下es快速安装ik插件