You Know, for Search
ElasticSearch入门
1 简介
Elasticsearch1是为了搜索食谱诞生的一个高度可扩展的、开源的、基于 Lucene 的全文搜索和多级缓存的分析引擎。它允许您快速,近实时地存储,搜索和分析大量数据,并支持多租户。
Elasticsearch使用Java开发并使用 Lucene 作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTful API 来隐藏 Lucene 的复杂性,从而让全文搜索变得简单。
不过,Elasticsearch 不仅仅是 Lucene 和全文搜索,我们还能这样去描述它:
- 分布式的实时文件存储,每个字段都被索引并可被搜索
- 分布式的实时分析搜索引擎
- 可以扩展到上百台服务器,处理PB级结构化或非结构化数据
而且,所有的这些功能被集成到一个服务里面,你的应用可以通过简单的RESTful API、各种语言的客户端甚至命令行与之交互。
2 版本说明
2010年创建了第一个版本。
在决定使用 Elasticsearch 的时候首先要考虑的是版本问题,Elasticsearch 目前有三个常用的稳定的主版本:2.x,5.x,6.x(排除 0.x 和 1.x)。
Elasticsearch 可以在这里查看所有历史版本,目前最新的稳定版本是 Elasticsearch 6.6.x和7.x的Alpha版。你可能会发现没有 3.x 和 4.x,为了ELK(ElasticSearch, logstash, kibana)技术栈的版本统一,免的给用户带来混乱。所以ES 从 2.4.6 直接跳到了 5.0.0。
版本间对比
- 版本问题
2.x 版本较老,无法体验新功能,且性能不如 5.x。
6.x 版本有点新,网上资料相对比较少(开发时间充足的可以研究)。
- 数据迁移
2.x 版本数据可以直接迁移到 5.x;
5.X 版本的数据可以直接迁移到 6.x; 但是 2.x 版本数据无法直接迁移到 6.x。
- 周边工具
2.x 版本周边工具版本比较混乱;Kibana 等工具的对应版本需要自己查,不好匹配。
5.x 之后 Kibana 等工具的主版本号进行了统一。
- Sql 语法支持
2.x,5.x,6.x 都可以安装 Elasticsearch-sql 插件,使用熟悉的SQL语法查询 Elasticsearch。
6.3.0 以后内置支持 SQL 模块,这个 SQL 模块是属于 X-Pack 的一部分。
3 业界案例
- 维基百科使用Elasticsearch来进行全文搜做并高亮显示关键词,以及提供search-as-you-type、did-you-mean等搜索建议功能。
- 英国卫报使用Elasticsearch来处理访客日志,以便能将公众对不同文章的反应实时地反馈给各位编辑。
- StackOverflow将全文搜索与地理位置和相关信息进行结合,以提供more-like-this相关问题的展现。
- GitHub使用Elasticsearch来检索超过1300亿行代码。
- Goldman Sachs使用它来处理每天5TB数据的索引,还有很多投行使用它来分析股票市场的变动。
4 环境搭建-从单点到集群
5 基本概念
本章ES 的核心基本概做一个简单的描述。
Elasticsearch是一个近乎实时(NRT)的搜索平台。这意味着从索引文档到可搜索文档的时间有一点延迟(通常是一秒)。通常有集群,节点,分片,副本等概念。
我们假设有一个集群由三个节点组成(Node1 , Node2 , Node3)。 它有两个主分片(P0 , P1),每个主分片有两个副本分片(R0 , R1)。相同分片的副本不会放在同一节点,所以我们的集群看起来如下图所示 “有三个节点和一个索引的集群”。
我们使用下表来类比ES、Solr和关系型数据库,方便理解各部分的关系:
| elastic search | solr | 关系数据库 |
|---|---|---|
| cluster | solrCloud | cluster |
| index | solr | database |
| type | collection | table |
| document | document | row |
| mapping | schema | 表结构 |
| shard | shard | partition |
| replicas | replication | backup |
索引这个词在Elasticsearch中有着不同的含义,所以有必要在此做一下索引含义的区分:
- 索引(名词) 一个索引就像是传统关系数据库中的数据库,在6.0中也可以认为是一张表因为已经淡化了type的概念,它是相关文档存储的地方。
- 索引(动词) 「索引一个文档」表示把一个文档存储到索引(名词)里,以便它可以被检索或者查询。这很像SQL中的INSERT关键字,差别是,如果文档已经存在,新的文档将覆盖旧的文档。
- 倒排索引 传统数据库为特定列增加一个索引,例如B-Tree索引来加速检索。Elasticsearch和Lucene使用一种叫做倒排索引(inverted index)的数据结构来达到相同目的。
5.1集群(Cluster)
集群(cluster)是一组具有相同cluster.name2的节点集合,他们协同工作,共享数据并提供故障转移和扩展功能,当然一个节点也可以组成一个集群。
集群由唯一名称标识,默认情况下为“elasticsearch”。此名称很重要,因为如果节点设置为按名称加入集群的话,则该节点只能是集群的一部分。
确保不同的环境中使用不同的集群名称,否则最终会导致节点加入错误的集群。
【集群健康状态】
集群状态通过 绿,黄,红 来标识
绿色 - 一切都很好(集群功能齐全)。
黄色 - 所有数据均可用,但尚未分配一些副本(集群功能齐全)。
红色 - 某些数据由于某种原因不可用(集群部分功能)。
注意:当群集为红色时,它将继续提供来自可用分片的搜索请求,但您可能需要尽快修复它,因为存在未分配的分片。
要检查群集运行状况,我们可以在浏览器地址栏输入http://[ip]:9200/_cluster/health?pretty,得到如下信息:
{
"cluster_name" : "cewell-elscluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"active_primary_shards" : 32,
"active_shards" : 64,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 0,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 100.0
}
集群监控相关命令也可以在浏览器地址栏中输入如下地址进行查询http://[ip]:9200/_cat
开启详细输出
/_cat/XXX/?v
输出可用的列
GET /_cat/XXX/?help
指定输出的列
GET /_cat/XXX/?h=column1,column2
指定输出的列进行排序,默认按照升序排序
GET /_cat/XXX/?v&s=column1,column2:desc,column3
**指定响应返回的数据格式:text(默认),json,yaml,smile,cbor
**
GET /_cat/XXX?format=json
查询每个节点上分配的分片(shard)的数量和每个分片(shard)所使用的硬盘容量
/_cat/allocation
输出节点包含分片的详细信息(当前分片是primary shard还是 replica shard,doc的数量,硬盘上占用的字节已经该节点被分配在哪里等)
这个命令可以用于查看分片的迁移情况和分片
/_cat/shards
指定索引(模糊匹配)
/_cat/shards/{index}
仅用于显示master的节点ID,绑定IP地址,节点名称
/_cat/master
输出当前集群的拓扑结构(包括当前节点所在的地方和整个集群的相关信息等)full_id(true/false)用于是否格式化ID字段以显示ID的全长或者简写
/_cat/nodes
输入任务历史
/_cat/tasks
** 查询指定索引或全部索引的相关信息(组成一个索引(index)的shard数量,document的数量,删除的doc数量,主存大小和所有索引的总存储大小(包括replicas)
其中document的数量和删除document的数量是lucense层级的,包括所有隐藏的document数量
要获取Elasticsearch层级的精确的document数量可以使用 cat count或者Count API
**
/_cat/indices
/_cat/indices/{index}
输出索引分片中关于segment的低层级的信息(包括索引名称,分片数量,doc数量等),提供的信息类似于_segments端点
/_cat/segments
查询指定索引的segments信息
/_cat/segments/{index}
所有索引的总文档数
/_cat/count
指定索引的总文档数
/_cat/count/{index}
提供一个视图关于索引分片 正在恢复或者已经完成恢复的相关信息
恢复事件操作可以发生在集群中一个索引分片从一个节点移动到另外一个节点上。可以发生在快照恢复期间,一个replication层级的变化,节点失败,或者节点启动的时候。节点启动的恢复操作也叫本地存储恢复(当一个节点启动的时候分片从硬盘上被加载到)
/_cat/recovery
/_cat/recovery/{index}
集群各节点健康状况
/_cat/health
输出集群中正在执行的任务(集群层级的变化,比如:创建索引,更新mapping,分配或者fail shard)同 /_cluster/pending_tasks
/_cat/pending_tasks
查询当前配置索引,过滤器,路由的别名
如果需要指定一至多个别名,则以逗号隔开
/_cat/aliases
/_cat/aliases/{alias}
输出每个节点集群范围的线程池统计信息,默认情况下返回正在活动,队列和被拒绝的统计信息
/_cat/thread_pool
/_cat/thread_pool/{thread_pools}
输出每个节点正在运行的插件信息
/_cat/plugins
查询集群中每个节点中的fileddata所使用的堆内存
/_cat/fielddata
/_cat/fielddata/{fields}
输出显示自定义节点属性
/_cat/nodeattrs
输出集群中注册快照存储库
/_cat/repositories
输出属于指定仓库的快照信息(snapshots)
每个快照信息包括了它被启动和被停止的信息
/_cat/snapshots/{repository}
输出当前正在存在的模板信息
/_cat/templates
/_cat/templates/{templates_id}
5.2节点(Node)
节点,一个运行的 ES 实例就是一个节点,节点存储数据并参与集群的索引和搜索功能。
就像集群一样,节点由名称标识,默认情况下,该名称是在启动时分配给节点的随机通用唯一标识符(UUID)。如果不需要默认值,可以定义所需的任何节点名称。此名称对于管理目的非常重要,您可以在其中识别网络中哪些服务器与 Elasticsearch 集群中的哪些节点相对应。
可以将节点配置为按集群名称加入特定集群。默认情况下,每个节点都设置为加入一个名为 cluster 的 elasticsearch 集群,这意味着如果您在网络上启动了许多节点并且假设它们可以相互发现 - 它们将自动形成并加入一个名为 elasticsearch 的集群。
5.3索引(Index)
索引是具有某些类似特征的文档集合。例如,您可以拥有店铺数据的索引,商品的一个索引以及订单数据的一个索引。
索引由名称标识(必须全部小写),此名称用于在对其中的文档执行索引,搜索,更新和删除操作时引用索引。
5.4类型(Type)
类型,曾经是索引的逻辑类别/分区,允许您在同一索引中存储不同类型的文档,例如,一种类型用于用户,另一种类型用于博客帖子。
在 6.0.0 中弃用,以后将不再可能在索引中创建多个类型,并且将在更高版本中删除类型的整个概念。
5.5文档(Document)
文档是可以建立索引的基本信息单元。例如,您可以为单个客户提供文档,为单个产品提供一个文档,为单个订单提供一个文档。该文档以JSON(JavaScript Object Notation)表示,JSON是一种普遍存在的互联网数据交换格式。
在索引/类型中,您可以根据需要存储任意数量的文档。请注意,尽管文档实际上驻留在索引中,但实际上必须将文档编入索引/分配给索引中的类型。
5.6 分片(Shards)
索引可能存储大量可能超过单个节点的硬件限制的数据。例如,占用1TB磁盘空间的十亿个文档的单个索引可能不适合单个节点的磁盘,或者可能太慢而无法单独从单个节点提供搜索请求。
为了解决这个问题,Elasticsearch 提供了将索引细分为多个称为分片的功能。创建索引时,只需定义所需的分片数即可。每个分片本身都是一个功能齐全且独立的“索引”,可以托管在集群中的任何节点上。
设置分片的目的及原因主要是:
- 它允许您水平拆分/缩放内容量
- 它允许您跨分片(可能在多个节点上)分布和并行化操作,从而提高性能/吞吐量
分片的分布方式以及如何将其文档聚合回搜索请求的机制完全由 Elasticsearch 管理,对用户而言是透明的。
5.7副本(Replicasedit)
副本,是对分片的复制。目的是为了当分片/节点发生故障时提供高可用性,它允许您扩展搜索量/吞吐量,因为可以在所有副本上并行执行搜索。
总而言之,每个索引可以拆分为多个分片。索引也可以不拆分。复制之后,每个索引将具有主分片(从原始分片复制而来的)和拆分分片(主分片的副本)。
可以在创建索引时为每个索引定义分片和副本的数量。创建索引后,您也可以随时动态更改副本数。您可以使用_shrink和_splitAPI更改现有索引的分片数。
默认情况下,Elasticsearch 中的每个索引都分配了5个主分片和1个副本。
5 ES的特点和使用场景
优点
- Elasticsearch是分布式的。不需要其他组件,分发是实时的,被叫做
push replication,相对于pull replication的方式,能够更及时的存储和查询分片上的数据。 - 处理多租户(multitenancy)不需要特殊配置,而Solr则需要更多的高级设置。
- Elasticsearch 采用 Gateway 的概念,代表es索引的持久化存储方式,es默认是先把索引存放到内存中,当内存满了时再持久化到硬盘。当这个es集群关闭再重新启动时就会从gateway中读取索引数据,尽可能的保持数据一致性。es支持多种类型的gateway,有本地文件系统(默认),分布式文件系统,Hadoop的HDFS和amazon的s3云存储服务。
- 各节点组成对等的网络结构,某些节点出现故障时会自动分配其他节点代替其进行工作。
- 支持分析检索,也就是支持聚合查询
缺点
- 对与强事务场景支持不好
- 关联查询支持不好
父子关系 1对多
与solr比较
当进行小数据量搜索时,solr比es更快
当实时建立索引时进行查询es更具优势,solr会有IO阻塞,es没有
Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;
Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch。
Elasticsearch支持聚合查询,并且支持复杂的时间聚合,以及多字段聚合。
更多与solr比较 这个比较是ES6.2.4 与 Solr7.2.1的比较会遗漏ES的新特性
7Mapping总结
Mapping是定义一个文档及其包含的字段如何存储和索引的过程。例如,使用映射来定义:
- 应将哪些字符串字段视为全文字段。
- 哪些字段包含数字,日期或地理位置。
- 是否应将文档中所有字段的值索引到catch-all _all字段中。
- 日期值的格式。
- 自定义规则以控制动态添加字段的映射。
其实在 ElasticSearch中可以不需要事先定义Mapping,文档写入ElasticSearch时,会根据文档字段自动识别类型,但是通过这种自动识别的字段不是很精确,对于一些复杂的需要分词的就不适合了。
根据是否自动识别Mapping类型,我们可以将Mapping分为动态和静态两种。
- 动态Mapping,即不事先指定Mapping类型,文档写入ElasticSearch时,ES会根据文档字段自动识别类型,这种机制称之为动态Mapping。
- 静态Mapping,即人为事先定义好Mapping,包含文档的各个字段及其类型等,这种方式称之为静态Mapping,亦可称为显式Mapping。
8ES-CLIENT总结
官方支持:
Java, Groovy, PHP, Ruby, Perl, Python, .NET, Javascript
ES 官方支持的Clinets
社区支持:
Clojure, Cold Fusion, Erlang, Go, Groovy, Haskell, Java, JavaScript, .NET, OCaml, Perl, PHP, Python, R, Ruby, Scala, Smalltalk, Vert.x
ES 社区支持Client
9ES-SQL总结
- 6.3版本后不需要安装插件 x-pack集成
- 不支持分词字段聚合
SQL使用说明