书籍学习-一本书讲透Elasticsearch:原理、进阶和工程实践(一)

本文是个人学习书籍《一本书讲透Elasticsearch:原理、进阶和工程实践》过程中所记录的一些笔记,内容来源于书籍

Elastic Stack全景

  • ELK Stack:Elasticsearch、Logstash、Kibana

  • Elastic Stack:Elasticsearch(存储、查询)、Logstash + Beats(采集、清洗)、Kibana(可视化)

  • Elasticsearch特点

    • RESTful API

    • 横向扩展节点

    • 面向文档

    • 无模式,无须定义好字段类型、长度等

    • 近实时搜索

    • 响应快

    • 易扩展

    • 多租户

    • 多语言

  • Logstash:提供免费且开放的服务器端数据处理管道(pipeline),能够从多个不同的数据源采集数据、转换数据,然后将数据发送到诸如Elasticsearch等“存储库”中

  • Kibana:集成了丰富的可视化工具、界面交互开发工具和管理工具,可以辅助技术人员进行开发、调试和运维工作,并可以自定义各种维度的数据报表

  • Beats:集合了多种单一用途的数据采集器,这些数据采集器包含轻量型日志采集器Filebeat、轻量型指标采集器Metricbeat、轻量型网络数据采集器Packetbeat等

  • Elastic Stack应用场景

    • 全文检索

    • 日志分析

    • 商业智能

Elasticsearch基础知识

  • 搜索引擎的目标

    • 全面性

    • 速度

    • 准确性

  • 搜索引擎的核心要求

    • 识别用户真正的需求

    • 匹配用户需求

    • 找到可信数据

  • 检索质量的评价指标

    • 召回率:在一次返回的搜索结果中与搜索关键词相关的文档占所有相关文档的比例

    • 精准率:本次搜索结果中相关文档所占的比例

  • 倒排索引:在一个文档集合中,每个文档都可视为一个词语的集合,倒排索引则是将词语映射到包含这个词语的文档的数据结构

  • 全文检索:全文检索的前提是待检索的数据已经索引化,当用户查询时能根据建立的倒排索引进行查找

  • Elasticsearch的核心概念

    • 集群:一组Elasticsearch节点的集合

    • 节点:一个Elasticsearch实例,更确切地说,它是一个Elasticsearch进程

    • 索引:用于存储和管理相关数据的逻辑容器

    • 分片:包含索引数据的一个子集,并且其本身具有完整的功能和独立性,可以将分片近似看作“独立索引“

    • 副本:为了保证集群的容错性和高可用性、提高查询的吞吐率,Elasticsearch提供了复制数据的特性。分片可以被复制,被复制的分片称为“主分片“,主分片的复制版本称为“副本“

    • 文档:存储在Elasticsearch索引中的JSON对象

    • 字段:Elasticsearch中最小的单个数据单元,类似于关系型数据库表中的字段

    • 映射:映射类似于关系型数据库中的Schema,可以近似地理解为“表结构”

    • 分词:构建倒排索引的重要一环

Elasticsearch集群部署

  • Elasticsearch集群堆内存设置建议:将堆大小配置为服务器可用内存的50%,上限为32GB,且预留足够的内存给操作系统以提升缓存效率

  • 节点角色(node.roles配置项)

    • 主节点:关键作用主要在全局管理上,如管理索引的创建和删除、监控集群节点、确认分片分配、存储重要的元数据(索引的元数据、集群的元数据)

      • 专用候选主节点(master)

      • 仅投票主节点:仅用于投票,不会被选为主节点(master, voting_only)

    • 数据节点:保存数据、执行数据处理操作(data)

      • 内容数据节点:存储、搜索、索引数据(data_content)

      • 热数据节点:保存最近、最常访问的热数据(data_hot)

      • 温数据节点:保存访问频次低且很少更新的时序数据(data_warm)

      • 冷数据节点:保存不经常访问且通常不更新的时序数据(data_cold)

      • 冷冻数据节点:保存很少访问且从不更新的时序数据(data_frozen)

      • 注意:data_hot、data_warm和data_cold需要和data_content一起配置,数据的实际存储需要靠data_content角色

    • ingest节点:通常执行由预处理管道组成的预处理任务(ingest)

    • 仅协调节点:负责路由分发请求、聚合结果(配置项为空)

    • 远程节点:用于跨集群检索或跨集群复制(remote_cluster_client)

    • 机器学习节点(ml, remote_cluster_client)

    • 转换节点(transform)

  • Elasticsearch集群核心配置

    • network.host,不修改时默认为开发模式,节点配置错误时只会在日志中写入警告信息,节点依然能启动;修改后会升级为生产模式,一旦配置错误,则节点无法正常启动

    • Linux前置配置

      • 修改文件描述符数量限制(调高)

      • 修改最大映射数量(调高)

    • elasticsearch.yml配置文件

    • jvm.option配置文件

Elasticsearch索引

  • 定义

    • 名称

    • settings

      • 静态设置

      • 动态设置

    • mappings

      • 可以将索引映射理解成MySQL中的表结构Schema
    • aliases

      • 一个索引可以创建多个别名

      • 一个别名也可以指向多个索引

  • 操作

    • 新增/创建索引

      • 方式一:详细定义索引设置、映射、别名

      • 方式二:只定义索引名,而settings、mappings取默认值

    • 删除索引

      • 方式一:删除索引(推荐)

      • 方式二:结合delete_by_query和match_all实现清空,还能保留索引

    • 修改索引

    • 查询索引

  • 索引别名

  • 索引模板

    • 定义

      • 普通模板(_index_template)

      • 组件模板(_component_template)

    • 映射下的动态模板(dynamic_templates)

Elasticsearch映射

  • 映射的定义

    • 元字段

      • 标识元字段

        • _index:表示文档所属的索引

        • _id:表示文档的id

      • 文档源字段

        • _source:表示代表文档正文的原始JSON对象

        • _size:表示source字段的大小(以字节为单位)

      • 索引元字段

        • _field_names:表示给定文档中包含非空值的所有字段

        • _ignored:表示由于设置ignore_malformed而在索引时被忽略的字段

      • 路由元字段

        • _routing:用于将给定文档路由到指定的分片
      • 其他元字段

        • _meta:表示应用程序特定的元数据

        • _tier:指定文档所属索引的数据层级别

    • 数据类型

      • 基本类型

        • binary:编码为Base64字符串的二进制类型

        • boolean:仅支持true和false的布尔类型

        • keyword:支持精准匹配的keyword类型、const_keyword类型和wildcard类型

        • number:数值类型,如integer、long、float、double等

        • date:日期类型,包括date和date_nanos

        • alias:别名类型,字段级别的别名

        • text:字段级别的别名

      • 复杂数据类型

        • 数组类型:Array

        • JSON对象类型:Object

        • 嵌套数据类型:Nested

        • 父子关联类型:Join

        • Flattened类型:将原来一个复杂的Object或者Nested嵌套多字段类型统一映射为扁平的单字段类型

      • 专用数据类型

        • 坐标数据类型:用于保存地理位置详细信息

        • IP类型:表示IPV4或IPV6地址

        • completion类型:是Elasticsearch中的一种专用字段类型,旨在实现高效的自动补全功能

      • 多字段类型:为相同字段生成多种数据类型

    • 映射类型

      • 动态映射:自动检测字段类型后添加新字段(boolean类型、float类型、long类型、Object类型、Array类型、date类型、字符串类型支持动态检测,除此之外的类型是不支持动态检测匹配的,会适配为text类型)

        • 弊端

          • 字段匹配不准确

          • 占据多余的存储空间

          • 映射可能错误泛滥

      • 静态映射:在数据建模前,需要明确文档中各个字段的类型

        • 忽略动态添加字段(mappings内指定dynamic为false)

        • 严格禁止动态添加字段(mappings内指定dynamic为“strict”)

    • 映射创建后还可以更新吗

      • 已经定义的字段在大多数情况下不能更新,除非通过reindex操作来更新映射,但有3种情况例外:

        • Object对象可以添加新的属性

        • 在已经存在的字段里面可以添加fields,以构成一个字段多种类型

        • ignore_above是可以更新的

  • Nested类型及应用

    • 没有特殊的字段类型说明,那么默认写入的嵌套数据映射为Object类型,其嵌套的字段部分被扁平化为一个简单的字段名称和值列表

    • Nested类型是Object数据类型的升级版本,它允许对象以彼此独立的方式进行索引

  • Join类型及应用

    • Join类型的重要特点

      • 对于每个索引,仅允许定义一个与Join类型关联的映射

      • 父文档和子文档必须在同一个分片上写入索引

      • 一个文档可以有多个子文档,但一个子文档只能有一个父文档

      • 可以为已经存在的Join类型添加新的关系

      • 当一个文档已经成为父文档后,就可以为该文档添加子文档

  • Flattened类型及应用

    • Flattened字段就是用来解决字段膨胀问题的

    • 使用Flattened类型,Elasticsearch未对字段进行分词等处理,因此它只会返回匹配字母大小写且完全一致的结果

    • Flattened类型的不足

      • Flattened不支持的查询类型

        • 无法执行涉及数字计算的查询

        • 无法支持高亮查询

        • 尽管支持诸如term聚合之类的聚合,但不支持处理诸如histograms或date_histograms之类的数值数据的聚合

  • 多表关联设计

    • Elasticsearch多表关联方案

      • Nested嵌套类型

        • 适用于一对少量、子文档偶尔更新、查询频繁的场景

        • 优点

          • 可以将父子关系的两部分数据关联起来

          • 可以基于Nested类型做任何查询

        • 缺点

          • 查询相对较慢

          • 更新子文档时需要更新整篇文档

      • Join父子文档类型

        • 适用于子文档数据量明显多于父文档的数据量的场景

        • 优点

          • 父子文档可独立更新
        • 缺点

          • 维护Join关系需要占据部分内存,查询较Nested类型更耗资源
      • 宽表冗余存储

        • 对每个文档保持一定数量的冗余数据以避免访问时进行多表关联

        • 优点

          • 速度快,本质是以空间换时间
        • 缺点

          • 索引更新或删除数据时,应用程序不得不处理宽表的冗余数据

          • 某些搜索和聚合操作的结果可能不准确

      • 业务端关联

        • 在应用接口层面处理关联关系,适用于数据量少的多表关联业务场景
  • 内部数据结构

    • 倒排索引

      • 从单词到文档的映射关系的最佳实现形式

      • 特点

        • 在索引时创建

        • 序列化到磁盘

        • 全文搜索速度非常快

        • 不适合做排序

        • 默认开启

      • 适用场景

        • 文本搜索引擎

        • 文档检索系统

        • 企业内部搜索

        • 社交媒体分析

        • 新闻和论文检索

        • 数据挖掘

    • 正排索引

      • 在Elasticsearch中,正排索引(doc_values)就是一种列式存储结构,默认情况下每个字段的doc_values都是激活的(除了text类型)

      • 特点

        • 在索引时创建

        • 序列化到磁盘

        • 适合排序、聚合操作

        • 将单个字段的所有值一起存储在单个数据列中

        • 默认情况下,除text之外的所有字段类型均启用正排索引

      • 适用场景

        • 对一个字段进行排序、聚合

        • 某些过滤场景,比如地理位置过滤

        • 某些与字段相关的脚本计算

    • fielddata

      • 当text字段被用于聚合、排序或脚本操作时,fielddata会按需构建相应的数据结构。通过从磁盘读取每个字段的完整倒排索引,反转词项与文档之间的关系,并将结果存储在JVM堆的内存中构建的

      • 特点

        • 仅适用于text字段类型

        • 在查询时创建

        • 是基于内存的数据结构

        • 没有序列化到磁盘

        • 默认情况下被禁用

      • 适用场景

        • 全文统计词频

        • 全文生成词云

        • 聚合、排序、脚本计算

    • _source字段

      • _source字段包含索引时传递的原始JSON文档主体
    • store字段

      • 默认情况下,对字段值进行索引以使其可搜索(如倒排索引),但不存储它们。字段值是_source字段的一部分,默认情况下已存储。但对于某些特殊场景,比如你只想检索单个字段或几个字段的值,而不是整个_source的值,这时store字段就派上用场了
  • null_value

    • 使用null_value参数可以用指定的值替换显式的空值,以便对其进行索引和搜索

    • text类型不支持null_value,如果需要,可以使用multi_fields,借助keyword和text组合类型达到业务需求

Elasticsearch分词

  • 分词发生的阶段

    • 写入阶段

    • 执行检索阶段

  • 分词器的组成

    • 字符过滤(character filter,0个或多个)

    • 文本切分为分词(tokenizer,1个)

    • 分词后再过滤(token filter,0个或多个)

  • 分词器的分类

    • 支持不同语言的分词器

    • 默认分词器(standard分词器):将词汇单元转换成小写,并去除停用词和标点符号

    • 其他典型的分词器(如IK分词等)

  • 分词选型注意事项

    • 若数据量非常少且不要求子串高亮,则可以考虑keyword

    • 若数据量大且要求子串高亮,则推荐使用Ngram分词,结合match或者match_phrase检索实现

    • 若数据量大,则不建议使用wildcard前缀匹配

Elasticsearch预处理

  • Elasticsearch数据预处理是指在从数据源写入Elasticsearch的中间环节对数据进行的处理操作

  • 预处理步骤

    • 定义预处理管道,通过管道实现数据预处理(_ingest/pipeline/xxx)

    • 写入数据关联预处理管道

    • 写入数据

  • enrich预处理

    • 能在不同索引间通过相同的关联字段,从一个索引向另一个索引扩充字段信息

    • 组成部分

      • enrich policy(_enrich/policy/xxx)

      • source index(源索引):用于丰富新写入文档的索引

      • enrich index(丰富索引):执行enrich policy生成的索引

        • Elasticsearch内部管理的系统级索引

        • 用途很单一,仅用于enrich processor

        • 以.enrich-*开头

        • 只读,不支持人为修改