【ElasticSearch】

发布于:2025-04-07 ⋅ 阅读:(21) ⋅ 点赞:(0)

目录

1. 基本知识

1.1 restful语法

  1. 新增索引 put /index

  2. 新增文档 put /index/type/id {文档}

  3. 查询文档 get /index/type/id

  4. 修改文档(替换操作) put /index/type/id

  5. 修改文档 (更新文档)POST /{index}/type /{id}/_update 或 POST /{index}/_update/{id}

  6. 删除操作 deete /index/type/id

1.2 内部基于_version乐观锁控制

es内部主从同步时,是多线程异步。采用乐观锁机制。

1.3 restful 批量(bulk)增删改

POST /_bulk
{ "create": { "_index": "test_index",  "_id": "14" }}
{ "test_field": "test14" }
{ "create": { "_index": "test_index",  "_id": "5" }}
{ "test_field": "test14" }
{ "delete": { "_index": "test_index",  "_id": "5" }} 
{ "update": { "_index": "test_index",  "_id": "14"} }
{ "doc" : {"test_field" : "bulk test"} }

``

1、功能:

  • delete:删除一个文档,只要1个json串就可以了
  • create:相当于强制创建 PUT /index/type/id/_create
  • index:普通的put操作,可以是创建文档,也可以是全量替换文档
  • update:执行的是局部更新partial update操作

2、 格式:每个json不能换行相邻json必须换行;

3、 隔离:每个操作互不影响操作失败的行会返回其失败信息;

4、 实际用法:bulk请求一次不要太大,否则一下积压到内存中,性能会下降所以,一次请求几千个操作、大小在几M正好;

2. 分布式及容错机制

2.1 ElasticSearch分布式基础

1 ES分布式机制

  • 分片机制:数据存储到哪个分片,副本数据写入另外分片。
  • 集群发现机制:新启动es实例,会自动加入集群。
  • shard负载均衡:大量数据写入及查询,es会将数据平均分配。举例,假设现在有3个节点,总共有25个shard要分配到3个节点上去,es会自动进行均匀分配,以保持每个节点的均衡的读写负载请求。
  • shard副本:新增副本数,分片重分配。

2 rebalance

当新增或减少es实例时,或者新增加数据或者删除数据时,就会导致某些服务器负载过重或者过轻。es集群就会将数据重新分配,保持一个相对均衡的状态。

3 master节点

1、 管理es集群的元数据

  • 创建删除节点
  • 创建删除索引

2、 默认情况下,es会自动选择一台机器作为master,因为任何一台机器都可能被选择为master节点,所以单点故障的情况可以忽略不计。

4 节点对等

  • 节点对等,每个节点都能接收所有的请求
  • 自动请求路由
  • 响应收集

2.2 分片shard、副本replica机制

  • 每个index包含一个或多个shard
  • 每个shard都是一个最小工作单元,承载部分数据,lucene实例,完整的建立索引和处理请求的能力
  • 增减节点时,shard会自动在nodes中负载均衡
  • primary shard和replica shard,每个document肯定只存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard
  • replica shard是primary shard的副本,负责容错,以及承担读请求负载
  • primary shard的数量在创建索引的时候就固定了,replica shard的数量可以随时修改
  • primary shard的默认数量是1,replica默认是1,默认共有2个shard,1个primary shard,1个replica shard。注意:es7以前primary shard的默认数量是5,replica默认是1,默认有10个shard,5个primary shard,5个replica shard
  • primary shard不能和自己的replica shard放在同一个节点上(否则节点宕机,primary shard和副本都丢失,起不到容错的作用),但是可以和其他primary shard的replica shard放在同一个节点上

2.3 es容错机制

以3分片,2副本数,3节点为例介绍。

  • master node宕机,自动master选举,集群为red
  • replica容错:新master将replica提升为primary shard,yellow
  • 重启宕机node,master copy replica到该node,使用原有的shard并同步宕机后的修改,green

3. 文档(document)内部机制详解

3.1 路由算法

shard = hash(routing) % number_of_primary_shards

对一个文档经行crud时,都会带一个路由值 routing number。默认为文档_id(可能是手动指定,也可能是自动生成)

涉及到以往数据的查询搜索,所以一旦建立索引,主分片数不可变。

3.2 文档写数据过程

1、 客户端选择一个node发送请求过去,这个node就是coordinating node(协调节点)

2、 coordinating node,对document进行路由,将请求转发给对应的node(有primary shard)

3、 实际的node上的primary shard处理请求,然后将数据同步到replica node。

4、 coordinating node,如果发现primary node和所有replica node都搞定之后,就返回响应结果给客户端。

3.3 文档读数据过程

1、 客户端发送请求到任意一个node,成为coordinatenode;

2、 coordinatenode对document进行路由,将请求转发到对应的node,此时会使用round-robin随机轮询算法,在primaryshard以及其所有replica中随机选择一个,让读请求负载均衡;

3、 接收请求的node返回document给coordinatenode;

4、 coordinatenode返回document给客户端;

5、 特殊情况:document如果还在建立索引过程中,可能只有primaryshard有,任何一个replicashard都没有,此时可能会导致无法读取到document,但是document完成索引建立之后,primaryshard和replicashard就都有了;

3.4 搜索机制(过程)

  • 客户端发送请求到一个 coordinate node。
  • 协调节点将搜索请求转发到所有的 shard 对应的 primary shard 或 replica shard,都可以。
  • query phase:每个 shard 将自己的搜索结果(其实就是一些 doc id)返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果。
  • fetch phase:接着由协调节点根据 doc id 去各个节点上拉取实际的 document 数据,最终返回给客户端。

4. mapping的核心数据类型

string :text and keyword,byte,short,integer,long,float,double,boolean,date

4.1 查看索引 mapping

GET index_name/_mapping

4.2 创建索引

PUT book


-- 手动创建映射
PUT book/_mapping
{
    "properties": {
           "name": {
                  "type": "text"
            },
           "description": {
              "type": "text",
              "analyzer":"english",
              "search_analyzer":"english"
           },
           "pic":{
             "type":"text",
             "index":false
           },
           "studymodel":{
             "type":"text"
           }
    }
}

4.3 字段解释

1 Text类型

  1. analyzer:通过analyzer属性指定分词器。上边指定了analyzer是指在索引和搜索都使用english,如果单独想定义搜索时使用的分词器则可以通过search_analyzer`属性。

  2. index:index属性指定是否索引。默认为index=true,即要进行索引,只有进行索引才可以从索引库搜索到。但是也有一些内容不需要索引,比如:商品图片地址只被用来展示图片,不进行搜索图片,此时可以将index设置为false。删除索引,重新创建映射,将pic的index设置为false,尝试根据pic去搜索,结果搜索不到数据。

  3. store:是否在source之外存储,每个文档索引后会在 ES中保存一份原始文档,存放在"_source"中,一般情况下不需要设置store为true,因为在_source中已经有一份原始文档了。

2 keyword 关键字类型

keyword字段为关键字字段,通常搜索keyword是按照整体搜索,所以创建keyword字段的索引时是不进行分词的

3 date日期类型

日期类型不用设置分词器。

通常日期类型的字段用于排序。

format:通过format设置日期格式

4.4 修改映射

只能创建index时手动建立mapping,或者新增field mapping,但是不能update field mapping。因为已有数据按照映射早已分词存储好,如果修改的话,那这些存量数据怎么办。

4.5 删除映射

通过删除索引的方式来删除映射。

DELETE /book

4.6 复杂数据类型

1 multivalue field

数组,建立索引时与string是一样的,注意数组里面存放的数据的数据类型不能混

{ "tags": [ "tag1", "tag2" ]}

2 empty field

空值存放

null[][null]

如果是text或者keyword类型,空值为null,如果是数组类型的话,空值为后面两个中的任意一个。

3 object field

PUT /company/_doc/1
{
  "address": {
    "country": "china",
    "province": "guangdong",
    "city": "guangzhou"
  },
  "name": "jack",
  "age": 27,
  "join_date": "2019-01-01"
}

3 底层存储格式

  1. objec类型

对应的底层存储格式,可以看到其实就是扁平化处理了

{
    "name":            [jack],
    "age":          [27],
    "join_date":      [2017-01-01],
    "address.country":         [china],
    "address.province":   [guangdong],
    "address.city":  [guangzhou]
}
  1. 对象数组
{
    "authors": [
        { "age": 26, "name": "Jack White"},
        { "age": 55, "name": "Tom Jones"},
        { "age": 39, "name": "Kitty Smith"}
    ]
}


// 存储格式

{
    "authors.age":    [26, 55, 39],
    "authors.name":   [jack, white, tom, jones, kitty, smith]
}

5. 采用restful风格对索引的增删改查5

5.1 创建索引

PUT /index
{
    "settings": { ... any settings ... },
    "mappings": {
       "properties" : {
            "field1" : { "type" : "text" }
        }
    },
      // 索引别名
    "aliases": {
        "default_index": {}
  } 
} 

5.2 查询索引

GET /my_index/_mapping

GET /my_index/_setting

5.3 修改索引

//修改索引中的副本数
PUT /my_index/_settings
{
  "index": {
    "number_of_replicas": 2
  }
}

5.4 删除索引

删除索引有好几种方式,指定删除某一个,删除某两个,根据匹配来进行删除,或者直接删除全部索引。

DELETE /my_index

DELETE /index_one,index_two

DELETE /index_*

DELETE /_all

为了安全起见,防止恶意删除索引,生产上可以设置elasticsearch.yml中以下配置,让删除时必须指定索引名:

action.destructive_requires_name: true

6 定制分词器(Analyzer)

主要用于将输入文本拆分成 Token(词元),便于索引和搜索匹配。分词器不仅决定了搜索的准确性,还影响查询效率和相关性。

6.1 分词器组成

分词器的基本组成

一个 分词器(Analyzer) 由以下 3 个组件组成:

① 字符过滤器(Character Filter,可选)

  • 作用:预处理文本,例如去掉 HTML 标签、转换字符等。
  • 常见过滤器
    • html_strip:去除 HTML 标签
    • mapping:字符映射(如 "(" -> "("
    • pattern_replace:正则替换
    • uppercase / lowercase:大小写转换

② 分词器(Tokenizer,必选)

  • 作用:决定文本的切分规则,例如按 空格标点拼音词典 切分。
  • 常见 Tokenizer
    • standard(标准分词器):基于 Unicode 规则切分
    • whitespace(空格分词器):按空格切分
    • keyword(关键字分词器):整个文本作为一个词元
    • ngram(N-Gram 分词器):按固定长度滑动窗口切分
    • edge_ngram(前缀匹配分词器):适合 搜索建议

③ 词元过滤器(Token Filter,可选)

  • 作用:对分词结果进行处理,例如 停用词同义词词干提取 等。
  • 常见 Token Filter
    • lowercase:转小写(HELLO -> hello
    • stop:停用词过滤(isthe 等)
    • synonym:同义词(big -> large
    • stemmer:词干提取(running -> run
    • shingle:生成 n-gram 词组
    • unique:去重

6.2 自定义分词器(Custom Analyzer)

//创建一个包含 HTML 过滤、停用词 以及 标准分词 的自定义分词器
PUT my_index
{
  "settings": {
    "analysis": {
      "char_filter": {
        "html_strip": {
          "type": "html_strip"
        }
      },
      "tokenizer": {
        "custom_tokenizer": {
          "type": "standard"
        }
      },
      "filter": {
        "my_stopwords": {
          "type": "stop",
          "stopwords": ["的", "是", "和", "了"]  // 自定义停用词
        }
      },
// 自定义分词器
      "analyzer": {
        "my_custom_analyzer": {
          "type": "custom",
          "char_filter": ["html_strip"],
          "tokenizer": "custom_tokenizer",
          "filter": ["lowercase", "my_stopwords"]
        }
      }
    }
  }
}

6.3 中文分词器

IK 分词器提供 两种模式

  1. ik_smart(智能分词):按 最大粒度 切分,适合搜索引擎。
  2. ik_max_word(细粒度分词):尽可能多地切分,适合 索引构建
PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "ik_max_analyzer": {
          "type": "custom",
          "tokenizer": "ik_max_word",
          "filter": ["lowercase", "stop"]
        }
      }
    }
  }
}

7 搜索字段解析

7.1 结果字段解析

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "title" : "2019-09-10"
        }
      }
    ]
  }
}

解释

took:took表示Elasticsearch执行搜索所用的时间,单位是毫秒。这里0毫秒代表特别快,实际上一般都在几十毫秒以上。

timed_out:是否超时,这里是没有

_shards:指示搜索了多少分片,成功几个,跳过几个,失败几个。

hits.total:查询结果的数量,3个document

hits.max_score:score的含义,就是document对于一个search的相关度的匹配分数,越相关,就越匹配,分数也高

hits.hits:包含了匹配搜索的document的所有详细数据

7.2 time_out字段解析

time_out机制:指定每个shard只能在给定时间内查询数据,能有几条就返回几条。这样至少能搜索出来结果,用户也能好受一点。

8 多索引搜索

8.1 multi-index 多索引搜索

/_search:所有索引下的所有数据都搜索出来
/index1/_search:指定一个index,搜索其下所有的数据
/index1,index2/_search:同时搜索两个index下的数据
/index*/_search:按照通配符去匹配多个索引

应用场景:生产环境log索引可以按照日期分开。
log_to_es_20200910
log_to_es_20200911
log_to_es_20200910

8.2 _all metadata的原理和作用

直接可以搜索所有的field,任意一个field包含指定的关键字就可以搜索出来

es中all元数据。建立索引的时候,插入一条docunment,es会将所有的field值经行全量分词,把这些分词,放到all field中。在搜索的时候,没有指定field,就在_all搜索。

GET /book/_search?q=java
{
    name:jack
    email:123@qq.com
    address:beijing
}
_all : jack,123@qq.com,beijing

9 deep paging

9.1 性能问题

根据相关度评分倒排序,所以分页过深,协调节点会将大量数据聚合分析。
  1. 消耗网络带宽,因为所搜过深的话,各 shard要把数据传递给 coordinate node,这个过程是有大量数据传递的,消耗网络。

  2. 消耗内存,各 shard 要把数据传送给 coordinate node,这个传递回来的数据,是被 coordinate node 保存在内存中的,这样会大量消耗内存。

  3. 消耗cup,coordinate node 要把传回来的数据进行排序,这个排序过程很消耗cpu。 所以:鉴于deep paging的性能问题,所有应尽量减少使用。

真正的分页
首先每个shard都会将10000条数据给协调节点,协调节点在内存中再排序,拿出我们想要的10条数据,然后在返回给客户端。

综上所述,在实际的应用过程中一般避免分页过深。

10 resful风格查询

10.1 DSL语法

  1. 基本查询(查询DSL)
//匹配查询(全文搜索)
{
  "query": {
    "match": {
      "title": "Elasticsearch DSL"
    }
  }
}
//术语查询(准确匹配)
//term不会对搜索内容分词,适用于关键字类型字段。
{
  "query": {
    "term": {
      "status": "published"
    }
  }
}
//bool查询(组合查询)
//must表示必须匹配,filter仅用于筛选,不计算相关性。
//must(必须匹配)   should(任选匹配,加分项)   must_not(必须不匹配)
{
  "query": {
    "bool": {
      "must": [
        { "match": { "title": "Elasticsearch" } }
      ],
      "filter": [
        { "term": { "status": "published" } },
        { "range": { "publish_date": { "gte": "2024-01-01" } } }
      ]
    }
  }
}

  1. 过滤查询(Filter DSL)
//range(过滤范围)
//使用高效的过滤数据,不影响评分(即_score)。
{
  "query": {
    "range": {
      "price": {
        "gte": 10,
        "lte": 100
      }
    }
  }
}
//exists(检查字段是否存在)
{
  "query": {
    "exists": {
      "field": "email"
    }
  }
}
//术语(多个值匹配)
{
  "query": {
    "terms": {
      "category": ["tech", "science"]
    }
  }
}

  1. 聚合查询(Aggregations)
{
  "size": 0,
  "aggs": {
    "category_count": {
      "terms": {
        "field": "category.keyword"
      }
    }
  }
}



  1. 排序(Sort)
{
  "query": {
    "match_all": {}
  },
  "sort": [
    { "publish_date": "desc" }
  ]
}


  1. 分页(来自+大小)
{
  "query": {
    "match_all": {}
  },
  "from": 10,
  "size": 5
}

部分语法

  1. match_all
  2. match
  3. multi_match
{
  "query": {
    "multi_match": {
      "query": "java程序员",
      "fields": [
        "name"
      ]
    }
  }
}

  1. range query
  2. term query (字段为keyword时,存储和搜索都不分词)
  3. terms query
  4. exist query 查询有某些字段值的文档
  5. Fuzzy query 模糊查询

包括以下几种情况:

更改角色(box→fox)
删除字符(aple→apple)
插入字符(sick→sic)
调换两个相邻字符(ACTCAT{
  "query": {
    "fuzzy": {
      "description": {
        "value": "jave"
      }
    }
  }
}
  1. IDs
  2. prefix 前缀查询
  3. regexp query 正则查询

10.2 Filter与Query对比

在同等查询结果下,filter的性能一般是要优于query的。

filter,仅仅只是按照搜索条件过滤出需要的数据而已,不计算任何相关度分数,对相关度没有任何影响。

query,会去计算每个document相对于搜索条件的相关度,并按照相关度进行排序。

filter,不需要计算相关度分数,不需要按照相关度分数进行排序,同时还有内置的自动cache最常使用filter的数据。比如在范围查询,keyword字段查询中推荐使用filter来进行查询。

query,相反,要计算相关度分数,按照分数进行排序,而且无法cache结果。

10.3 使用explain关键字分析语法

验证语法是否有误

GET /book/_validate/query?explain
{
  "query": {
    "mach": {
      "description": "java程序员"
    }
  }
}

10.4 text字段排序

场景:如果es对一个text field进行排序,es中无法排序。因为文档入倒排索引表时,分词存入,es无法知道此字段的真实值。

两种解决办法:
1、 将一个textfield建立两次索引,一个分词,用来进行搜索;一个不分词,用来进行排序;
2、 mapping时设置fielddata:true,按照第一个分词进行字典序排序这种方式也不是很准确,因为只是按照第一个分词进行排序,后续的分词不会参与排序fielddata:true的排序是对text内部分词结果进行排序之后再进行外部排序的,效率低不推荐使用;

10.5 Scroll 分批查询

场景:下载某一个索引中1亿条数据,到文件或是数据库。

不能一下全查出来,这样会造成系统内存溢出。所以使用scoll滚动搜索技术,一批一批查询。scoll搜索会在第一次搜索的时候,保存一个当时的视图快照,之后只会基于该旧的视图快照提供数据搜索,如果这个期间数据变更,是不会让用户看到的。每次发送scroll请求,我们还需要指定一个scoll参数,指定一个时间窗口,每次搜索请求只要在这个时间窗口内能完成就可以了。

ET /book/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "size": 1
}
//获得的结果里面包含有一个scoll_id,下一次再发送scoll请求的时候,必须带上这个scoll_id,
GET /_search/scroll
{
    "scroll": "1m", 
    "scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAByQWQWx5bzRmTW9TeUNpNmVvN0E2dF9YQQ=="
}

11 相关评分机制

11.1 相关算法

  1. Term frequency(词频)
    搜索文本中的各个词条在field文本中出现了多少次,出现次数越多,就越相关。
搜索请求:阿莫西林
doc1:阿莫西林胶囊是什么。。。阿莫西林胶囊能做什么。。。。阿莫西林胶囊结构
doc2:本药店有阿莫西林胶囊、红霉素胶囊、青霉素胶囊。。。

阿莫西林关键词来说在doc1中出现的次数大于doc2的,所以doc1的优先级高于doc2
  1. Inverse document frequency (文档频率倒数)
    搜索文本中的各个词条在整个索引的所有文档中出现了多少次,出现的次数越多,就越不相关.
搜索请求:阿莫西林胶囊
doc1:A市健康大药房简介。本药店有阿莫西林胶囊、红霉素胶囊、青霉素胶囊。。。
doc2:B市民生大药房简介。本药店有阿莫西林胶囊、红霉素胶囊、青霉素胶囊。。。
doc3:C市未来大药房简介。本药店有阿莫西林胶囊、红霉素胶囊、青霉素胶囊。。。

所有的doc里面都包含这个关键词,那说明这个关键词不是那么重要,说明这个关键词所占的权重很低
  1. Field-length norm(字段长度规范)
    field的长度越长,相关度越弱
搜索请求:A市 阿莫西林胶囊
doc1:{"title":"A市健康大药房简介。","content":"本药店有、红霉素胶囊、青霉素胶囊。。。(一万字)"}
doc2:{"title":"B市民生大药房简介。","content":"本药店有阿莫西林胶囊、红霉素胶囊、青霉素胶囊。。。(一万字)"}

11.2_score是如何被计算出来的

步骤如下:

1、 对用户输入的关键词分词;
2、 每个分词分别计算对每个匹配文档的TF和IDF值;
3、 综合每个分词的TF/IDF值,利用公式计算每个文档总分;
4、 最后按照score降序返回;

11.3 document判断是否被匹配

测试判断一个文档能不能被搜索到,适用于生产环境
GET /book/_explain/1
{
  "query": {
    "match": {
      "description": "java程序员"
    }
  }
}

12 文档查询

12.1 query

1 query

  1. 搜索请求发送到某一个coordinate node,构构建一个priority queue,长度以paging操作from和size为准,默认为10
  2. coordinate node将请求转发到所有shard,每个shard本地搜索,并构建一个本地的priority queue
  3. 各个shard将自己的priority queue返回给coordinate node,并构建一个全局的priority queue

一次请求要打到所有shard的一个replica/primary上去,如果每个shard都有多个replica,那么同时并发过来的搜索请求可以同时打到其他的replica上去。

2 fetch

  1. coordinate node构建完priority queue之后,就发送mget请求去所有shard上获取对应的document
  2. 各个shard将document返回给coordinate node
  3. coordinate node将合并后的document结果返回给client客户端

12.2 preference

结果跳跃(bouncing results)问题?
两个document排序,field值相同;不同的shard上,可能排序不同;每次请求轮询打到不同的replica shard上;每次页面上看到的搜索结果的排序都不一样。这就是bouncing result,也就是跳跃的结果。

解决方案:设置preference参数,使每个user每次搜索的时候,都使用同一个replica shard去执行,就不会看到bouncing results了

preference参数决定了哪些shard会被用来执行搜索操作

  • _primary:发送到集群的相关操作请求只会在主分片上执行。
  • _primary_first:指查询会先在主分片中查询,如果主分片找不到(挂了),就会在副本中查询。
  • _replica:发送到集群的相关操作请求只会在副本上执行。
  • _replica_first:指查询会先在副本中查询,如果副本找不到(挂了),就会在主分片中查询。
  • _local: 指查询操作会优先在本地节点有的分片中查询,没有的话再在其它节点查询。
  • _prefer_nodes:abc,xyz:在提供的节点上优先执行(在这种情况下为’abc’或’xyz’
  • _shards:2,3:限制操作到指定的分片。 (2和“3”)。这个偏好可以与其他偏好组合,但必须首先出现:_shards:2,3 | _primary
  • _only_nodes:node1,node2:指在指定id的节点里面进行查询,如果该节点只有要查询索引的部分分片,就只在这部分分片中查找,不同节点之间用“,”分隔。
GET /_search?preference=_shards:2,3

12.3 search_type

es查询步骤
1、 ES客户端将会同时向5个分片发起搜索请求;
2、 这5个分片基于本分片的内容独立完成搜索,然后将符合条件的结果全部返回;
存在两个问题:
1、 数量问题
2、 排名问题

ES 也没有什么较好的解决方法, 最终把选择的权利交给用户, 方法就是在搜索的时候指定 search type

  1. query and fetch
    向索引的所有分片 ( shard)都发出查询请求, 各分片返回的时候把元素文档 ( document)和计算后的排名信息一起返回。
    优点:这种搜索方式是最快的。因为相比后面的几种es的搜索方式,这种查询方法只需要去shard查询一次。
    缺点:返回的数据量不准确, 可能返回(N*分片数量)的数据并且数据排名也不准确,同时各个shard返回的结果的数量之和可能是用户要求的size的n倍。

  2. query then fetch
    es默认的搜索方式,如果你搜索时, 没有指定搜索方式, 就是使用的这种搜索方式。 这种搜索方式, 大概分两个步骤:
    1、 先向所有的shard发出请求,各分片只返回文档id(注意,不包括文档document)和排名相关的信息(也就是文档对应的分值),然后按照各分片返回的文档的分数进行重新排序和排名,取前size个文档;
    2、 根据文档id去相关的shard取document这种方式返回的document数量与用户要求的大小是相等的;
    优点:返回的数据量是准确的。
    缺点:性能一般,并且数据排名不准确

  3. DFS query and fetch
    这种方式比第一种方式多了一个 DFS 步骤,有这一步,可以更精确控制搜索打分和排名。也就是在进行查询之前, 先对所有分片发送请求, 把所有分片中的词频和文档频率等打分依据全部汇总到一块, 再执行后面的操作、
    优点:数据排名准确
    缺点:性能一般,返回的数据量不准确, 可能返回(N*分片数量)的数据

  4. DFS query then fetch
    比第2 种方式多了一个 DFS 步骤。也就是在进行查询之前, 先对所有分片发送请求, 把所有分片中的词频和文档频率等打分依据全部汇总到一块, 再执行后面的操作、

优点:返回的数据量是准确的;数据排名准确
缺点:能最差,这个最差只是表示在这四种查询方式中性能最慢, 也不至于不能忍受,如果对查询性能要求不是非常高, 而对查询准确度要求比较高的时候可以考虑这个

  1. DFS过程
    DFS 其实就是在进行真正的查询之前, 先把各个分片的词频率和文档频率收集一下, 然后进行词搜索的时候, 各分片依据全局的词频率和文档频率进行搜索和排名。 显然如果使用DFS_QUERY_THEN_FETCH 这种查询方式, 效率是最低的,因为一个搜索, 可能要请求 3 次分片。 但使用 DFS 方法, 搜索精度是最高的。

总结一下, 从性能考虑QUERY_AND_FETCH 是最快的,DFS_QUERY_THEN_FETCH 是最慢的。从搜索的准确度来说, DFS 要比非 DFS 的准确度更高。

12.4 聚合概念(bucket和metric)

  • metric: 对每个bucket中所有的数据,计算一个数量。例如avg(),sum(),max(),min()
  • bucket: 分组 等

13 Logstash

logstash简单来说就是一个数据抽取工具,将数据从一个地方转移到另一个地方。

13.1 配置文件

Logstash配置文件有如下三部分组成,其中input、output部分是必须配置,filter部分是可选配置,而filter就是过滤器插件,可以在这部分实现各种日志过滤功能。

input {
   输入插件
}
filter {
   过滤匹配插件
}
output {
   输出插件
}

13.2 input

input {
	//读取文件 
    file {
        path => ["E:/nginx*.log"]        
        start_position => "beginning"
    }
	//读取tcp网络数据
  tcp {
    port => "1234"
  }
}

13.2 filter

Filter帮我们对数据进行解析,丰富,转换

  1. Grok正则捕获
%{语法: 语义}
  1. 时间处理(Date)
  2. 数据修改(Mutate)

例子:

input {
    stdin {}
}
filter {
    grok {
        match => { "message" => "%{IP:clientip}\ \[%{HTTPDATE:timestamp}\]\ %{QS:referrer}\ %{NUMBER:response}\ %{NUMBER:bytes}" }
        remove_field => [ "message" ]
   }
date {
        match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
    }
mutate {
          convert => [ "response","float" ]
           rename => { "response" => "response_new" }   
           gsub => ["referrer","\"",""]          
           split => ["clientip", "."]
        }
}
output {
    stdout {
        codec => "rubydebug"
    }

13.3 output

output {
// 保存文件
    file {
        path => "/data/log/%{+yyyy-MM-dd}/%{host}_%{+HH}.log"
    }
// 保存es
elasticsearch {
        host => ["192.168.1.1:9200","172.16.213.77:9200"]
        index => "logstash-%{+YYYY.MM.dd}"       
    }
}

Logstash提供了%{+YYYY.MM.dd}这种写法

参考