ES 思维导图

ElasticSearch总结.xmind

ElasticSearch总结

ES 的定位

  1. ES 是 build on top of Lucene 建立的可以集群化部署的搜素引擎。
  2. ES 可以是 document store(此处可以理解为文档仓库或者文档存储),可以结构化解决数据仓库存储的问题。在 es 中一切皆对象,使用对象对数据建模可以很好地处理万事万物的关系。

  3. ES 是海量数据的分析工具能够支持:搜索、分析和实时统计。

ES 的架构有优越的地方:

  1. 自己使用 pacifica 协议,写入完成就达成共识。
  2. 节点对内对外都可以使用 RESTful API(or json over http)来通信,易于调试。
  3. 因为它有很多很好的默认值,所以开箱即用。
  4. 它天生就是分布式的,可以自己管理多节点。

ES 的架构

ES 是基于 Lucene 的,集群上的每个 node 都有一个 Lucene 的实例。而 Lucene 本身是没有 type 的,所以 ES 最终也去掉了 type。

ES 中每个节点自己都能充当其他节点的 proxy,每个节点都可以成为 primary。用户需要设计拓扑的时候只需要关注种子节点和 initial master 即可。

ES 中的搜索

全文搜索

按照《全文搜索》中的例子,使用 match 总会触发全文搜索。因为在Elasticsearch中,每一个字段的数据都是默认被索引的。也就是说,每个字段专门有一个反向索引用于快速检索。想不要做索引需要对任意的 properties 使用 "index": "not_analyzed"

精确(短语)搜索

精确查询的方法有:

短语查询

1
2
3
4
5
6
7
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}

这种查询可以查出rock climbinga rock climbing

term 查询(这种查询是客户端查询里最常用的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"query": {
"bool": {
"must": [
{
"term": {
"about" : "rock climbing"
}
}
],
"must_not": [],
"should": [],
"filter": []
}
},
"from": 0,
"size": 10,
"sort": [],
"profile": false
}

这种查询可以查出rock climbing,不可以查出a rock climbing

另一种 phrase 查询:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"from": 0,
"size": 200,
"query": {
"bool": {
"must": {
"match": {
"about": {
"query": "rock climbing",
"type": "phrase"
}
}
}
}
}
}

精确和不精确查询有好几种方法,详见《elasticsearch 查询(match和term)》《finding_exact_values》

注意,es 的查询可以有很多的变种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// 以下几个查询请求体在语义上等价

{
"query" : {
"match": {
"content": "我的宝马多少马力"
}
}
}

// 加入了嵌套的 content 和 query,content 就是 field name 的意思
{
"query": {
"match": {
"content" : {
"query" : "我的宝马多少马力"
}
}
}
}

// 在同层级里加入 filtered 和 filter
{
"query": {
"filtered": {
"filter": {
"range": {
"age": {
"gt": 30
}
}
},
"match": {
"content": "我的宝马多少马力"
}
}
}
}

// 使用 bool 子句进行查询
{
"query": {
"bool": {
"must": [
{
"match": {
"content": "我的宝马多少马力"
}
}
]
}
}
}

// 使用 term 来提供 query
{
"query": {
// 注意,即使一个 doc 的原始 content 是 我的宝马多少马力,它如果被 analyzed 过了,这个搜索可能还是搜不出来东西
"term": { "content":"我的宝马多少马力"}
}
}

//

{
"query": {
"terms": {
"content": [
"我的宝马多少马力"
]
}
}

elastic-search查询字句整理
elastic-search查询字句整理

search api 的搜索

参考《空查询》

倒排索引简析

倒排索引的 key 是 term,value 是文档的指针,可以参考这个《倒排索引》文档。

过滤机制

头机制

x-pack

version 机制

容量与分片

为何分片不宜过大?

  1. 增加索引读压力-不利于并行查询。
  2. 不利于集群扩缩容(分片迁移耗费较长时间)。
  3. 集群发生故障时,恢复时间较长。

类似的问题也会发生在 Redis 之类的架构方案里。

解决大分片的方法

  1. 索引按月、日进行分割。
  2. delete_by_query 方法删除索引对索引进行缩容。
  3. 模板增加主分片数量-存疑,通常只能增加副本数,而无法改变切片比例。
  4. 扩容数据节点。
  5. 减小单位分片大小。

一个可实操的方案:

  1. 修改写入逻辑和 mapping,让新写入的 doc 的 field 变少。
  2. 对老的索引进行 delete_by_query。

常用查询段

  • aggs
  • match
    • 等于分词以后的 or 查询,依赖于 analyzer。“hello world”如果被分词为 hello 和 world,则类似term = hello or term = wolrd
  • match_phrase
    • term 出现在一个句子中,句子包含 term,依赖于 analyzer。类似contains("hello world")
    • 这是 String.contains。
    • 不匹配 slop,还不如用 term。
  • page:
  • range:是大于等于小于的意思,不是 from 和 size
  • search_after
  • term
    • term 类似于 Collection.contains"[hello, world]".contains("hello")"[hello]".terms("hello") 都成立。
  • terms:term 的数组形式,类似in,是多值或的意思。
  • wildcard:
    • 允许指定匹配的正则式。它使用标准的 shell 通配符查询:? 匹配任意字符,* 匹配 0 或多个字符。

写入流程

写入流程

  • 同步双写:对数据的实时性要求极高,通常在一个事务中完成数据的双写动作,保证数据层面的强一致性;

  • 异步解耦:在完成数据库的写动作之后,基于MQ消息解耦索引的写入,流程存在轻微的延迟,如果消费失败会导致数据缺失;

  • 定时任务:通过任务调度的方式,以指定的时间周期执行新增数据的同步机制,存在明显的时效问题;

  • 组件同步:采用合适的同步组件,比如官方提供的组件或者一些第三方开源的组件,在原理上与任务同步类似;

数据同步的选型方案有多种,如何选择完全看具体的场景,在过往的使用过程中,对于核心业务会采用同步双写,对于内部的活动类业务会采用异步的方式,对于业务日志会采用任务调度,对于系统的监控或执行日志则多是依赖同步组件;

数据同步

数据同步方案

设计难点

翻页

ES中常用From/Size进行分页查询,但是存在一个限制,在索引的设置中存在max_result_window分页深度的限制,6.8版本默认值是10000条,即10000之后的数据无法使用From/Size翻页;

先从实际应用场景来分析,大多数的翻页需求最多也就前10页左右,所以从这个角度考虑,ES的翻页限制在合理区间,在实践中也存在对部分索引调高的情况,暂未出现明显问题;

再从技术角度来思考一下,如果翻页的参数过大意味着更多的数据过滤,那计算资源的占用也会升高,ES引擎的强大在于搜索能力,检索出符合要求的数据即可;

索引设计

聚合

指标聚合

桶聚合

性能分析

Quantitative Cluster Sizing

It depends.

ES 运行,是要解决 scale 和 speed 的矛盾。

有4种 basic computing resources:

  • storage: 热数据放在贵硬件里。分成 warm tier 和 cold tier。
  • memory:heap 使用 50% 内存就行了,堆不需要超过30gb,否则 gc 会是大问题:biz object、meta data(index、cluster)、segment。剩下的内存仍然有用,os cache、file cache 用来存储搜索和分析用的数据 in a cache format。es 会有很棒的缓存机制,既缓存最热的,也缓存长尾的(也要关注长尾是很多人意想不到的)。
    • ML 节点很消耗内存。
    • 如果有必要,使用 dedicated server 来 host master 节点。
  • compute:
    • 一定要知道我们的核心数、线程数和队列数的关系。
  • network:
    • 跨级群搜索的时候需要考虑网络问题。这时候我们要考虑“联合客户端”tribe node。

基本操作:

  • index: store for future retrieval.
  • delete
  • update
  • search