Elasticsearch入门指南(三) 之 高级篇

01. 数据聚合

聚合的分类

聚合(aggregations) 可以实现对文档数据统计、分析、运算。聚合常见的有三类:

  • 桶(Bucket)聚合:用来对文档做分组
  • TermAggregation :按照文档字段值分组
  • Date Histogram :按照日期阶梯分组,例如一周为一组,或者一月为一组
  • 度量(Metric)聚合 :用以计算一些值,比如:最大值、最小值、平均值等
    • Avg:求平均值
    • Max:求最大值
    • Min:求最小值
    • Stats:同时求max、min、 avg、 sum等
  • 管道(pipeline) 聚合 :其它聚合的结果为基础做聚合
    参与聚合的字段类型必须是:keyword、数值、日期、布尔

DSL实现Bucket聚合

现在,我们要统计所有数据中的酒店品牌有几种,此时可以根据酒店品牌的名称做聚合。
聚合三要素 :聚合名称、聚合类型、聚合字段

类型为term类型,DSL示例:

clike 复制代码
GET /hotel/_search
{
    "query":{"match_all":{}},
    "size": 0, // 设置size为0,结果中不包含文档,只包含聚合结果
    "aggs": { //定义聚合
        "brandAgg": { //给聚合起个名字
            "terms": { //聚合的类型,按照品牌值聚合,所以选择term
                "field": "brand", //参与聚合的字段
                "size": 20 //希望获取的聚合结果数量
             }
       }
}

Bucket聚合-聚合结果排序

默认情况下,Bucket聚合会统计Bucket内的文档数量,记为_count,并且按照 count降序排序

我们可以修改结果排序方式:

clike 复制代码
GET /hotel/_search
{
    "size": 0, 
    "aggs": { 
        "brandAgg": { 
            "terms": { 
                "field": "brand", 
                "order":{
                    "_count": "asc"   //按照_count升序排序             
                }
                "size": 20 
             }
       }
}

Bucket聚合,限定聚合范围

默认情况下,Bucket聚合是对索引库的所有文档做聚合,我们可以限定要聚合的文档范围 ,只要添加query条件即可。

clike 复制代码
GET /hotel/_search
{
    "query":{
        "range":{
            "price":{
                "lte":200//只对200元以下的文档聚合            
            }        
        }    
    }
    "size": 0, 
    "aggs": { 
        "brandAgg": { 
            "terms": { 
                "field": "brand", 
                "size": 20 
             }
       }
}

DSL实现 Metrics 聚合

例如,我们要实现每个品牌的用户平分的Min、max、avg等值

clike 复制代码
GET /hotel/_search
{
    "size": 0, 
    "aggs": { 
        "brandAgg": { 
            "terms": { 
                "field": "brand", 
                "size": 20,
                "order": {
                     "scroe_stats.avg":"desc" //可对聚合后聚合的结果做排序               
                }
             },
             "aggs":{ //是brand聚合的子聚合,也就是分组后对每组分别进行计算
                 "score_stats":{ //聚合名称
                     "stats": { //聚合类型,这里stats可以计算min、max、avg等
                         "filed": "score"  //聚合字段,这里是score                 
                     }                 
                 }             
             }  
       }
}

RestAPI实现聚合


聚合结果解析

02 自动补全

拼音分词器

使用拼音分词

要实现根据字母做补全,就必须对文档按照拼音分词。在GitHub上恰好有elasticsearch的拼音分词插件。地址:
https://github.com/medcl/elasticsearch-analysis-pinyin

安装方式与IK分词器一样,分三步:

①解压

②上传到 虚拟机中,elasticsearch的plugins目录(/var/lib/docker/volumes/es-plugins/_data

③重启elasticsearch

④测试

clike 复制代码
POST /_analyze
{
    "analyzer": "pinyin",
    "text": "如家酒店还不错"
}

分词结果:rjjdhbc、ru、jia、jiu、dian、hai、bu、cuo

拼音分词器缺点

  • 全部转成拼音,丢弃了汉字

自定义分词器

clike 复制代码
PUT /test
{
    "settings": {
        "analysis": {
            "analyzer": {
                "my_analyzer": {
                    "tokenizer": "ik_max_word",
                    "filter": "py"
                 }
            },
            "filter": {
                "py": {
                    "type": "pinyin",
                    "keep_full_pinyin": false,
                    "keep_joined_full_pinyin": true,
                    "keep_original": true,
                    "limit_first_letter_length": 16,
                    "remove_duplicated_term": true,
                    "none_chinese_pinyin_tokenize": false
                }
             }
         }
    }
}

elasticsearch中分词器(analyzer) 的组成包含三部分:

  • character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符
  • tokenizer:将文本按照一定的规则切割成词条(term) 。例如keyword,就是不分词;还有ik_smart
  • tokenizer filter:将tokenizer输出的词条做进一步处理。 例如大小写转换、同义词处理、拼音处理等

我们可以在创建索引库时,通过settings来配置自定义的analyzer ( 分词器) :

拼音分词器适合在创建倒排索引时使用,但不能在搜索的时候使用

completion suggester查询

clike 复制代码
# 自动补全查询
POST /test2/_search
{
    "suggest": {
        "title_suggest": {
            "text": "s",
            "completion": {
                "field": "title",
                "skip_duplicates": true,
                "size": 10
            }
        }
    }
}

elasticsearch提供了Completion Suggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。为了提高补全查询的效率,对于文档中字段的类型有一些约束:

  • 参与补全查询的字段必须是completion类型。
  • 字段的内容一般是用来补全的多个词条形成的数组。

查询语法

RestAPI 实现自动补全查询


查询结果解析

03 数据同步

数据同步问题分析

elasticsearch中的酒店数据来自于mysql数据库,因此mysql数据发生改变时,elasticsearch也必须跟着改变,这个就是elasticsearch与mysql之间的数据同步

在微服务中,负责酒店管理(操作mysql )的业务与负责酒店搜索(操作elasticsearch )的业务可能在两个不同的微服务上,数据同步该如何实现呢?

方案一:同步调用

缺点 :数据耦合

方案二:异步通知

缺点 :引入mq,复杂度上升

方案三:监听binlog

耦合度最低,但完全依赖canal中间件,而且使用mysql的binlog ,增加了mysql的压力。

总结

方式一:同步调用

  • 优点:实现简单,粗暴
  • 缺点:业务耦合度高
    方式二:异步通知
  • 优点:低耦合,实现难度一般
  • 缺点:依赖mq的可靠性
    方式三:监听binlog
  • 优点:完全解除服务间耦合
  • 缺点:开启binlog增加数据库负担、实现复杂度高
    tip: 这里要先启动hotel-admin(消息发送者),不然会报错

04 es集群

单机的elasticsearch做数据存储,必然面临两个问题:海量数据存储问题、单点故障问题。

  • 海量数据存储问题:将索引库从逻辑上拆分为N个分片(shard) ,存储到多个节点
  • 单点故障问题 :将分片数据在不同节点备份(replica )索引库

搭建es集群

需要用到三台机器搭建,可用3个docker节点模拟3个es的节点(参考安装elasticsearch

es集群的节点角色

搜索架构需管理集群、存储数据并处理搜索请求。为了避免在扩容时浪费资源,可以将这些功能拆分,赋予节点不同角色:

  • 主节点 (Master Node):管理集群。
  • 数据节点 (Data Node):存储管理数据。
  • 协调节点 (Coordinate Node) :处理客户端搜索请求。
    在小规模集群中,一个节点可充当多个角色,随着规模增大,建议每个节点专注于单一角色。

    tip: 不同职责节点对硬件要求也不同

ES集群的分布式查询

Elasticsearch 中每个节点角色负责不同职责,建议集群部署时每个节点具备独立角色

ES集群的脑裂

默认情况下,所有节点都是候选主节点,一旦主节点宕机,候选节点会选举新主。若主节点与其他节点失去网络连接,可能发生脑裂

为避免脑裂,选票需超过 (eligible节点数量 + 1) / 2,因此候选节点数量应为奇数 。配置项为 discovery.zen.minimum_master_nodes,在 ES 7.0 后已成为默认设置。

ES集群的分布式存储

数据保存到某一个分片,但查询时所有分片上都能查到,加上参数 "explaine" : true可以看到具体在哪个分片上

当新增文档时,应该保存到不同分片,保证数据均衡,那么coordinating node如何确定数据该存储到哪个分片呢?

elasticsearch会通过hash算法来计算文档应该存储到哪个分片:

clike 复制代码
shard = hash(_routing) % number_of_shards
  • _routing 默认为文档 ID
  • 分片数量在索引创建后不可修改

查询流程:

Elasticsearch 查询分为两个阶段:

  1. Scatter Phase:协调节点将请求分发到所有分片。
  2. Gather Phase:协调节点汇总数据节点的结果,并返回最终结果。

故障转移

集群的主节点监控节点状态,发现宕机节点后,会迁移其分片数据以确保安全,这称为故障转移。

若主节点宕机:

  • 新的候选主节点被选举。
  • 主节点负责监控分片状态,将故障节点的分片迁移到其他节点以确保数据安全。
相关推荐
Francek Chen11 分钟前
【PySpark大数据分析概述】03 PySpark大数据分析
大数据·分布式·数据挖掘·数据分析·pyspark
_玖-幽42 分钟前
Python 数据分析01 环境搭建教程
大数据·python·jupyter
IT成长日记2 小时前
【Hadoop入门】Hadoop生态之Flume简介
大数据·hadoop·flume
IT成长日记2 小时前
【Hadoop入门】Hadoop生态之Spark简介
大数据·hadoop·spark
Lilith的AI学习日记2 小时前
LangChain高阶技巧:动态配置Runnable组件的原理剖析与实战应用
大数据·网络·人工智能·架构·langchain
Data跳动2 小时前
【Flink运行时架构】组件构成
大数据·架构·flink
小蓝波3 小时前
Docker部署jenkins
java·docker·jenkins
IT成长日记12 小时前
【Hadoop入门】Hadoop生态之MapReduce简介
大数据·hadoop·mapreduce
Apache Flink12 小时前
Dinky 和 Flink CDC 在实时整库同步的探索之路
大数据·flink