ElasticSearch 是一个近实时的搜索平台。也就是说当你索引一个文档时可能出现轻微的延迟(通常都是秒级别),公司的logcenter出现的延时是出如今Kafka2ES层,而非索引层。html
ElasticSearch 是一个分布式可扩展的实时搜索和分析引擎,一个创建在全文搜索引擎 Apache Lucene(TM) 基础上的搜索引擎。固然 ElasticSearch 并不只仅是 Lucene 那么简单,它不只包括了全文搜索功能,还能够进行如下工做:node
一个分布式的实时文档存储,每一个字段均可以被索引与搜索mysql
一个分布式实时分析搜索引擎sql
能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据数据库
ElasticSearch英文翻译:弹性搜索。json
能够这样理解:ElasticSearch是一个面向文档型的数据库,一条数据在里面就是一个文档,用JSON做为文档序列化格式。下面是一份ElasticSearch和关系型数据库术语的对比关系表:api
MySQL数组 |
ElasticSearch缓存 |
|
---|---|---|
Database(数据库)安全 |
对应的术语 |
含义 |
索引(Index) |
一系列文档的集合,相似于mysql中数据库的概念 |
|
Table(表) |
类型(type) |
在Index里面能够定义不一样的type,type的概念相似于mysql中表的概念,是一系列具备相同特征数据的结合。 |
Row (行) |
文档(Document) |
文档的概念相似于mysql中的一条存储记录,而且为json格式,在Index下的不一样type下,能够有许多document。 |
Column (列) |
字段(Fields) |
|
Index (索引) |
Everything Indexed by default (全部字段默认都被索引) |
|
SQL (结构化查询语言) |
Query DSL (查询专用语言) |
|
Shards |
在数据量很大的时候,进行水平的扩展,提升搜索性能。 分片只保存了索引中全部数据的一部分。 咱们的文档存储在分片中,而且在分片中被索引,可是咱们的应用程序不会直接与它们通讯,取而代之的是,直接与索引通讯。 文档存储在分片中,而后分片分配到你集群中的节点上。当你的集群扩容或缩小,Elasticsearch将会自动在你的节点间迁移分片,以使集群保持平衡。 |
|
Replicas |
防止某个分片的数据丢失,能够并行得在备份数据里及搜索提升性能。 |
优点 |
含义 |
---|---|
横向可扩展性 |
增长服务器可直接配置在集群中,只须要保证cluster.name一致便可。 |
分片机制 |
可以提供更好的分布性,分而治之的方式来提高处理效率。 |
高可用 |
提供复制备份(replica)机制。 |
实时性 |
经过将磁盘上的文件放入文件缓存系统来提升查询速度。 |
关于数据库的水平扩展和竖直扩展:对于大多数数据库而言,横向扩展意味着你的程序将作很是大的改动才能利用这些新添加的设备。对比来讲,Elasticsearch天生就是分布式的,它知道如何管理节点来提供高扩展和高可用。这意味着你的程序不须要关心这些。 只要在建立集群(cluster)、节点(node)和分片(shards)的时候,按照必定的规则,则能按照你的需求进行扩展,并保证在硬件故障的时候数据依然安全。
为说明分片和复制分片的含义,以及如何扩展,这里举一个栗子:
(1)、启动一个空节点,这时它没有索引也没有文档数据。
(2)、咱们添加了一个名为log的索引,设置它有三个主分片。(ES默认是5个主分片)。
(3)、单一节点运行很容易出现单点故障--数据丢失,这时咱们扩展第二个节点,设置相同的cluster.name就能够加入同个集群,设置log索引每一个主分片有一个复制分片,这时任意一个节点故障都能依然支持客户端的查询需求。
(4)、这时咱们继续扩展,扩展第三个节点,ES集群会从新组织本身,分片会从新被分配以达到平衡负载,这时每一个节点只有两个分片,与以前相比少了一个,意味着每一个节点的分片有更多的资源,好比CPU、I/O等。
(5)、若是一个节点只有一个分片的话,那么该分片就可独享当前节点的全部资源。若是咱们须要扩展到6个节点以上?主分片的数量在建立索引时已经肯定,那么咱们能够增长复制分片的数量,能够设置每一个分片有一个复制分片为两个。
(6)、ES能够应对单点故障,这时咱们杀掉一个节点进程,且是主节点,ES会在瞬间选举出一个新的主节点,且可以支持全部数据的查询访问。
关系型数据库的B-/B+Tree,ES采用倒排索引,ES索引的一切设计都是为了提升搜索的性能。
是为优化写入的索引结构,特色是二叉查找效率为logN,同时插入新的节点没必要移动所有节点,因此用树型结构存储索引,能同时兼顾插入和查询的性能。
倒排索引的结构:
举个栗子:
ID |
Name |
Age |
Sex |
---|---|---|---|
1 |
Kate |
24 |
女 |
2 |
John |
24 |
男 |
3 |
Bill |
29 |
男 |
那么ES创建的索引以下:
Name:
Term |
Posting List |
---|---|
Kate |
[1] |
John |
[2] |
Bill |
[3] |
Age:
Term |
Posting List |
---|---|
24 |
[1,2] |
29 |
[3] |
Sex:
Term |
Posting List |
---|---|
男 |
[2,3] |
女 |
[1] |
如上,Elasticsearch分别为每一个field都创建了一个倒排索引,Kate, John, 24, Female这些叫term,而1,2就是Posting List。Posting list就是一个int的数组,存储了全部符合某个term的文档id。在ES的每一部分中都采用了一些优化及压缩技术,例如Term Index采用相似字典的索引页的方式,能够理解为一棵树,Term Dictionary存储block,从Term Index找到对应的节点后再去Term Dictionary中寻找对应的block,从而磁盘去寻找Term。
这样简化存储后,ES仍然没有知足,为了将Term Index、Term Dictionary及Posting List存储入内存,Term Index使用了FST的压缩,Posting List采用:增量编码压缩,将大数变小数,按字节存储的方式进行压缩。
Posting List的压缩:
和ES的交互方式取决于你是否使用JAVA。如下咱们是以JAVA为例对ES的查询进行说明。
若是你正在使用 Java,在代码中你可使用 ElasticSearch 内置的两个客户端:节点客户端(Node client)、传输客户端(Transport client)。Java客户端默认端口是9300,而且使用ES的原生传输协议和集群进行交互。
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'复制代码
被 < > 标记的部件 |
含义 |
VERB |
适当的 HTTP
方法
或
谓词
: GET`、 `POST`、 `PUT`、 `HEAD 或者 `DELETE`。 |
PROTOCOL |
http 或者 https`(若是你在 ElasticSearch 前面有一个 `https 代理) |
HOST |
ElasticSearch 集群中任意节点的主机名,或者用 localhost 表明本地机器上的节点。 |
PORT |
运行 ElasticSearch HTTP 服务的端口号,默认是 9200 。 |
PATH |
API 的终端路径(例如 _count 将返回集群中文档数量)。Path 可能包含多个组件,例如:_cluster/stats 和 _nodes/stats/jvm 。 |
QUERY_STRING |
任意可选的查询字符串参数 (例如 pretty 将格式化地输出 JSON 返回值,使其更容易阅读) |
BODY |
一个 JSON 格式的请求体 (若是请求须要的话) |
举两个栗子:
(1)、计算集群中文档的数量,咱们能够用这个:
curl -XGET 'http://localhost:9200/_count?pretty' -d ' { "query": { "match_all": {} } }复制代码
ES将返回一个HTTP状态码(例如:200 OK`)和(除`HEAD`请求)一个JSON 格式的返回值。JSON 体以下:
{
"count" : 0,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
}
}复制代码
(2)、以新美大日志中心的查询为例:
curl -XPOST 'http://es.data.sankuai.com/log.mapi-log-service.userbehaviours_all/_search?pretty' -d' { "query": { //TODO:查询语句 }, "size":"100" }'复制代码
两种方式:发送HTTP GET请求进行检索、使用ES查询表达式 (DSL) 检索。
第一种方式即构造HTTP GET请求:(如下为缩写格式,即省略了请求中全部的相同部分,例如主机名、端口号以及curl命令自己,非完整请求)
参考:www.elastic.co/guide/cn/el…
curl -XGET /megacorp/employee/1复制代码
返回信息包含一些基本信息以及搜索的JSON元数据:
{
"_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" ]
}
}复制代码
第二种方式即便用使用ES查询表达式 (DSL) 检索:将请求参数按照ES约定的格式构造为一个JSON进行请求。
参考:www.elastic.co/guide/cn/el…
经常使用的查询:
查询方式 |
含义 |
使用方法 |
备注 |
||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
term过滤 |
term主要用于精确匹配哪些值,好比数字,日期,布尔值或 not_analyzed 的字符串。 not_analyzed 的字符串:未经切词的文本数据类型。 |
{
"query": {
"term": {
"title": "内蒙古"
}
}
}复制代码
|
|||||||||||
terms过滤 |
terms 跟 term 有点相似,但 terms 容许指定多个匹配条件。 若是某个字段指定了多个值,那么document须要一块儿去作匹配。 |
{
"query": {
"terms": {
"title": [
"内蒙古",
"黑龙江"
]
}
}
}复制代码
|
|||||||||||
range |
range过滤容许咱们按照指定范围查找一批数据。 |
{
"query":{
"range": {
"pubTime": {
"gt": "2017-06-25",
"lt": "2017-07-01"
}
}
}
}复制代码
|
范围操做符包含:
|
||||||||||
exists和missing |
exists 和 missing 过滤能够用于查找文档中是否包含指定字段或没有某个字段,相似于SQL语句中的IS_NULL条件。 这两个过滤只是针对已经查出一批数据来,可是想区分出某个字段是否存在的时候使用。 |
{
"exists":{
"field":"title"
}
}复制代码
|
|||||||||||
bool过滤 |
bool 过滤能够用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操做符: must :: 多个查询条件的彻底匹配,至关于 and。 must_not :: 多个查询条件的相反匹配,至关于 not。 should :: 至少有一个查询条件匹配, 至关于 or。 这些参数能够分别继承一个过滤条件或者一个过滤条件的数组 |
{
"bool":{
"must":{
"term":{
"folder":"inbox"
}
},
"must_not":{
"term":{
"tag":"spam"
}
},
"should":[
{
"term":{
"starred":true
}
},
{
"term":{
"unread":true
}
}
]
}
}复制代码
|