沙师弟,师父的充电器掉了

谈谈 ES 6.8 到 7.10 的功能变迁(3)- 查询方法篇

上一篇咱们了解了 ES 7.10 相较于 ES 6.8 新增的字段类型,这一篇我们继续了解新增的查询方法。

Interval 间隔查询:

功能介绍

Interval 查询,词项间距查询,可以根据匹配词项的顺序、间距和接近度对文档进行排名。主要解决的查询场景“创建一个多搜索词匹配的查询,同时保留搜索词的顺序”,比 match phrase 更加符合需求场景,查询方法使用比 span 查询更简单。ES 后续版本想用 interval 查询逐步替代 span 查询。

注意事项

规则组合

  • 可以使用 prefix、wildcard、fuzzy 等规则
  • 通过设置 max_gaps 和 ordered 参数,可以控制词项间的最大间隙和顺序要求

性能考虑

  • 间隔查询比简单的词项匹配更消耗资源
  • 嵌套规则越多,性能开销越大
  • 建议合理使用 maxGaps 参数限制间距

使用限制

  • 只能用于 text 字段
  • 不支持跨字段查询
  • 不支持对数值类型字段使用

Distance feature 查询

功能说明

时间/地理距离特性查询,该查询用于查找更接近被查询日期和地理位置的结果。 日期和位置分别是声明为 date 和 geo_point 数据类型的字段。返回结果的字段值不需要完全等于被查询值,而是按照给定日期或给定位置的进度算分,越是接近被查询值,在相关性得分中被评为更高

字段类型要求

  • 日期字段必须是 date 类型,地理位置字段必须是 geo_point 类型
  • 不支持其他类型的距离计算

评分机制

  • 距离越近,得分越高
  • 使用 boost 参数调整权重
  • 可以与其他查询组合使用

性能考虑

  • 地理距离计算较为耗费资源,建议使用合适的索引优化地理查询,比如:考虑使用地理网格索引提升性能

Pinned 查询

功能说明

实现对某些文档的置顶功能,使用存储在_id 字段中的文档 ID 来标识升级或“固定”的文档。
此功能通常用于引导搜索者查找精选的文档,这些文档在搜索的任何 “organic” 匹配项之上被提升。当查询中有排序时,pinned 查询失效

使用限制

  • 不能与自定义排序一起使用
  • 置顶文档必须存在于索引中
  • 最多支持 100 个置顶文档

排序规则

  • 置顶文档按照 ids 数组中的顺序排序
  • organic 查询结果按照相关性得分排序
  • 置顶文档始终在 organic 结果之前

PIT 查询

功能说明

Point in time 查询是一个轻量级的视图,根据保留周期保留 PIT 查询发生时数据的状态,用于不同条件的深度分页查询。

scroll 滚动搜索及其上下文与查询内容绑定。这意味着编写一个查询,添加一个滚动参数,来自这个查询的响应数据就会保持一致。不同的查询内容则会产生不同的 scroll 上下文,资源使用就会相对紧张。有时想对同一固定数据集适时运行不同的查询,就需要 PIT 查询。

如果对于一个不断变化的索引有着很高的搜索负载,那么为每个请求创建一个新的时间点查询会使用相当多的资源。可以通过使用一个后台进程每隔几分钟创建一个时间点 id 并将其用于所有搜索请求的方式来优化资源使用

更多内容可以参照这里

注意事项

资源管理

  • PIT 会占用系统资源,需要及时释放
  • 建议设置合理的保留时间
  • 监控 open context 数量

使用场景

  • 适合需要一致性视图的场景
  • 适合需要深度分页的场景
  • 适合需要在固定数据集上执行多次查询的场景

性能优化

  • 避免过长的保留时间,合理设置批次大小
  • 建议查询的时候带 sort 参数排序

测试代码

// 1. 使用 product_test 索引,创建 PIT
POST /product_test/_pit?keep_alive=1m

GET /_search
{
  "size": 1,
  "query": {
    "match": {
      "model": "iphone"
    }
  },
  "pit": {
    "id": "i6-xAwEMcHJvZHVjdF90ZXN0FmRObXltV3ZDU1VTTnllYjNoR0ZtamcAFk1GQklTWXBaUkllb2h1cGl1VVFsdUEAAAAAAAABZk8WOFVoUHBhN3BSVVN5TWVmeTh4d3JpdwEWZE5teW1XdkNTVVNOeWViM2hHRm1qZwAA",
    "keep_alive": "1m"
  },
  "sort": [
    {"_score": "desc"},
    {"_id": "asc"}
  ]
}

DELETE /_pit
{"id":"i6-xAwEMcHJvZHVjdF90ZXN0FmRObXltV3ZDU1VTTnllYjNoR0ZtamcAFk1GQklTWXBaUkllb2h1cGl1VVFsdUEAAAAAAAABZk8WOFVoUHBhN3BSVVN5TWVmeTh4d3JpdwEWZE5teW1XdkNTVVNOeWViM2hHRm1qZwAA"}

小结

作为查询方法,Elasticsearch 新增的几个功能面对的场景更加具象且方便,大家可以根据业务的场景特性可以优化使用。其中深度分页查询是 ES 使用者几乎避免不了的场景,PIT 查询也是提供了一个更为优质的方法。

推荐阅读

关于极限科技(INFINI Labs)

INFINI Labs

极限科技,全称极限数据(北京)科技有限公司,是一家专注于实时搜索与数据分析的软件公司。旗下品牌极限实验室(INFINI Labs)致力于打造极致易用的数据探索与分析体验。

极限科技是一支年轻的团队,采用天然分布式的方式来进行远程协作,员工分布在全球各地,希望通过努力成为中国乃至全球企业大数据实时搜索分析产品的首选,为中国技术品牌输出添砖加瓦。

官网:https://infinilabs.cn

作者:金多安,极限科技(INFINI Labs)搜索运维专家,Elastic 认证专家,搜索客社区日报责任编辑。一直从事与搜索运维相关的工作,日常会去挖掘 ES / Lucene 方向的搜索技术原理,保持搜索相关技术发展的关注。
原文:https://infinilabs.cn/blog/2025/feature-evolution-from-elasticsearch-6.8-to-7.10-part-3/

继续阅读 »

上一篇咱们了解了 ES 7.10 相较于 ES 6.8 新增的字段类型,这一篇我们继续了解新增的查询方法。

Interval 间隔查询:

功能介绍

Interval 查询,词项间距查询,可以根据匹配词项的顺序、间距和接近度对文档进行排名。主要解决的查询场景“创建一个多搜索词匹配的查询,同时保留搜索词的顺序”,比 match phrase 更加符合需求场景,查询方法使用比 span 查询更简单。ES 后续版本想用 interval 查询逐步替代 span 查询。

注意事项

规则组合

  • 可以使用 prefix、wildcard、fuzzy 等规则
  • 通过设置 max_gaps 和 ordered 参数,可以控制词项间的最大间隙和顺序要求

性能考虑

  • 间隔查询比简单的词项匹配更消耗资源
  • 嵌套规则越多,性能开销越大
  • 建议合理使用 maxGaps 参数限制间距

使用限制

  • 只能用于 text 字段
  • 不支持跨字段查询
  • 不支持对数值类型字段使用

Distance feature 查询

功能说明

时间/地理距离特性查询,该查询用于查找更接近被查询日期和地理位置的结果。 日期和位置分别是声明为 date 和 geo_point 数据类型的字段。返回结果的字段值不需要完全等于被查询值,而是按照给定日期或给定位置的进度算分,越是接近被查询值,在相关性得分中被评为更高

字段类型要求

  • 日期字段必须是 date 类型,地理位置字段必须是 geo_point 类型
  • 不支持其他类型的距离计算

评分机制

  • 距离越近,得分越高
  • 使用 boost 参数调整权重
  • 可以与其他查询组合使用

性能考虑

  • 地理距离计算较为耗费资源,建议使用合适的索引优化地理查询,比如:考虑使用地理网格索引提升性能

Pinned 查询

功能说明

实现对某些文档的置顶功能,使用存储在_id 字段中的文档 ID 来标识升级或“固定”的文档。
此功能通常用于引导搜索者查找精选的文档,这些文档在搜索的任何 “organic” 匹配项之上被提升。当查询中有排序时,pinned 查询失效

使用限制

  • 不能与自定义排序一起使用
  • 置顶文档必须存在于索引中
  • 最多支持 100 个置顶文档

排序规则

  • 置顶文档按照 ids 数组中的顺序排序
  • organic 查询结果按照相关性得分排序
  • 置顶文档始终在 organic 结果之前

PIT 查询

功能说明

Point in time 查询是一个轻量级的视图,根据保留周期保留 PIT 查询发生时数据的状态,用于不同条件的深度分页查询。

scroll 滚动搜索及其上下文与查询内容绑定。这意味着编写一个查询,添加一个滚动参数,来自这个查询的响应数据就会保持一致。不同的查询内容则会产生不同的 scroll 上下文,资源使用就会相对紧张。有时想对同一固定数据集适时运行不同的查询,就需要 PIT 查询。

如果对于一个不断变化的索引有着很高的搜索负载,那么为每个请求创建一个新的时间点查询会使用相当多的资源。可以通过使用一个后台进程每隔几分钟创建一个时间点 id 并将其用于所有搜索请求的方式来优化资源使用

更多内容可以参照这里

注意事项

资源管理

  • PIT 会占用系统资源,需要及时释放
  • 建议设置合理的保留时间
  • 监控 open context 数量

使用场景

  • 适合需要一致性视图的场景
  • 适合需要深度分页的场景
  • 适合需要在固定数据集上执行多次查询的场景

性能优化

  • 避免过长的保留时间,合理设置批次大小
  • 建议查询的时候带 sort 参数排序

测试代码

// 1. 使用 product_test 索引,创建 PIT
POST /product_test/_pit?keep_alive=1m

GET /_search
{
  "size": 1,
  "query": {
    "match": {
      "model": "iphone"
    }
  },
  "pit": {
    "id": "i6-xAwEMcHJvZHVjdF90ZXN0FmRObXltV3ZDU1VTTnllYjNoR0ZtamcAFk1GQklTWXBaUkllb2h1cGl1VVFsdUEAAAAAAAABZk8WOFVoUHBhN3BSVVN5TWVmeTh4d3JpdwEWZE5teW1XdkNTVVNOeWViM2hHRm1qZwAA",
    "keep_alive": "1m"
  },
  "sort": [
    {"_score": "desc"},
    {"_id": "asc"}
  ]
}

DELETE /_pit
{"id":"i6-xAwEMcHJvZHVjdF90ZXN0FmRObXltV3ZDU1VTTnllYjNoR0ZtamcAFk1GQklTWXBaUkllb2h1cGl1VVFsdUEAAAAAAAABZk8WOFVoUHBhN3BSVVN5TWVmeTh4d3JpdwEWZE5teW1XdkNTVVNOeWViM2hHRm1qZwAA"}

小结

作为查询方法,Elasticsearch 新增的几个功能面对的场景更加具象且方便,大家可以根据业务的场景特性可以优化使用。其中深度分页查询是 ES 使用者几乎避免不了的场景,PIT 查询也是提供了一个更为优质的方法。

推荐阅读

关于极限科技(INFINI Labs)

INFINI Labs

极限科技,全称极限数据(北京)科技有限公司,是一家专注于实时搜索与数据分析的软件公司。旗下品牌极限实验室(INFINI Labs)致力于打造极致易用的数据探索与分析体验。

极限科技是一支年轻的团队,采用天然分布式的方式来进行远程协作,员工分布在全球各地,希望通过努力成为中国乃至全球企业大数据实时搜索分析产品的首选,为中国技术品牌输出添砖加瓦。

官网:https://infinilabs.cn

作者:金多安,极限科技(INFINI Labs)搜索运维专家,Elastic 认证专家,搜索客社区日报责任编辑。一直从事与搜索运维相关的工作,日常会去挖掘 ES / Lucene 方向的搜索技术原理,保持搜索相关技术发展的关注。
原文:https://infinilabs.cn/blog/2025/feature-evolution-from-elasticsearch-6.8-to-7.10-part-3/

收起阅读 »

谈谈 ES 6.8 到 7.10 的功能变迁(2)- 字段类型篇

我们继续来了解一下从 ES 6.8 到 ES 7.10 新增的功能。本篇主要介绍新增的字段类型,会简要概述一下新增字段类型的使用场景和限制,提供简单的测试代码。

Flattened 扁平化对象字段

功能说明

解决场景

该功能主要用于处理具有大量不确定键的 JSON 对象,避免字段映射爆炸问题,特别适用于不需要对对象内部字段进行单独分析和聚合的场景,以及当对象结构不固定,字段名称动态变化时。

使用注意点

  • 整个对象被视为单个字段,无法对内部单个字段进行分析或聚合
  • 只支持 keyword 类型的操作,如 term、prefix 查询等。因为它的每个解析出的字段都值为 keyword 字段
  • 默认最大字段深度为 20,可以通过 depth_limit 来设置。
  • 不支持数字范围查询,高亮显示
  • 查询时,无法使用通配符引用字段键,比如 { "term": {"labels.time*": 1541457010}}
  • split_queries_on_whitespace 为 true 时,这个字段的全文查询(match,query_string,simple_query_string)等于是用了空格分词器。

支持的查询方法

  • term 查询:精确匹配某个字段的值
  • terms/terms_set 查询:匹配多个值中的任意一个或者多个
  • prefix 查询:前缀匹配
  • exists 查询:检查字段是否存在
  • match 查询:分词后的全文检索(但因为是 keyword,所以实际上是精确匹配)
  • query_string 和 simple_query_string

Shape 字段

功能说明

该功能主要用于存储和查询任意几何图形数据,支持点、线、圆、矩形、多边形等几何形状,特别适用于地理空间分析和基于形状的搜索场景,以及相比于 geo_shape 专门用于地理空间数据(坐标系统固定为 WGS84 经纬度),shape 字段可以用于任意坐标系统的几何形状,比如虚拟世界或者保密空间。

使用要点

  • 形状数据使用 GeoJSONWell-Known Text (WKT)格式表示
  • 支持的空间关系操作包括:INTERSECTS(相交)、DISJOINT(不相交)、WITHIN(内部)和 CONTAINS(包含)
  • 由于 shape 字段的复杂输入结构和索引表示,目前无法对 shape 字段进行排序,也无法直接检索其字段值(只能通过 _source 字段获取)
  • orientation 参数用于定义多边形顶点读取的顺序:默认逆时针(counterclockwise),可选顺时针(clockwise)

Wildcard 字段

功能说明

解决的场景

用于优化通配符和正则表达式查询性能。特别适用于需要进行暴力模糊匹配的文本字段。 wildcard 字段在 keyword 字段和 ngrams 分词器之间找到了性能和存储成本的均衡

原理说明

wildcard 字段采用了一种独特的索引策略,使用这种数据类型自动加速通配符和正则表达式搜索:

  1. n-gram 索引:存储字符串中所有 3 个字符的序列。可以理解为 ngram 分词器取长度为 3 的子串.
  2. 二进制 doc value:存储完整的原始文档值

这种方式与传统的 keyword 字段(完全不分词)和 text 字段(基于分词器分词)有很大不同。在查询时,系统首先使用这些 ngrams 构建的索引进行初步筛选,快速定位可能匹配的文档。这个过程类似于数据库中的索引过滤,可以大大减少需要详细检查的文档数量。然后,系统会从二进制 doc value 中取出这些候选文档的完整字段值,进行精确的模式匹配,确保最终结果的准确性。

这种策略在性能和存储空间上取得了很好的平衡:

  • 相比 keyword 字段,在精确匹配查询时性能稍差
  • 相比 ngrams 分词,它避免了过度的 token 生成,既节省存储空间,又保持了不错的查询性能
  • 特别适合对日志数据进行类似 grep 的模式匹配查询,如通配符查询和正则表达式查询

使用注意点

  • 比 keyword 类型更适合做通配符搜索,但会占用更多磁盘空间
  • 建议仅在确实需要频繁进行通配符查询的字段上使用
  • 与 keyword 字段一样是非分词(untokenized)的,所以不支持依赖词项位置的查询(如短语查询)

更多原理说明可以参照这里

Version 字段类型

功能说明

该功能主要用于存储和比较软件版本号,提供版本号的自然排序和比较功能,支持标准的版本号格式(如 1.0.0, 2.1.3-alpha 等)。

使用说明

  • 版本号必须符合标准格式:主版本号、次版本号、修订号
  • 支持带有预发布标识符的版本号(如 alpha, beta, rc 等)
  • 可以进行版本号的大小比较和范围查询,比如可以在 1.0.0 和 2.0.0 之间查找所有版本
  • 底层存储的是 keyword 类型,虽然可以正则匹配或者模糊查询,但是在大数据量下注意性能问题。

Histogram 直方图字段

功能说明

解决的场景

Histogram 字段专门用于存储预先计算好的直方图数据,这种数据结构在需要频繁进行统计分析的场景下特别有用。通过预先聚合数据并以直方图形式存储,可以显著减少查询时的实时计算开销,提高查询性能。对大规模数据集的统计分析很有利,比如系统监控指标、用户行为分析等需要快速获取数据分布情况的场景。

直方图的数据格式

直方图字段需要包含两个必需的参数来表示直方图数据:

  • values:数值数组,表示每个聚合分桶的取值点,即区间的起点。数组中的值必须是严格递增双精度浮点数
  • counts:整数数组,表示落在当前区间内的元素数量。数组中的值必须是非负整数。具体来说,对于位置 i,counts[i] 表示数值大于等于 values[i] 且小于 values[i+1] 的元素个数(最后一个区间则包含等于 values[last] 的元素)

这两个数组必须具有相同的长度。 例如,一个表示年龄分布的直方图数据可能如下:

{
  "age_histogram": {
    "values": [20.0, 30.0, 40.0, 50.0], // 年龄区间的起点:[20-30)、[30-40)、[40-50)、[50 及以上]
    "counts": [100, 150, 75, 25] // 表示:20-29 岁有 100 人,30-39 岁有 150 人,40-49 岁有 75 人,50 岁及以上有 25 人
  }
}

存储说明

直方图字段主要用于聚合分析。为了优化聚合操作的性能,数据以二进制 doc values 形式存储,而不是创建索引。每个直方图字段的存储大小最多为 13 * numValues 字节,其中 numValues 是数组的长度。

使用注意点

  • value 数组必须按升序排列
  • count 数组的长度必须与 value 数组相同
  • 由于数据被索引,直方图字段仅支持以下操作:
    • 聚合操作:min(最小值)、max(最大值)、sum(求和)、value_count(计数)、avg(平均值)、percentiles(百分位数)、percentile_ranks(百分位等级)、boxplot(箱线图)、histogram(直方图)
    • 查询操作:仅支持 exists(存在性)查询

Search-as-you-type 字段

功能说明

解决的场景

该功能主要用于实现自动补全的即时搜索体验,比如可以在当用户输入搜索关键词的时候,还没输完就可以提示用户数据库里最相关的内容。 它是通过支持前缀匹配和部分词语匹配的方式,使用户在输入过程中就能获得搜索结果。

字段结构说明

search_as_you_type 字段会自动创建以下子字段:

  • {field_name}: 基础字段,用于完整词语匹配,使用字段设置的分词器。
  • {field_name}._2gram: 用大小为 2 的 shingle token filter 分词器对 ny_field 进行分词
  • {field_name}._3gram: 用大小为 3 的 shingle token filter 分词器对 ny_field 进行分词
  • {field_name}._index_prefix: 用 edge ngram token filter 包装 my_field._3gram 的分词器

使用注意

  • 可以通过设置 max_shingle_size 参数(默认为 3)来控制生成的子字段数量。max_shingle_size 参数越大,子字段越多,默认 3 个字段能覆盖大部分的场景。
  • search-as-you-type 字段索引空间占用较大,因为需要存储多个分词器的结果。

前缀查询(prefix)优化机制

search_as_you_type 字段在处理前缀查询时有特殊的优化。当对根字段或其子字段进行前缀查询时,查询会被重写为针对 ._index_prefix 子字段的 term 查询,这比传统的文本字段前缀查询更高效 ._index_prefix 子字段的分析器会对分词结果进行特殊处理:

  • 不仅索引常规的 n-gram 分词结果
  • 还会索引字段值词条的前缀,即使这些词条不会出现在 n-gram 子字段中

例如,对于文本 "quick brown fox",在 max_shingle_size 为 3 的情况下:不仅会索引会索引"quick" "brown" "fox",还会索引这些此项的前缀,这确保了字段中所有词条都能支持自动完成功能,即使这些词条组合并不存在于 ._3gram 子字段中

小结

这里我们只是简要的介绍了一下新增字段类型的设计背景和原理,并没有深入展开挖掘新增字段的性能场景或者奇思妙用,比如 wildcard 与 ngram 颗粒度性能对比,直方图数据和 pipeline 进行日志分析的组合等等。大家可以根据实际的需求场景进行深度挖掘。

推荐阅读

关于极限科技(INFINI Labs)

INFINI Labs

极限科技,全称极限数据(北京)科技有限公司,是一家专注于实时搜索与数据分析的软件公司。旗下品牌极限实验室(INFINI Labs)致力于打造极致易用的数据探索与分析体验。

极限科技是一支年轻的团队,采用天然分布式的方式来进行远程协作,员工分布在全球各地,希望通过努力成为中国乃至全球企业大数据实时搜索分析产品的首选,为中国技术品牌输出添砖加瓦。

官网:https://infinilabs.cn

作者:金多安,极限科技(INFINI Labs)搜索运维专家,Elastic 认证专家,搜索客社区日报责任编辑。一直从事与搜索运维相关的工作,日常会去挖掘 ES / Lucene 方向的搜索技术原理,保持搜索相关技术发展的关注。

继续阅读 »

我们继续来了解一下从 ES 6.8 到 ES 7.10 新增的功能。本篇主要介绍新增的字段类型,会简要概述一下新增字段类型的使用场景和限制,提供简单的测试代码。

Flattened 扁平化对象字段

功能说明

解决场景

该功能主要用于处理具有大量不确定键的 JSON 对象,避免字段映射爆炸问题,特别适用于不需要对对象内部字段进行单独分析和聚合的场景,以及当对象结构不固定,字段名称动态变化时。

使用注意点

  • 整个对象被视为单个字段,无法对内部单个字段进行分析或聚合
  • 只支持 keyword 类型的操作,如 term、prefix 查询等。因为它的每个解析出的字段都值为 keyword 字段
  • 默认最大字段深度为 20,可以通过 depth_limit 来设置。
  • 不支持数字范围查询,高亮显示
  • 查询时,无法使用通配符引用字段键,比如 { "term": {"labels.time*": 1541457010}}
  • split_queries_on_whitespace 为 true 时,这个字段的全文查询(match,query_string,simple_query_string)等于是用了空格分词器。

支持的查询方法

  • term 查询:精确匹配某个字段的值
  • terms/terms_set 查询:匹配多个值中的任意一个或者多个
  • prefix 查询:前缀匹配
  • exists 查询:检查字段是否存在
  • match 查询:分词后的全文检索(但因为是 keyword,所以实际上是精确匹配)
  • query_string 和 simple_query_string

Shape 字段

功能说明

该功能主要用于存储和查询任意几何图形数据,支持点、线、圆、矩形、多边形等几何形状,特别适用于地理空间分析和基于形状的搜索场景,以及相比于 geo_shape 专门用于地理空间数据(坐标系统固定为 WGS84 经纬度),shape 字段可以用于任意坐标系统的几何形状,比如虚拟世界或者保密空间。

使用要点

  • 形状数据使用 GeoJSONWell-Known Text (WKT)格式表示
  • 支持的空间关系操作包括:INTERSECTS(相交)、DISJOINT(不相交)、WITHIN(内部)和 CONTAINS(包含)
  • 由于 shape 字段的复杂输入结构和索引表示,目前无法对 shape 字段进行排序,也无法直接检索其字段值(只能通过 _source 字段获取)
  • orientation 参数用于定义多边形顶点读取的顺序:默认逆时针(counterclockwise),可选顺时针(clockwise)

Wildcard 字段

功能说明

解决的场景

用于优化通配符和正则表达式查询性能。特别适用于需要进行暴力模糊匹配的文本字段。 wildcard 字段在 keyword 字段和 ngrams 分词器之间找到了性能和存储成本的均衡

原理说明

wildcard 字段采用了一种独特的索引策略,使用这种数据类型自动加速通配符和正则表达式搜索:

  1. n-gram 索引:存储字符串中所有 3 个字符的序列。可以理解为 ngram 分词器取长度为 3 的子串.
  2. 二进制 doc value:存储完整的原始文档值

这种方式与传统的 keyword 字段(完全不分词)和 text 字段(基于分词器分词)有很大不同。在查询时,系统首先使用这些 ngrams 构建的索引进行初步筛选,快速定位可能匹配的文档。这个过程类似于数据库中的索引过滤,可以大大减少需要详细检查的文档数量。然后,系统会从二进制 doc value 中取出这些候选文档的完整字段值,进行精确的模式匹配,确保最终结果的准确性。

这种策略在性能和存储空间上取得了很好的平衡:

  • 相比 keyword 字段,在精确匹配查询时性能稍差
  • 相比 ngrams 分词,它避免了过度的 token 生成,既节省存储空间,又保持了不错的查询性能
  • 特别适合对日志数据进行类似 grep 的模式匹配查询,如通配符查询和正则表达式查询

使用注意点

  • 比 keyword 类型更适合做通配符搜索,但会占用更多磁盘空间
  • 建议仅在确实需要频繁进行通配符查询的字段上使用
  • 与 keyword 字段一样是非分词(untokenized)的,所以不支持依赖词项位置的查询(如短语查询)

更多原理说明可以参照这里

Version 字段类型

功能说明

该功能主要用于存储和比较软件版本号,提供版本号的自然排序和比较功能,支持标准的版本号格式(如 1.0.0, 2.1.3-alpha 等)。

使用说明

  • 版本号必须符合标准格式:主版本号、次版本号、修订号
  • 支持带有预发布标识符的版本号(如 alpha, beta, rc 等)
  • 可以进行版本号的大小比较和范围查询,比如可以在 1.0.0 和 2.0.0 之间查找所有版本
  • 底层存储的是 keyword 类型,虽然可以正则匹配或者模糊查询,但是在大数据量下注意性能问题。

Histogram 直方图字段

功能说明

解决的场景

Histogram 字段专门用于存储预先计算好的直方图数据,这种数据结构在需要频繁进行统计分析的场景下特别有用。通过预先聚合数据并以直方图形式存储,可以显著减少查询时的实时计算开销,提高查询性能。对大规模数据集的统计分析很有利,比如系统监控指标、用户行为分析等需要快速获取数据分布情况的场景。

直方图的数据格式

直方图字段需要包含两个必需的参数来表示直方图数据:

  • values:数值数组,表示每个聚合分桶的取值点,即区间的起点。数组中的值必须是严格递增双精度浮点数
  • counts:整数数组,表示落在当前区间内的元素数量。数组中的值必须是非负整数。具体来说,对于位置 i,counts[i] 表示数值大于等于 values[i] 且小于 values[i+1] 的元素个数(最后一个区间则包含等于 values[last] 的元素)

这两个数组必须具有相同的长度。 例如,一个表示年龄分布的直方图数据可能如下:

{
  "age_histogram": {
    "values": [20.0, 30.0, 40.0, 50.0], // 年龄区间的起点:[20-30)、[30-40)、[40-50)、[50 及以上]
    "counts": [100, 150, 75, 25] // 表示:20-29 岁有 100 人,30-39 岁有 150 人,40-49 岁有 75 人,50 岁及以上有 25 人
  }
}

存储说明

直方图字段主要用于聚合分析。为了优化聚合操作的性能,数据以二进制 doc values 形式存储,而不是创建索引。每个直方图字段的存储大小最多为 13 * numValues 字节,其中 numValues 是数组的长度。

使用注意点

  • value 数组必须按升序排列
  • count 数组的长度必须与 value 数组相同
  • 由于数据被索引,直方图字段仅支持以下操作:
    • 聚合操作:min(最小值)、max(最大值)、sum(求和)、value_count(计数)、avg(平均值)、percentiles(百分位数)、percentile_ranks(百分位等级)、boxplot(箱线图)、histogram(直方图)
    • 查询操作:仅支持 exists(存在性)查询

Search-as-you-type 字段

功能说明

解决的场景

该功能主要用于实现自动补全的即时搜索体验,比如可以在当用户输入搜索关键词的时候,还没输完就可以提示用户数据库里最相关的内容。 它是通过支持前缀匹配和部分词语匹配的方式,使用户在输入过程中就能获得搜索结果。

字段结构说明

search_as_you_type 字段会自动创建以下子字段:

  • {field_name}: 基础字段,用于完整词语匹配,使用字段设置的分词器。
  • {field_name}._2gram: 用大小为 2 的 shingle token filter 分词器对 ny_field 进行分词
  • {field_name}._3gram: 用大小为 3 的 shingle token filter 分词器对 ny_field 进行分词
  • {field_name}._index_prefix: 用 edge ngram token filter 包装 my_field._3gram 的分词器

使用注意

  • 可以通过设置 max_shingle_size 参数(默认为 3)来控制生成的子字段数量。max_shingle_size 参数越大,子字段越多,默认 3 个字段能覆盖大部分的场景。
  • search-as-you-type 字段索引空间占用较大,因为需要存储多个分词器的结果。

前缀查询(prefix)优化机制

search_as_you_type 字段在处理前缀查询时有特殊的优化。当对根字段或其子字段进行前缀查询时,查询会被重写为针对 ._index_prefix 子字段的 term 查询,这比传统的文本字段前缀查询更高效 ._index_prefix 子字段的分析器会对分词结果进行特殊处理:

  • 不仅索引常规的 n-gram 分词结果
  • 还会索引字段值词条的前缀,即使这些词条不会出现在 n-gram 子字段中

例如,对于文本 "quick brown fox",在 max_shingle_size 为 3 的情况下:不仅会索引会索引"quick" "brown" "fox",还会索引这些此项的前缀,这确保了字段中所有词条都能支持自动完成功能,即使这些词条组合并不存在于 ._3gram 子字段中

小结

这里我们只是简要的介绍了一下新增字段类型的设计背景和原理,并没有深入展开挖掘新增字段的性能场景或者奇思妙用,比如 wildcard 与 ngram 颗粒度性能对比,直方图数据和 pipeline 进行日志分析的组合等等。大家可以根据实际的需求场景进行深度挖掘。

推荐阅读

关于极限科技(INFINI Labs)

INFINI Labs

极限科技,全称极限数据(北京)科技有限公司,是一家专注于实时搜索与数据分析的软件公司。旗下品牌极限实验室(INFINI Labs)致力于打造极致易用的数据探索与分析体验。

极限科技是一支年轻的团队,采用天然分布式的方式来进行远程协作,员工分布在全球各地,希望通过努力成为中国乃至全球企业大数据实时搜索分析产品的首选,为中国技术品牌输出添砖加瓦。

官网:https://infinilabs.cn

作者:金多安,极限科技(INFINI Labs)搜索运维专家,Elastic 认证专家,搜索客社区日报责任编辑。一直从事与搜索运维相关的工作,日常会去挖掘 ES / Lucene 方向的搜索技术原理,保持搜索相关技术发展的关注。

收起阅读 »

谈谈 ES 6.8 到 7.10 的功能变迁(1)- 性能优化篇

前言

ES 7.10 可能是现在比较常见的 ES 版本。但是对于一些相迭代比较慢的早期业务系统来说,ES 6.8 是一个名副其实的“钉子户”。

借着工作内升级调研的任务东风,我整理从 ES 6.8 到 ES 7.10 ELastic 重点列出的新增功能和优化内容。将分为 6 个篇幅给大家详细阐述。

本系列文章主要针对 Elasticsearch 传统的使用功能和基础的模块,像是集群任务的管理、搜索、聚合还有字段类型这样的功能。对于付费功能或者全新的模块,比如:CCR、机器学习和数据流,这里不去深入探讨。

内容的主要来源于 Elastic 各个版本的发布信息,这里主要比对 ES 6.8 版本到 7.10 版本的差异,并不一一枚举各个新的功能点出现的时间版本。

下面是第一篇:关于 ES 性能的优化

ES 7.10 的性能优化

集群协调算法升级

基于 Elastic 博客提供的资料,Elasticsearch 7.0 的核心改进在于集群协调层的彻底重构,取代了旧版 Zen Discovery 的局限性,引入更健壮、自动化的分布式共识机制。从理论上来说这次优化有着不少的进步,可以显著提升了高可用性与运维效率

主要的优化点有下面三点:

  1. 消除分裂脑(Split Brain)风险:通过自动化计算,确保集群状态更新的安全性。旧版 minimum_master_nodes 的手动配置被移除,避免人为误操作。

  2. 提升集群稳定性与恢复速度:节点故障时,集群更快达成一致,减少服务中断窗口。

  3. 简化运维复杂度:可以动态扩缩容无需手动调整配置,系统自动管理选举配置。同时提供更清晰的日志和错误提示,加速故障诊断。
旧版配置 ES 7.0 配置 作用
discovery.zen.ping.unicast.hosts discovery.seed_hosts 定义初始发现的种子节点列表(IP 或主机名)
discovery.zen.minimum_master_nodes 已移除 由系统自动管理法定人数

而在优化的原则里,Elastic 更强调安全第一。比如,在半数以上主节点永久丢失的风险场景下,ES 7.0 之前的集群会静默等待恢复,允许通过启动新空节点强制恢复,这样可能会导致数据不一致或丢失。在 Elasticsearch 7.0 以及更高版本中,这种不安全活动受到了更多限制。集群宁愿保持不可用状态,也不会冒这种风险(除非使用 elasticsearch-node 恢复工具)。

这次优化显著降低了人为错误的风险:移除脆弱的手动配置,减少运维使用的理解成本。同时提升关键业务连续性:快速故障恢复与明确的容错机制,能适合更多场景需求。

当然也并不是尽善尽美的,也会存在大集群下投票节点过多导致竞争激烈而无法选主的问题,这种情况下,建议部署独立的主节点,并且可以考虑适当增大 cluster.election.duration 的配置。

Top K 对检索的加速

这里的 Top K 主要是指在普通检索时展示前列的数据 Top K。也就是说 Elasticsearch 7.0 对检索数据的查询性能做了明显的改善。那是做了所有查询场景的提升么?

ELastic 做了这么一个场景假设:如果用户通常只关注搜索结果的第一页,且并不关心具体匹配的文档总数,对于超出一定数量的数据搜索引擎可以展示“超过 10,000 条结果”并提供分页浏览来优化搜索效率。但是在实际过程中用户常在查询中使用高频词(如“the”或“a”),这迫使 Elasticsearch 为大量文档计算评分,明显占用了查询资源的使用,即使这些常见词对相关性排序贡献甚微。

而现在,Elasticsearch 现在可以跳过那些在早期阶段就被判定为不会进入结果集顶部的低排名记录的评分计算,从而显著提升查询速度。这里主要涉及了 block-max WAND 算法的实现。这是一个复杂且漫长的优化过程,有兴趣的同学可以阅读一下这段Magic WAND: Faster Retrieval of Top Hits in Elasticsearch

从 Elastic 的测试结果来看,新算法的优化让 term 查询加速了 3-7 倍。当然从场景背景可以看出,这个优化主要在大数据量下有明显效果(小数据量也不会有太多的日常高频词)。

默认开启 soft-delete 减少 translog

从 Elasticsearch 7.4 开始,副本的数据恢复,不再完全依赖 translog 了,而是通过索引的 soft-delete 特性(Elasticsearch 7.0 起所有新索引默认启用软删除 soft-deletes)。这样就可以缩小 translog 的使用场景,从而 translog 的保留大小也可以减少了。

那原来使用 translog 是什么样的呢?

translog 是 ES 用于保证数据安全性的重要工具。同时副分片进行恢复时,它也起着重要作用,只要副分片待获取的差异数据是在 translog 所保留的数据范围内,就可以只从 trasnlog 复制差异的部分数据,而不用拖取整个分片。在之前的版本中,Elasticsearch 默认会保留 512M 或 12 小时的 translog 用于副本恢复。

那现在使用的 soft-delete 是什么呢?

soft-deletes 是 Lucene 中实现的特性。这个软删除有时候会和 lucene 本身的标记删除概念发生混淆。为了方便理解,我们在这里归纳一下,lucene 实现删除的方式是一种标记删除的方式,而这种标记删除可以分为硬删除和软删除。软删除和硬删除有一个明显的区分点是:硬删除,被删除的文档对应的文档号用索引文件 .liv 来描述。软删除 soft-delete,被标记为删除的文档不使用索引文件.liv 来描述,而是通过索引文件 .dvd .dvm 来描述

这里再扩展一下,.liv 文件主要实现 fixedbitset 数据结构。而 .dvd .dvm 则组合实现了 docvalue 这种正排数据结构。

正排索引的数据结构助力了 translog 的‘减负’,副本可以相对简便的通过软删除中的数据标记来实现数据恢复的处理。

相比较简洁高效的位图索引,docvalue 虽然实现了更多的功能,满足更多的场景,也会带来更多的问题。最明显的就是对于 update 操作,会导致 refresh 变得慢,有些压力场景下 refresh 会达到 10s 以上。

数值/日期排序查询加速

Elasticsearch 7.6 版本提升了按日期或数值(即任何存储为有符号 64 位整数(long 类型)的字段)进行排序的查询性能。

这背后的优化原理和之前 top K 使用的 Block-Max WAND 算法有点相似,都是利用算法跳过非竞争性文档来实现加速。

实际效果可能因环境而异,受多种参数影响。在 Elastic 进行的测试场景下,可以达到 35 倍的速度优化。

FST 内存使用迁移到堆外

Elastic 7.3 版本实现了这个优化,是藏在 release note 里的彩蛋。

Also mmap terms index (.tip) files for hybridfs #43150 (issue: #42838)

看似不经意的一行,但是带来效果却不小。FST 从堆内转移到堆外后,JVM 的空间可以空余出很客观的一部分

一直以来,ES 堆中常驻内存中占据比重最大是 FST,即 tip(terms index) 文件占据的空间,1TB 索引大约占用 2GB 或者更多的内存,因此为了节点稳定运行,业界通常认为一个节点 open 的索引不超过 5TB。现在,从 ES 7.3 版本开始,将 tip 文件修改为通过 mmap 的方式加载,这使 FST 占据的内存从堆内转移到了堆外由操作系统的 pagecache 管理。

存储字段压缩优化

Elasticsearch 7.10 基于 Apache Lucene 8.7 引入了对存储字段(stored fields)的更高压缩率优化。不管是对于基于 DEFLATE 的 index.codec: best_compression 还是基于 LZ4 的index.codec: default都有不错的表现,在 Elastic 的测试场景下,最大可达到 10%的存储空间减少。

对于数据压缩 lucene 这次主要做了两个优化。

  1. Elastic 研究发现在存储数据的时候,底层的 block 越大,压缩效果越好,因为中间被压缩的重复数据可能越多。但是大块的 block 也可能因为解码重复数据降低查询速度。

  2. block 间通过共享字典来维持检索效率和数据压缩之间的平衡。

    2.1. 首先为压缩算法提供一个数据字典,它也可以用于字符串重复数据删除。如果在要压缩的数据流和字典之间有许多重复的字符串,那么最终可以得到更好的压缩比。在解压缩时也通过字典来快速补足。

    2.2. 同时,ES 使用更大的数据块,这些数据块本身被分成一个字典和 10 个子块,这些子块使用这个字典进行压缩。

而对于实际业务场景中,日志和监控数据的重复率往往会很好,因此在这两个场景中的压缩效果也是最明显的。

小结

当然,除了这几项外,ES 在各个版本中也做了不少优化,比如:调整 search.max_buckets 增加到 65534;Date histogram 聚合性能优化等等。有兴趣的同学可以参照各个版本的 release highlight

参考资料:

  1. Save space and money with improved storage efficiency in Elasticsearch 7.10
  2. Elasticsearch 7.3 的 offheap 原理
  3. Elasticsearch 7.4 的 soft-deletes 是个什么鬼

推荐阅读

作者:金多安,极限科技(INFINI Labs)搜索运维专家,Elastic 认证专家,搜索客社区日报责任编辑。一直从事与搜索运维相关的工作,日常会去挖掘 ES / Lucene 方向的搜索技术原理,保持搜索相关技术发展的关注。
原文:https://infinilabs.cn/blog/2025/feature-evolution-from-elasticsearch-6.8-to-7.10-part-1/

继续阅读 »

前言

ES 7.10 可能是现在比较常见的 ES 版本。但是对于一些相迭代比较慢的早期业务系统来说,ES 6.8 是一个名副其实的“钉子户”。

借着工作内升级调研的任务东风,我整理从 ES 6.8 到 ES 7.10 ELastic 重点列出的新增功能和优化内容。将分为 6 个篇幅给大家详细阐述。

本系列文章主要针对 Elasticsearch 传统的使用功能和基础的模块,像是集群任务的管理、搜索、聚合还有字段类型这样的功能。对于付费功能或者全新的模块,比如:CCR、机器学习和数据流,这里不去深入探讨。

内容的主要来源于 Elastic 各个版本的发布信息,这里主要比对 ES 6.8 版本到 7.10 版本的差异,并不一一枚举各个新的功能点出现的时间版本。

下面是第一篇:关于 ES 性能的优化

ES 7.10 的性能优化

集群协调算法升级

基于 Elastic 博客提供的资料,Elasticsearch 7.0 的核心改进在于集群协调层的彻底重构,取代了旧版 Zen Discovery 的局限性,引入更健壮、自动化的分布式共识机制。从理论上来说这次优化有着不少的进步,可以显著提升了高可用性与运维效率

主要的优化点有下面三点:

  1. 消除分裂脑(Split Brain)风险:通过自动化计算,确保集群状态更新的安全性。旧版 minimum_master_nodes 的手动配置被移除,避免人为误操作。

  2. 提升集群稳定性与恢复速度:节点故障时,集群更快达成一致,减少服务中断窗口。

  3. 简化运维复杂度:可以动态扩缩容无需手动调整配置,系统自动管理选举配置。同时提供更清晰的日志和错误提示,加速故障诊断。
旧版配置 ES 7.0 配置 作用
discovery.zen.ping.unicast.hosts discovery.seed_hosts 定义初始发现的种子节点列表(IP 或主机名)
discovery.zen.minimum_master_nodes 已移除 由系统自动管理法定人数

而在优化的原则里,Elastic 更强调安全第一。比如,在半数以上主节点永久丢失的风险场景下,ES 7.0 之前的集群会静默等待恢复,允许通过启动新空节点强制恢复,这样可能会导致数据不一致或丢失。在 Elasticsearch 7.0 以及更高版本中,这种不安全活动受到了更多限制。集群宁愿保持不可用状态,也不会冒这种风险(除非使用 elasticsearch-node 恢复工具)。

这次优化显著降低了人为错误的风险:移除脆弱的手动配置,减少运维使用的理解成本。同时提升关键业务连续性:快速故障恢复与明确的容错机制,能适合更多场景需求。

当然也并不是尽善尽美的,也会存在大集群下投票节点过多导致竞争激烈而无法选主的问题,这种情况下,建议部署独立的主节点,并且可以考虑适当增大 cluster.election.duration 的配置。

Top K 对检索的加速

这里的 Top K 主要是指在普通检索时展示前列的数据 Top K。也就是说 Elasticsearch 7.0 对检索数据的查询性能做了明显的改善。那是做了所有查询场景的提升么?

ELastic 做了这么一个场景假设:如果用户通常只关注搜索结果的第一页,且并不关心具体匹配的文档总数,对于超出一定数量的数据搜索引擎可以展示“超过 10,000 条结果”并提供分页浏览来优化搜索效率。但是在实际过程中用户常在查询中使用高频词(如“the”或“a”),这迫使 Elasticsearch 为大量文档计算评分,明显占用了查询资源的使用,即使这些常见词对相关性排序贡献甚微。

而现在,Elasticsearch 现在可以跳过那些在早期阶段就被判定为不会进入结果集顶部的低排名记录的评分计算,从而显著提升查询速度。这里主要涉及了 block-max WAND 算法的实现。这是一个复杂且漫长的优化过程,有兴趣的同学可以阅读一下这段Magic WAND: Faster Retrieval of Top Hits in Elasticsearch

从 Elastic 的测试结果来看,新算法的优化让 term 查询加速了 3-7 倍。当然从场景背景可以看出,这个优化主要在大数据量下有明显效果(小数据量也不会有太多的日常高频词)。

默认开启 soft-delete 减少 translog

从 Elasticsearch 7.4 开始,副本的数据恢复,不再完全依赖 translog 了,而是通过索引的 soft-delete 特性(Elasticsearch 7.0 起所有新索引默认启用软删除 soft-deletes)。这样就可以缩小 translog 的使用场景,从而 translog 的保留大小也可以减少了。

那原来使用 translog 是什么样的呢?

translog 是 ES 用于保证数据安全性的重要工具。同时副分片进行恢复时,它也起着重要作用,只要副分片待获取的差异数据是在 translog 所保留的数据范围内,就可以只从 trasnlog 复制差异的部分数据,而不用拖取整个分片。在之前的版本中,Elasticsearch 默认会保留 512M 或 12 小时的 translog 用于副本恢复。

那现在使用的 soft-delete 是什么呢?

soft-deletes 是 Lucene 中实现的特性。这个软删除有时候会和 lucene 本身的标记删除概念发生混淆。为了方便理解,我们在这里归纳一下,lucene 实现删除的方式是一种标记删除的方式,而这种标记删除可以分为硬删除和软删除。软删除和硬删除有一个明显的区分点是:硬删除,被删除的文档对应的文档号用索引文件 .liv 来描述。软删除 soft-delete,被标记为删除的文档不使用索引文件.liv 来描述,而是通过索引文件 .dvd .dvm 来描述

这里再扩展一下,.liv 文件主要实现 fixedbitset 数据结构。而 .dvd .dvm 则组合实现了 docvalue 这种正排数据结构。

正排索引的数据结构助力了 translog 的‘减负’,副本可以相对简便的通过软删除中的数据标记来实现数据恢复的处理。

相比较简洁高效的位图索引,docvalue 虽然实现了更多的功能,满足更多的场景,也会带来更多的问题。最明显的就是对于 update 操作,会导致 refresh 变得慢,有些压力场景下 refresh 会达到 10s 以上。

数值/日期排序查询加速

Elasticsearch 7.6 版本提升了按日期或数值(即任何存储为有符号 64 位整数(long 类型)的字段)进行排序的查询性能。

这背后的优化原理和之前 top K 使用的 Block-Max WAND 算法有点相似,都是利用算法跳过非竞争性文档来实现加速。

实际效果可能因环境而异,受多种参数影响。在 Elastic 进行的测试场景下,可以达到 35 倍的速度优化。

FST 内存使用迁移到堆外

Elastic 7.3 版本实现了这个优化,是藏在 release note 里的彩蛋。

Also mmap terms index (.tip) files for hybridfs #43150 (issue: #42838)

看似不经意的一行,但是带来效果却不小。FST 从堆内转移到堆外后,JVM 的空间可以空余出很客观的一部分

一直以来,ES 堆中常驻内存中占据比重最大是 FST,即 tip(terms index) 文件占据的空间,1TB 索引大约占用 2GB 或者更多的内存,因此为了节点稳定运行,业界通常认为一个节点 open 的索引不超过 5TB。现在,从 ES 7.3 版本开始,将 tip 文件修改为通过 mmap 的方式加载,这使 FST 占据的内存从堆内转移到了堆外由操作系统的 pagecache 管理。

存储字段压缩优化

Elasticsearch 7.10 基于 Apache Lucene 8.7 引入了对存储字段(stored fields)的更高压缩率优化。不管是对于基于 DEFLATE 的 index.codec: best_compression 还是基于 LZ4 的index.codec: default都有不错的表现,在 Elastic 的测试场景下,最大可达到 10%的存储空间减少。

对于数据压缩 lucene 这次主要做了两个优化。

  1. Elastic 研究发现在存储数据的时候,底层的 block 越大,压缩效果越好,因为中间被压缩的重复数据可能越多。但是大块的 block 也可能因为解码重复数据降低查询速度。

  2. block 间通过共享字典来维持检索效率和数据压缩之间的平衡。

    2.1. 首先为压缩算法提供一个数据字典,它也可以用于字符串重复数据删除。如果在要压缩的数据流和字典之间有许多重复的字符串,那么最终可以得到更好的压缩比。在解压缩时也通过字典来快速补足。

    2.2. 同时,ES 使用更大的数据块,这些数据块本身被分成一个字典和 10 个子块,这些子块使用这个字典进行压缩。

而对于实际业务场景中,日志和监控数据的重复率往往会很好,因此在这两个场景中的压缩效果也是最明显的。

小结

当然,除了这几项外,ES 在各个版本中也做了不少优化,比如:调整 search.max_buckets 增加到 65534;Date histogram 聚合性能优化等等。有兴趣的同学可以参照各个版本的 release highlight

参考资料:

  1. Save space and money with improved storage efficiency in Elasticsearch 7.10
  2. Elasticsearch 7.3 的 offheap 原理
  3. Elasticsearch 7.4 的 soft-deletes 是个什么鬼

推荐阅读

作者:金多安,极限科技(INFINI Labs)搜索运维专家,Elastic 认证专家,搜索客社区日报责任编辑。一直从事与搜索运维相关的工作,日常会去挖掘 ES / Lucene 方向的搜索技术原理,保持搜索相关技术发展的关注。
原文:https://infinilabs.cn/blog/2025/feature-evolution-from-elasticsearch-6.8-to-7.10-part-1/

收起阅读 »

代理 Elasticsearch 服务:INFINI Gateway VS Nginx

INFINI Gateway 简介

INFINI Gateway 是一款面向 Elasticsearch 的高性能应用网关,专为提升 Elasticsearch 集群的性能、安全性和可管理性而设计。它作为 Elasticsearch 的前置网关,能够处理所有客户端请求,并将其转发到后端的 Elasticsearch 集群,同时提供丰富的功能来优化请求处理和管理。此外还支持代理 Opensearch、Easysearch 服务。

Nginx 简介

Nginx 是一个高性能的 HTTP 和反向代理服务器,以其高并发处理能力、低内存消耗和稳定性著称,广泛应用于 Web 服务器、负载均衡和反向代理等场景。在 Elasticsearch 的使用场景里,也有小伙伴使用 Nginx 来代理 Elasticsearch 的服务,利用 Nginx 的负载均衡能力,将请求转发到多个 Elasticsearch 节点。

这两个软件都能代理 Elasticsearch 服务,但是他们有什么区别?我们来一起分析分析。

负载均衡

Elasticsearch 是分布式系统,提倡使用 round-robin 方式将请求发送到多个节点。不管是 Nginx 还是 INFINI Gateway 都默认使用 round-boin 方式转发请求,也都支持 weighted round-robin(加权轮询)方式进行请求转发,这点两者相当。

节点自动更新

Elasticsearch 集群可能会遇到添加、删除节点的情况,代理程序能否感知 Elasticsearch 节点的变化将变得非常关键。

在 Nginx 中,所有转发节点的 IP 地址都必须写入到配置文件中。如果 Elasticsearch 集群加入了新的节点进行请求处理,则需要 Nginx 编辑配置文件把新节点的 IP 地址加入其中,然后重启或重载 Nginx 服务,才能将请求分发到新的节点。反之如果有节点下线,也要编辑 Nginx 配置文件并重载服务。

INFINI Gateway 是面向 Elasticsearch 设计的应用网关,具有后端节点发现和更新的功能,能够感知 Elasticsearch 集群节点加入、离开的情况。开启节点发现和更新功能后,Gateway 会定期自动更新节点列表,将请求均匀转发到列表中的节点。可参考之前的博客开启节点自动更新。

⚠️ 注意:INFINI Gateway 默认后端节点发现和更新的功能为关闭状态。

定向转发请求

使用 Elasticsearch 集群的场景多种多样,如果想对转发的节点做进一步控制,可能需要根据不同条件进行节点筛选:

  • IP 地址
  • 节点角色
  • 节点标签

Nginx

Nginx 支持根据 IP 地址进行转发的,将需要转发的节点 IP 地址写入配置文件即可。

 upstream es-cluster {
   server 192.168.56.102:9200;
   server 192.168.56.102:9201;
   server 192.168.56.102:9202;
 }

但不支持按节点角色、节点标签进行筛选,因为 Nginx 中并没有这种概念。

INFINI Gateway

INFINI Gateway 支持按 IP 地址进行筛选:

  • 不开节点发现:只转发到配置文件指定的节点(IP 地址)
  • 开启节点发现:转发到所有发现的节点
flow:
  - name: cache_first
    filter:
      - elasticsearch:
          elasticsearch: prod
          refresh:
            enabled: true
            interval: 30s
          filter:
            hosts:
              exclude:
                - 192.168.3.201:9200
              include:
                - 192.168.3.202:9200
                - 192.168.3.203:9200

此外 Gateway 还支持通过节点角色、节点标签筛选转发节点。

flow:
  - name: cache_first
    filter:
      - elasticsearch:
          elasticsearch: prod
          refresh:
            enabled: true
            interval: 30s
          filter:
            tags:
              exclude:
                - temp: cold
              include:
                - disk: ssd
            roles:
              exclude:
                - master
              include:
                - data
                - ingest

多种筛选条件可以同时使用,详细信息请查看官方文档

作者:杨帆,极限科技(INFINI Labs)高级解决方案架构师、《老杨玩搜索》栏目 B 站 UP 主,拥有十余年金融行业服务工作经验,熟悉 Linux、数据库、网络等领域。目前主要从事 Easysearch、Elasticsearch 等搜索引擎的技术支持工作,服务国内私有化部署的客户。
原文:https://infinilabs.cn/blog/2025/proxy-elasticsearch-infini-gateway-vs-nginx/

继续阅读 »

INFINI Gateway 简介

INFINI Gateway 是一款面向 Elasticsearch 的高性能应用网关,专为提升 Elasticsearch 集群的性能、安全性和可管理性而设计。它作为 Elasticsearch 的前置网关,能够处理所有客户端请求,并将其转发到后端的 Elasticsearch 集群,同时提供丰富的功能来优化请求处理和管理。此外还支持代理 Opensearch、Easysearch 服务。

Nginx 简介

Nginx 是一个高性能的 HTTP 和反向代理服务器,以其高并发处理能力、低内存消耗和稳定性著称,广泛应用于 Web 服务器、负载均衡和反向代理等场景。在 Elasticsearch 的使用场景里,也有小伙伴使用 Nginx 来代理 Elasticsearch 的服务,利用 Nginx 的负载均衡能力,将请求转发到多个 Elasticsearch 节点。

这两个软件都能代理 Elasticsearch 服务,但是他们有什么区别?我们来一起分析分析。

负载均衡

Elasticsearch 是分布式系统,提倡使用 round-robin 方式将请求发送到多个节点。不管是 Nginx 还是 INFINI Gateway 都默认使用 round-boin 方式转发请求,也都支持 weighted round-robin(加权轮询)方式进行请求转发,这点两者相当。

节点自动更新

Elasticsearch 集群可能会遇到添加、删除节点的情况,代理程序能否感知 Elasticsearch 节点的变化将变得非常关键。

在 Nginx 中,所有转发节点的 IP 地址都必须写入到配置文件中。如果 Elasticsearch 集群加入了新的节点进行请求处理,则需要 Nginx 编辑配置文件把新节点的 IP 地址加入其中,然后重启或重载 Nginx 服务,才能将请求分发到新的节点。反之如果有节点下线,也要编辑 Nginx 配置文件并重载服务。

INFINI Gateway 是面向 Elasticsearch 设计的应用网关,具有后端节点发现和更新的功能,能够感知 Elasticsearch 集群节点加入、离开的情况。开启节点发现和更新功能后,Gateway 会定期自动更新节点列表,将请求均匀转发到列表中的节点。可参考之前的博客开启节点自动更新。

⚠️ 注意:INFINI Gateway 默认后端节点发现和更新的功能为关闭状态。

定向转发请求

使用 Elasticsearch 集群的场景多种多样,如果想对转发的节点做进一步控制,可能需要根据不同条件进行节点筛选:

  • IP 地址
  • 节点角色
  • 节点标签

Nginx

Nginx 支持根据 IP 地址进行转发的,将需要转发的节点 IP 地址写入配置文件即可。

 upstream es-cluster {
   server 192.168.56.102:9200;
   server 192.168.56.102:9201;
   server 192.168.56.102:9202;
 }

但不支持按节点角色、节点标签进行筛选,因为 Nginx 中并没有这种概念。

INFINI Gateway

INFINI Gateway 支持按 IP 地址进行筛选:

  • 不开节点发现:只转发到配置文件指定的节点(IP 地址)
  • 开启节点发现:转发到所有发现的节点
flow:
  - name: cache_first
    filter:
      - elasticsearch:
          elasticsearch: prod
          refresh:
            enabled: true
            interval: 30s
          filter:
            hosts:
              exclude:
                - 192.168.3.201:9200
              include:
                - 192.168.3.202:9200
                - 192.168.3.203:9200

此外 Gateway 还支持通过节点角色、节点标签筛选转发节点。

flow:
  - name: cache_first
    filter:
      - elasticsearch:
          elasticsearch: prod
          refresh:
            enabled: true
            interval: 30s
          filter:
            tags:
              exclude:
                - temp: cold
              include:
                - disk: ssd
            roles:
              exclude:
                - master
              include:
                - data
                - ingest

多种筛选条件可以同时使用,详细信息请查看官方文档

作者:杨帆,极限科技(INFINI Labs)高级解决方案架构师、《老杨玩搜索》栏目 B 站 UP 主,拥有十余年金融行业服务工作经验,熟悉 Linux、数据库、网络等领域。目前主要从事 Easysearch、Elasticsearch 等搜索引擎的技术支持工作,服务国内私有化部署的客户。
原文:https://infinilabs.cn/blog/2025/proxy-elasticsearch-infini-gateway-vs-nginx/

收起阅读 »

Elasticseach Ingest 模块&&漏洞分析

本文基于Elasticsearch7.10.2分析

0.Ingest 节点 概述

在实际进行文档index之前,使用采集节点(默认情况下,每个es节点都是ingest)对文档进行预处理。采集节点会拦截bulk和index请求,进行转换,然后将文档传回index或bulk API。

每个索引都有index.default_pipeline 和 index.final_pipeline 两个配置。

他们都是用于指定 Elasticsearch index 或者bulk 文档时要执行的预处理逻辑。

  • index.default_pipeline 定义了默认管道,它会在索引文档时首先执行。但如果索引请求中指定了 pipeline 参数,则该参数指定的管道会覆盖默认管道。如果设置了 index.default_pipeline 但对应的管道不存在,索引请求会失败。特殊值 _none 表示不运行任何摄取管道。
  • index.final_pipeline 定义了最终管道,它总是在请求管道(如果指定)和默认管道(如果存在)之后执行。如果设置了 index.final_pipeline 但对应的管道不存在,索引请求会失败。特殊值 _none 表示不运行最终管道。

简而言之,default_pipeline 先执行,可被覆盖;final_pipeline 后执行,不可被覆盖。两者都可设为 _none 以禁用。

一个Pipeline可以有多个Processor组成,每个Processor有着各自的不同功能,官方支持的Processor可参考:https://www.elastic.co/guide/en/elasticsearch/reference/7.10/ingest-processors.html

一个简单的例子,利用Set Processor 对新增的文档中加入新的字段和值:

PUT _ingest/pipeline/set_os
{
  "description": "sets the value of host.os.name from the field os",
  "processors": [
    {
      "set": {
        "field": "host.os.name",  // 增加的属性
        "value": "{{os}}"   // 这里引用了文档原先的os属性, 这里可以直接填写其他值
      }
    }
  ]
}

POST _ingest/pipeline/set_os/_simulate
{
  "docs": [
    {
      "_source": {
        "os": "Ubuntu"
      }
    }
  ]
}

这样转换之后,文档内容就变成了:

{
  "host" : {
    "os" : {
      "name" : "Ubuntu"
    }
  },
  "os" : "Ubuntu"
}

写单个文档的流程概述

没有指定pipeline.png

当请求,或者索引本身配置有pipline的时候,协调节点就会转发到ingest节点

PSOT source_index/_doc?pipeline=set_os
{
  "os": "xxxx"
}

指定了pipeline.png

【注】 并不是一定会发生内部rpc的请求转发,如果本地节点能接受当前的请求则不会转发到其他节点。

1. 模块总体概述

本小节关注IngestService中重要的相关类,对这些类有一个整体的了解有助于理解该模块。

  • ClusterService
    • IngestService 实现了 ClusterStateApplier 接口, 这样就能监听和响应集群的状态变化,当集群状态更新时,IngestService可以调整其内部 pipelines完成CRUD。
    • 另外IngestService还有List<Consumer>用来对提供给对集群状态变更之后需要最新状态的插件。
  • ScriptService
    • 某些Processor需要其用于管理和执行脚本,比如Script Processor。
  • AnalysisRegistry
    • 某些需要对文档内容进行分词处理的Processor。
  • ThreadPool
    • Processor都是异步执行的,实际执行线程池取决于调用上下文(如 write 或 management)
      • bulk API 时发生的pipeline 处理使用的是write线程池。
      • pipeline/_simulate API 使用的是management线程池,模拟执行通常是短时间的、低频的任务,不需要高并发支持而且为了不影响实际的文档处理或其他重要任务。
    • 另外为了避免Grok Processor运行时间过长,使用了Generic线程做定时调度检查执行时间
  • IngestMetric
    • 通过实现ReportingService接口来做到展示ingest内部的执行情况。
    • GET _nodes/stats?filter_path=nodes.*.ingest 可以查看到ingest 中的每个Pipeline中的执行的次数、失败次数以及总耗时
  • IngestPlugin
    • Ingest支持加载自定义的Processor插件,系统内置的所有Processor以及自定义的都通过IngestService 中的Map<String, Processor.Factory> processorFactories来进行管理。
  • IngestDocument
    • 其包含文档的源数据,提供了修改和查询文档的字段的能力,为Processor灵活操作文档数据提供基础,在后续pipeline的执行中,也是由其的executePipeline方法驱动的。

2. Processor 实现机制

抽象工厂设计模式的应用

Processor接口设计

每个Processor都有核心方法execute,使得处理器能够以统一的方式操作 IngestDocument,并通过多态实现不同处理逻辑。

Processor.Factory的设计

Processor.Factory 是 Processor 的抽象工厂,负责动态创建处理器实例。其主要职责包括:

  • 动态实例化
    • Processor create() 方法接收处理器配置并创建具体的处理器。
    • 支持递归创建,例如ConditionalProcessor可以嵌套其他处理器。
  • 依赖注入
    • Processor.Parameters 提供了一组服务和工具(如 ScriptService),工厂可以利用这些依赖创建复杂的Processor。

Processor.Factory的集中管理

在 IngestService 中,通过 Map<String, Processor.Factory> processorFactories 集中管理所有处理器工厂。这种管理方式提供了以下优势:

动态扩展

  • 插件可以注册自定义Processor工厂。
  • 新处理器类型的注册仅需添加到 processorFactories。

组合以及装饰器设计模式的应用

Processor经典的几个类的关系如下:

processor关系类图.png

CompoundProcessor是经典的组合设计模式,Pipeline这个类可以像使用单个 Processor 一样调用 CompoundProcessor,无需关注其内部具体细节。

而ConditionalProcessor 以及TrackingResultProcessor则体现了装饰器模式,在不改变原有对象的情况下扩展功能:

  • ConditionalProcessor 在执行Processor前会调用evaluate方法判断是否需要执行。
  • TrackingResultProcessor中decorate是为 CompoundProcessor 及其内部的 Processor 添加跟踪功能。

如何自定义Processor 插件

自定义 Processor 插件的注册方式为实现 IngestPlugin (Elasticsearch 提供不同的插件接口用来扩展不同类型的功能)的 getProcessors 方法,该方法返回一个工厂列表,IngestService 会将这些工厂注入到 processorFactories 中。

分析完代码之后,我们回到实战中来,简单起见,我们实现类似Append的Processor,但是我们这个更简单,输入的是字符串,然后我们用,分割一下将其作为数组设为值。

import org.elasticsearch.ingest.Processor;
import org.elasticsearch.plugins.IngestPlugin;
import org.elasticsearch.plugins.Plugin;
import java.util.HashMap;
import java.util.Map;
public class AddArrayProcessorPlugin extends Plugin implements IngestPlugin {
    @Override
    public Map<String, Processor.Factory> getProcessors(Processor.Parameters parameters) {
        Map<String, Processor.Factory> processors = new HashMap<>();
        processors.put(AddArrayProcessor.TYPE, new AddArrayProcessor.Factory());
        return processors;
    }
}
import org.elasticsearch.ingest.AbstractProcessor;
import org.elasticsearch.ingest.ConfigurationUtils;
import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor;
import java.util.*;

public class AddArrayProcessor extends AbstractProcessor {
    public static final String TYPE = "add_array";
    public String field;
    public String value;
    protected AddArrayProcessor(String tag, String description, String field, String value) {
        super(tag, description);
        this.field = field;
        this.value = value;
    }
    @Override
    public IngestDocument execute(IngestDocument ingestDocument) throws Exception {
        List valueList = new ArrayList<>(Arrays.asList(value.split(",")));
        ingestDocument.setFieldValue(field, valueList);
        return ingestDocument;
    }
    @Override
    public String getType() {
        return TYPE;
    }
    public static final class Factory implements Processor.Factory {
        @Override
        public Processor create(Map<String, Processor.Factory> processorFactories, String tag,
                                String description, Map<String, Object> config) throws Exception {
            String field = ConfigurationUtils.readStringProperty(TYPE, tag, config, "field");
            String value = ConfigurationUtils.readStringProperty(TYPE, tag, config, "value");
            return new AddArrayProcessor(tag, description, field, value);
        }
    }
}

打包之后,我们去install我们的Processor插件:

bin/elasticsearch-plugin install file:///home/hcb/data/data/es/data_standalone/elasticsearch-7.10.2-SNAPSHOT/AddArrayProcessor-1.0-SNAPSHOT.zip 
warning: no-jdk distributions that do not bundle a JDK are deprecated and will be removed in a future release
-> Installing file:///home/hcb/data/data/es/data_standalone/elasticsearch-7.10.2-SNAPSHOT/AddArrayProcessor-1.0-SNAPSHOT.zip
-> Downloading file:///home/hcb/data/data/es/data_standalone/elasticsearch-7.10.2-SNAPSHOT/AddArrayProcessor-1.0-SNAPSHOT.zip
[=================================================] 100%   
-> Installed AddArrayProcess

测试一下:

POST /_ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
       {
        "add_array": {
          "field": "test_arr",
          "value": "a,b,c,d,e,f"
        }
      }
    ]
  },
  "docs": [
    {
      "_index": "test",
      "_id": "1",
      "_source": {
        "field": "value"
      }
    }
  ]
}
docs结果:
"_source" : {
          "field" : "value",
          "test_arr" : [
            "a",
            "b",
            "c",
            "d",
            "e",
            "f"
          ]
        }

3. Pipeline设计

如何管理Pipeline

在IngestServcie中有一个Map存储所有的Pipeline实例,private volatile Map<String, PipelineHolder> pipelines = Collections.emptyMap();

这里并没有将Pipeline实例存储在IngestMetadata,这样做的原因有2个:

  1. 在 Elasticsearch 的启动过程中,插件和节点服务的初始化发生在 ClusterState 加载之后, 只有等所有插件完成加载后,所有的Processor工厂才会被注册到系统中,这意味着在集群状态初始化之前,Processor工厂并不可用。
  2. ClusterState 中的元数据结构是静态注册的,即在类加载时已经确定,如果要将运行时示例存储进去,必须改变 ClusterState 的元数据结构存储格式,这个很不方便维护,而且这在集群状态同步的时候也会带来不必要的序列化以及反序列化。

所以Pipeline的管理逻辑是:

  • ClusterState 中的IngestMetadata 只存储 JSON 格式的管道定义,描述 Pipeline 的配置(例如,包含哪些 Processor,它们的参数等)。
  • IngestService 中维护的运行时实例,将 JSON 配置解析为完整的 Pipeline 对象,包括处理器链

在集群变更时, pipeline的CRUD的实现在innerUpdatePipelines方法中 。

责任链设计模式的应用

管道的执行通过IngestDocument的org.elasticsearch.ingest.IngestDocument#executePipeline 去驱动,每个文档的每个Pipeline都会进入到这个函数, 而每个Pipeline有组装好的CompoundProcessor,实际的链式调用是在CompoundProcessor中。

简图大致如下:

pipeline执行简图.png

这里拿其和Zookeeper(3.6.3)中RequestProcessor 做一些对比:

特点 ES中的CompoundProcessor Zookeeper中RequestProcessor
链的存储定义 由两条列表组成,分别保存正常流程以及失败流程的Processor列表。 固定的链式结构。
异步执行 支持异步回调,可以异步执行链中的处理器。 同步执行 。
失败处理 提供专门的 onFailureProcessors 作为失败处理链。如果不忽略异常并且onFailureProcessors 不为空则会执行失败处理链逻辑。 没有专门的失败处理链,异常直接交由上层捕获。
可配置性 可动态调整处理器链和配置(如 ignoreFailure)。 代码中写死,无法配置

这里并没有说Zookeeper的设计就差于Elasticsearch, 只是设计目标有所不同,RequestProcessor就是适合集中式的强一致、其中Processor并不需要灵活变化,而CompoundProcessor就是适合高并发而Procesor灵活变化场景。

4. Ingest实战建议

回到实战中来,这里结合目前所分析的内容给出相应的实战建议。

  • 建立监控
    • 对于关键的Piepline,我们需要通过GET _nodes/stats?filter_path=nodes.*.ingest 获取其运行状况,识别延迟或失败的 Processor。
    • 文档写入的时候使用的是write线程池,我们也需要监控GET _nodes/stats?filter_path=nodes.*.thread_pool.write 的queue和write_rejections 判断需要扩展线程池。
  • 优化Processor
    • 减少高开销操作,优先使用内置 Processor,比如script Processor 可适时替换set, append,避免过度复杂的正则表达式或嵌套逻辑。
    • 自定义的Processor尽量优化,比如如果涉及查询外部系统可考虑引入缓存。
  • 建立单独的Ingest节点
    • 如果有大量的Pipeline需要执行,则可以考虑增加专用 Ingest 节点,避免与数据节点争夺资源。

5. 漏洞&&修复分析

这里分析7.10.2版本Ingest模块存在的漏洞以及官方是如何修复的。

CVE-2021-22144

https://discuss.elastic.co/t/elasticsearch-7-13-3-and-6-8-17-security-update/278100

Elasticsearch Grok 解析器中发现了一个不受控制的递归漏洞,该漏洞可能导致拒绝服务攻击。能够向 Elasticsearch 提交任意查询的用户可能会创建恶意 Grok 查询,从而导致 Elasticsearch 节点崩溃。

漏洞复现

发起这个请求:

  • patterns: 处理字段时使用的 Grok 模式,这里设置为 %{INT}。
  • pattern_definitions: 定义自定义 Grok 模式,这里故意让 INT 模式递归引用自身,导致循环引用问题。
POST /_ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
      {
        "grok": {
          "field": "message",
          "patterns": [
            "%{INT}"
          ],
          "pattern_definitions": {
            "INT": "%{INT}"
          }
        }
      }
    ]
  },
  "docs": [
    {
      "_source": {
        "message": "test"
      }
    }
  ]
}

当执行之后会使得节点直接StackOverflow中止进程。

修复逻辑

这个问题的关键在于原先的逻辑中,只会对间接的递归引用(pattern1 => pattern2 => pattern3 => pattern1)做了检测,但是没有对直接的自引用(pattern1 => pattern1 )做检测。

    private void forbidCircularReferences() {
                // 这个是增加的逻辑,检测直接的自引用
        for (Map.Entry<String, String> entry : patternBank.entrySet()) {
            if (patternReferencesItself(entry.getValue(), entry.getKey())) {
                throw new IllegalArgumentException("circular reference in pattern [" + entry.getKey() + "][" + entry.getValue() + "]");
            }
        }

        // 间接递归引用检测(这个是原先的逻辑)
        for (Map.Entry<String, String> entry : patternBank.entrySet()) {
            String name = entry.getKey();
            String pattern = entry.getValue();
            innerForbidCircularReferences(name, new ArrayList<>(), pattern);
        }
    }

CVE-2023-46673

https://discuss.elastic.co/t/elasticsearch-7-17-14-8-10-3-security-update-esa-2023-24/347708

漏洞复现

尝试了很多已有的Processor都没有复现,我们这使用自定义的Processor来复现,将之前的自定义AddArrayProcessor加一行代码:

    @Override
    public IngestDocument execute(IngestDocument ingestDocument) throws Exception {
        List valueList = new ArrayList<>(Arrays.asList(value.split(",")));
        valueList.add(valueList);  // 增加的代码
        ingestDocument.setFieldValue(field, valueList);
        return ingestDocument;
    }

重新编译再安装插件之后,执行改Processor 将会StackOverflow。

修复逻辑

这个问题的关键在于在IngestDocument的deepCopyMap的方法之前没有判断这样的无限引用的情况:

循环引用.png

那么在此之前做一个检测就好了,这个方法在原本的ES代码中就存在:org.elasticsearch.common.util.CollectionUtils#ensureNoSelfReferences(java.lang.Object, java.lang.String) ,其利用 IdentityHashMap 记录已访问对象的引用,检测并防止对象间的循环引用。

CVE-2024-23450

https://discuss.elastic.co/t/elasticsearch-8-13-0-7-17-19-security-update-esa-2024-06/356314

漏洞复现

虽然我们的索引只有2个Pipeline的配置,但是由于Pipeline Processor的存在,所以实际上一个文档其实能被很多Pipeline处理,当需要执行足够多个的pipline个数时,则会发生StackOverflow。

修复逻辑

这个问题的关键在于对Pipeline的个数并没有限制,添加一个配置项,当超出该个数则直接抛出异常。

public static final int MAX_PIPELINES = Integer.parseInt(System.getProperty("es.ingest.max_pipelines", "100"));

IngestDocument的org.elasticsearch.ingest.IngestDocument#executePipeline 添加逻辑:

    public void executePipeline(Pipeline pipeline, BiConsumer<IngestDocument, Exception> handler) {
        if (executedPipelines.size() >= MAX_PIPELINES) {
            handler.accept(
                null,
                new IllegalStateException(PIPELINE_TOO_MANY_ERROR_MESSAGE + MAX_PIPELINES + " nested pipelines")
            );
        } 

思考: 这里判断pipeline是否超出100个限制是用已经执行的pipeline个数来计算的。 假设已经超出100个pipeline,那这100个pipeline是会白跑的, 如果能在真正执行之前分析需要执行的Pipeline个数会更好。

6. 总结

Ingest 模块作为 Elasticsearch 数据处理流程的重要组成部分,提供了灵活的管道化能力,使得用户能够在数据写入前进行丰富的预处理操作。然而,在实际场景中,Ingest 模块也面临性能瓶颈、资源竞争等挑战,需要结合业务需求和系统现状进行精细化调优,通过优化 Processor 执行效率、合理规划集群架构以及增强监控与诊断手段,我们可以充分释放 Ingest 模块的能力,提升 Elasticsearch 的整体数据处理能力。

继续阅读 »

本文基于Elasticsearch7.10.2分析

0.Ingest 节点 概述

在实际进行文档index之前,使用采集节点(默认情况下,每个es节点都是ingest)对文档进行预处理。采集节点会拦截bulk和index请求,进行转换,然后将文档传回index或bulk API。

每个索引都有index.default_pipeline 和 index.final_pipeline 两个配置。

他们都是用于指定 Elasticsearch index 或者bulk 文档时要执行的预处理逻辑。

  • index.default_pipeline 定义了默认管道,它会在索引文档时首先执行。但如果索引请求中指定了 pipeline 参数,则该参数指定的管道会覆盖默认管道。如果设置了 index.default_pipeline 但对应的管道不存在,索引请求会失败。特殊值 _none 表示不运行任何摄取管道。
  • index.final_pipeline 定义了最终管道,它总是在请求管道(如果指定)和默认管道(如果存在)之后执行。如果设置了 index.final_pipeline 但对应的管道不存在,索引请求会失败。特殊值 _none 表示不运行最终管道。

简而言之,default_pipeline 先执行,可被覆盖;final_pipeline 后执行,不可被覆盖。两者都可设为 _none 以禁用。

一个Pipeline可以有多个Processor组成,每个Processor有着各自的不同功能,官方支持的Processor可参考:https://www.elastic.co/guide/en/elasticsearch/reference/7.10/ingest-processors.html

一个简单的例子,利用Set Processor 对新增的文档中加入新的字段和值:

PUT _ingest/pipeline/set_os
{
  "description": "sets the value of host.os.name from the field os",
  "processors": [
    {
      "set": {
        "field": "host.os.name",  // 增加的属性
        "value": "{{os}}"   // 这里引用了文档原先的os属性, 这里可以直接填写其他值
      }
    }
  ]
}

POST _ingest/pipeline/set_os/_simulate
{
  "docs": [
    {
      "_source": {
        "os": "Ubuntu"
      }
    }
  ]
}

这样转换之后,文档内容就变成了:

{
  "host" : {
    "os" : {
      "name" : "Ubuntu"
    }
  },
  "os" : "Ubuntu"
}

写单个文档的流程概述

没有指定pipeline.png

当请求,或者索引本身配置有pipline的时候,协调节点就会转发到ingest节点

PSOT source_index/_doc?pipeline=set_os
{
  "os": "xxxx"
}

指定了pipeline.png

【注】 并不是一定会发生内部rpc的请求转发,如果本地节点能接受当前的请求则不会转发到其他节点。

1. 模块总体概述

本小节关注IngestService中重要的相关类,对这些类有一个整体的了解有助于理解该模块。

  • ClusterService
    • IngestService 实现了 ClusterStateApplier 接口, 这样就能监听和响应集群的状态变化,当集群状态更新时,IngestService可以调整其内部 pipelines完成CRUD。
    • 另外IngestService还有List<Consumer>用来对提供给对集群状态变更之后需要最新状态的插件。
  • ScriptService
    • 某些Processor需要其用于管理和执行脚本,比如Script Processor。
  • AnalysisRegistry
    • 某些需要对文档内容进行分词处理的Processor。
  • ThreadPool
    • Processor都是异步执行的,实际执行线程池取决于调用上下文(如 write 或 management)
      • bulk API 时发生的pipeline 处理使用的是write线程池。
      • pipeline/_simulate API 使用的是management线程池,模拟执行通常是短时间的、低频的任务,不需要高并发支持而且为了不影响实际的文档处理或其他重要任务。
    • 另外为了避免Grok Processor运行时间过长,使用了Generic线程做定时调度检查执行时间
  • IngestMetric
    • 通过实现ReportingService接口来做到展示ingest内部的执行情况。
    • GET _nodes/stats?filter_path=nodes.*.ingest 可以查看到ingest 中的每个Pipeline中的执行的次数、失败次数以及总耗时
  • IngestPlugin
    • Ingest支持加载自定义的Processor插件,系统内置的所有Processor以及自定义的都通过IngestService 中的Map<String, Processor.Factory> processorFactories来进行管理。
  • IngestDocument
    • 其包含文档的源数据,提供了修改和查询文档的字段的能力,为Processor灵活操作文档数据提供基础,在后续pipeline的执行中,也是由其的executePipeline方法驱动的。

2. Processor 实现机制

抽象工厂设计模式的应用

Processor接口设计

每个Processor都有核心方法execute,使得处理器能够以统一的方式操作 IngestDocument,并通过多态实现不同处理逻辑。

Processor.Factory的设计

Processor.Factory 是 Processor 的抽象工厂,负责动态创建处理器实例。其主要职责包括:

  • 动态实例化
    • Processor create() 方法接收处理器配置并创建具体的处理器。
    • 支持递归创建,例如ConditionalProcessor可以嵌套其他处理器。
  • 依赖注入
    • Processor.Parameters 提供了一组服务和工具(如 ScriptService),工厂可以利用这些依赖创建复杂的Processor。

Processor.Factory的集中管理

在 IngestService 中,通过 Map<String, Processor.Factory> processorFactories 集中管理所有处理器工厂。这种管理方式提供了以下优势:

动态扩展

  • 插件可以注册自定义Processor工厂。
  • 新处理器类型的注册仅需添加到 processorFactories。

组合以及装饰器设计模式的应用

Processor经典的几个类的关系如下:

processor关系类图.png

CompoundProcessor是经典的组合设计模式,Pipeline这个类可以像使用单个 Processor 一样调用 CompoundProcessor,无需关注其内部具体细节。

而ConditionalProcessor 以及TrackingResultProcessor则体现了装饰器模式,在不改变原有对象的情况下扩展功能:

  • ConditionalProcessor 在执行Processor前会调用evaluate方法判断是否需要执行。
  • TrackingResultProcessor中decorate是为 CompoundProcessor 及其内部的 Processor 添加跟踪功能。

如何自定义Processor 插件

自定义 Processor 插件的注册方式为实现 IngestPlugin (Elasticsearch 提供不同的插件接口用来扩展不同类型的功能)的 getProcessors 方法,该方法返回一个工厂列表,IngestService 会将这些工厂注入到 processorFactories 中。

分析完代码之后,我们回到实战中来,简单起见,我们实现类似Append的Processor,但是我们这个更简单,输入的是字符串,然后我们用,分割一下将其作为数组设为值。

import org.elasticsearch.ingest.Processor;
import org.elasticsearch.plugins.IngestPlugin;
import org.elasticsearch.plugins.Plugin;
import java.util.HashMap;
import java.util.Map;
public class AddArrayProcessorPlugin extends Plugin implements IngestPlugin {
    @Override
    public Map<String, Processor.Factory> getProcessors(Processor.Parameters parameters) {
        Map<String, Processor.Factory> processors = new HashMap<>();
        processors.put(AddArrayProcessor.TYPE, new AddArrayProcessor.Factory());
        return processors;
    }
}
import org.elasticsearch.ingest.AbstractProcessor;
import org.elasticsearch.ingest.ConfigurationUtils;
import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor;
import java.util.*;

public class AddArrayProcessor extends AbstractProcessor {
    public static final String TYPE = "add_array";
    public String field;
    public String value;
    protected AddArrayProcessor(String tag, String description, String field, String value) {
        super(tag, description);
        this.field = field;
        this.value = value;
    }
    @Override
    public IngestDocument execute(IngestDocument ingestDocument) throws Exception {
        List valueList = new ArrayList<>(Arrays.asList(value.split(",")));
        ingestDocument.setFieldValue(field, valueList);
        return ingestDocument;
    }
    @Override
    public String getType() {
        return TYPE;
    }
    public static final class Factory implements Processor.Factory {
        @Override
        public Processor create(Map<String, Processor.Factory> processorFactories, String tag,
                                String description, Map<String, Object> config) throws Exception {
            String field = ConfigurationUtils.readStringProperty(TYPE, tag, config, "field");
            String value = ConfigurationUtils.readStringProperty(TYPE, tag, config, "value");
            return new AddArrayProcessor(tag, description, field, value);
        }
    }
}

打包之后,我们去install我们的Processor插件:

bin/elasticsearch-plugin install file:///home/hcb/data/data/es/data_standalone/elasticsearch-7.10.2-SNAPSHOT/AddArrayProcessor-1.0-SNAPSHOT.zip 
warning: no-jdk distributions that do not bundle a JDK are deprecated and will be removed in a future release
-> Installing file:///home/hcb/data/data/es/data_standalone/elasticsearch-7.10.2-SNAPSHOT/AddArrayProcessor-1.0-SNAPSHOT.zip
-> Downloading file:///home/hcb/data/data/es/data_standalone/elasticsearch-7.10.2-SNAPSHOT/AddArrayProcessor-1.0-SNAPSHOT.zip
[=================================================] 100%   
-> Installed AddArrayProcess

测试一下:

POST /_ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
       {
        "add_array": {
          "field": "test_arr",
          "value": "a,b,c,d,e,f"
        }
      }
    ]
  },
  "docs": [
    {
      "_index": "test",
      "_id": "1",
      "_source": {
        "field": "value"
      }
    }
  ]
}
docs结果:
"_source" : {
          "field" : "value",
          "test_arr" : [
            "a",
            "b",
            "c",
            "d",
            "e",
            "f"
          ]
        }

3. Pipeline设计

如何管理Pipeline

在IngestServcie中有一个Map存储所有的Pipeline实例,private volatile Map<String, PipelineHolder> pipelines = Collections.emptyMap();

这里并没有将Pipeline实例存储在IngestMetadata,这样做的原因有2个:

  1. 在 Elasticsearch 的启动过程中,插件和节点服务的初始化发生在 ClusterState 加载之后, 只有等所有插件完成加载后,所有的Processor工厂才会被注册到系统中,这意味着在集群状态初始化之前,Processor工厂并不可用。
  2. ClusterState 中的元数据结构是静态注册的,即在类加载时已经确定,如果要将运行时示例存储进去,必须改变 ClusterState 的元数据结构存储格式,这个很不方便维护,而且这在集群状态同步的时候也会带来不必要的序列化以及反序列化。

所以Pipeline的管理逻辑是:

  • ClusterState 中的IngestMetadata 只存储 JSON 格式的管道定义,描述 Pipeline 的配置(例如,包含哪些 Processor,它们的参数等)。
  • IngestService 中维护的运行时实例,将 JSON 配置解析为完整的 Pipeline 对象,包括处理器链

在集群变更时, pipeline的CRUD的实现在innerUpdatePipelines方法中 。

责任链设计模式的应用

管道的执行通过IngestDocument的org.elasticsearch.ingest.IngestDocument#executePipeline 去驱动,每个文档的每个Pipeline都会进入到这个函数, 而每个Pipeline有组装好的CompoundProcessor,实际的链式调用是在CompoundProcessor中。

简图大致如下:

pipeline执行简图.png

这里拿其和Zookeeper(3.6.3)中RequestProcessor 做一些对比:

特点 ES中的CompoundProcessor Zookeeper中RequestProcessor
链的存储定义 由两条列表组成,分别保存正常流程以及失败流程的Processor列表。 固定的链式结构。
异步执行 支持异步回调,可以异步执行链中的处理器。 同步执行 。
失败处理 提供专门的 onFailureProcessors 作为失败处理链。如果不忽略异常并且onFailureProcessors 不为空则会执行失败处理链逻辑。 没有专门的失败处理链,异常直接交由上层捕获。
可配置性 可动态调整处理器链和配置(如 ignoreFailure)。 代码中写死,无法配置

这里并没有说Zookeeper的设计就差于Elasticsearch, 只是设计目标有所不同,RequestProcessor就是适合集中式的强一致、其中Processor并不需要灵活变化,而CompoundProcessor就是适合高并发而Procesor灵活变化场景。

4. Ingest实战建议

回到实战中来,这里结合目前所分析的内容给出相应的实战建议。

  • 建立监控
    • 对于关键的Piepline,我们需要通过GET _nodes/stats?filter_path=nodes.*.ingest 获取其运行状况,识别延迟或失败的 Processor。
    • 文档写入的时候使用的是write线程池,我们也需要监控GET _nodes/stats?filter_path=nodes.*.thread_pool.write 的queue和write_rejections 判断需要扩展线程池。
  • 优化Processor
    • 减少高开销操作,优先使用内置 Processor,比如script Processor 可适时替换set, append,避免过度复杂的正则表达式或嵌套逻辑。
    • 自定义的Processor尽量优化,比如如果涉及查询外部系统可考虑引入缓存。
  • 建立单独的Ingest节点
    • 如果有大量的Pipeline需要执行,则可以考虑增加专用 Ingest 节点,避免与数据节点争夺资源。

5. 漏洞&&修复分析

这里分析7.10.2版本Ingest模块存在的漏洞以及官方是如何修复的。

CVE-2021-22144

https://discuss.elastic.co/t/elasticsearch-7-13-3-and-6-8-17-security-update/278100

Elasticsearch Grok 解析器中发现了一个不受控制的递归漏洞,该漏洞可能导致拒绝服务攻击。能够向 Elasticsearch 提交任意查询的用户可能会创建恶意 Grok 查询,从而导致 Elasticsearch 节点崩溃。

漏洞复现

发起这个请求:

  • patterns: 处理字段时使用的 Grok 模式,这里设置为 %{INT}。
  • pattern_definitions: 定义自定义 Grok 模式,这里故意让 INT 模式递归引用自身,导致循环引用问题。
POST /_ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
      {
        "grok": {
          "field": "message",
          "patterns": [
            "%{INT}"
          ],
          "pattern_definitions": {
            "INT": "%{INT}"
          }
        }
      }
    ]
  },
  "docs": [
    {
      "_source": {
        "message": "test"
      }
    }
  ]
}

当执行之后会使得节点直接StackOverflow中止进程。

修复逻辑

这个问题的关键在于原先的逻辑中,只会对间接的递归引用(pattern1 => pattern2 => pattern3 => pattern1)做了检测,但是没有对直接的自引用(pattern1 => pattern1 )做检测。

    private void forbidCircularReferences() {
                // 这个是增加的逻辑,检测直接的自引用
        for (Map.Entry<String, String> entry : patternBank.entrySet()) {
            if (patternReferencesItself(entry.getValue(), entry.getKey())) {
                throw new IllegalArgumentException("circular reference in pattern [" + entry.getKey() + "][" + entry.getValue() + "]");
            }
        }

        // 间接递归引用检测(这个是原先的逻辑)
        for (Map.Entry<String, String> entry : patternBank.entrySet()) {
            String name = entry.getKey();
            String pattern = entry.getValue();
            innerForbidCircularReferences(name, new ArrayList<>(), pattern);
        }
    }

CVE-2023-46673

https://discuss.elastic.co/t/elasticsearch-7-17-14-8-10-3-security-update-esa-2023-24/347708

漏洞复现

尝试了很多已有的Processor都没有复现,我们这使用自定义的Processor来复现,将之前的自定义AddArrayProcessor加一行代码:

    @Override
    public IngestDocument execute(IngestDocument ingestDocument) throws Exception {
        List valueList = new ArrayList<>(Arrays.asList(value.split(",")));
        valueList.add(valueList);  // 增加的代码
        ingestDocument.setFieldValue(field, valueList);
        return ingestDocument;
    }

重新编译再安装插件之后,执行改Processor 将会StackOverflow。

修复逻辑

这个问题的关键在于在IngestDocument的deepCopyMap的方法之前没有判断这样的无限引用的情况:

循环引用.png

那么在此之前做一个检测就好了,这个方法在原本的ES代码中就存在:org.elasticsearch.common.util.CollectionUtils#ensureNoSelfReferences(java.lang.Object, java.lang.String) ,其利用 IdentityHashMap 记录已访问对象的引用,检测并防止对象间的循环引用。

CVE-2024-23450

https://discuss.elastic.co/t/elasticsearch-8-13-0-7-17-19-security-update-esa-2024-06/356314

漏洞复现

虽然我们的索引只有2个Pipeline的配置,但是由于Pipeline Processor的存在,所以实际上一个文档其实能被很多Pipeline处理,当需要执行足够多个的pipline个数时,则会发生StackOverflow。

修复逻辑

这个问题的关键在于对Pipeline的个数并没有限制,添加一个配置项,当超出该个数则直接抛出异常。

public static final int MAX_PIPELINES = Integer.parseInt(System.getProperty("es.ingest.max_pipelines", "100"));

IngestDocument的org.elasticsearch.ingest.IngestDocument#executePipeline 添加逻辑:

    public void executePipeline(Pipeline pipeline, BiConsumer<IngestDocument, Exception> handler) {
        if (executedPipelines.size() >= MAX_PIPELINES) {
            handler.accept(
                null,
                new IllegalStateException(PIPELINE_TOO_MANY_ERROR_MESSAGE + MAX_PIPELINES + " nested pipelines")
            );
        } 

思考: 这里判断pipeline是否超出100个限制是用已经执行的pipeline个数来计算的。 假设已经超出100个pipeline,那这100个pipeline是会白跑的, 如果能在真正执行之前分析需要执行的Pipeline个数会更好。

6. 总结

Ingest 模块作为 Elasticsearch 数据处理流程的重要组成部分,提供了灵活的管道化能力,使得用户能够在数据写入前进行丰富的预处理操作。然而,在实际场景中,Ingest 模块也面临性能瓶颈、资源竞争等挑战,需要结合业务需求和系统现状进行精细化调优,通过优化 Processor 执行效率、合理规划集群架构以及增强监控与诊断手段,我们可以充分释放 Ingest 模块的能力,提升 Elasticsearch 的整体数据处理能力。

收起阅读 »

Elastic 宣布修改开源协议为 AGPL:Elasticsearch 再次成为开源软件

今日快讯!就在刚刚,开源搜索领域行业巨头 Elastic 官方博客发表了一篇最新公告《Elasticsearch is Open Source, Again》,Elastic 创始人& CTO Shay Banon 宣布 Elasticsearch 和 Kibana 许可证协议修改为 AGPL。

original-elastic-logos.png

以下为搜索客社区从 Elastic 官方博客翻译的原文内容:


Elasticsearch 再次成为开源软件

[D.N.A] Elasticsearch 和 Kibana 现在可以再次被称为开源软件了。这句话让我感到无比的兴奋。真的忍不住跳起来庆祝!我们所有在 Elastic 的人都很高兴。开源精神是我的DNA,也是 Elastic 的DNA。能够再次称 Elasticsearch 为开源软件,真的是一种纯粹的快乐。

[LOVE.] 简而言之,我们将在接下来的几周内,除了 ELv2 和 SSPL 之外,增加 AGPL 作为另一个许可选项。在更改许可后,我们从未停止过像一个开源社区一样相信和行动。但通过使用 AGPL 这一获得开放源码促进会(OSI)批准的许可,消除了人们可能存在的任何疑问或混淆。

[Not Like Us] 我们在 Elastic 从未停止过对开源的信仰。我个人对开源的信仰也从未动摇,至今已有 25 年了。那么为什么三年前我们要做出改变呢?我们遇到了与 AWS 相关的问题,以及他们的服务引发的市场混乱。在尝试了所有能想到的其他选项后,我们更改了许可协议,明知道这会导致 Elasticsearch 被分叉成另一个名称并走上不同的发展轨迹。这是一个漫长的故事。

[Like That] 好消息是,虽然过程痛苦,但结果奏效了。三年后,亚马逊已经完全投入到了他们的分叉项目中,市场的混乱(大部分)得到了缓解,我们与 AWS 的合作伙伴关系比以往更强。我们甚至被评为 AWS 的年度合作伙伴。我一直希望时间能过去得足够久,以至于我们可以安全地回到开源项目的状态——现在终于到了。

[All The Stars] 我们希望尽可能简化用户的使用体验。我们有用户非常喜欢 ELv2(一个受 BSD 启发的许可)。我们也有用户已经批准使用 SSPL(通过 MongoDB 使用)。这就是为什么我们只是增加了一个选项,而不是移除任何东西。如果你已经在使用并喜欢 Elasticsearch,请继续使用,没有任何变化。对于其他人,现在你也可以选择使用 AGPL。

[LOYALTY.] 我们选择 AGPL 而不是其他许可,是因为我们希望通过与 OSI 的合作,能在开源许可领域创造更多的选项。随着我们更改许可以来的发展(例如 Grafana 从 Apache2 转移到 AGPL),也许 AGPL 已经足够适用于像我们这样的基础设施软件了。我们致力于找到最合适的解决方案。

[euphoria] 我非常高兴能够再次称 Elasticsearch 为开源软件。

[Alright] 任何改变都可能引发混淆,当然也可能引来一些网络喷子。(网络喷子总是存在的,对吧?)让我们愉快地回答一些可能出现的问题吧。我可以想象到的一些问题如下,但我们会继续补充。

“更改许可是个错误,Elastic 现在在回撤”:我们在三年前更改许可时消除了很多市场混乱。由于我们的行动,很多事情已经改变。现在是一个完全不同的市场环境。我们不生活在过去。我们希望为用户打造一个更好的未来。正是因为我们当时采取了行动,现在我们才有能力采取新的行动。

“AGPL 不是真正的开源许可,X 才是”:AGPL 是获得 OSI 批准的许可,并且被广泛采用。例如,MongoDB 曾经使用 AGPL,Grafana 现在也是 AGPL。这表明 AGPL 并不影响使用或流行度。我们选择 AGPL 是因为我们认为这是与 OSI 一起为世界开辟更多开源道路的最佳方式,而不是减少开源。

“Elastic 更改许可是因为他们表现不好”:我要说的是,我今天对 Elastic 的未来依然充满期待。我为我们的产品和团队的执行力感到无比自豪。我们发布了无状态的 Elasticsearch ES|QL 和大量用于 GenAI 用例的向量数据库/混合搜索改进。我们在日志记录和可观察性方面大力投入 OTel。我们的安全产品 SIEM 不断添加令人惊叹的功能,并且是市场上增长最快的产品之一。用户的反应让我们感到非常谦卑。股市总有起伏,但我可以向你保证,我们始终着眼于长远发展,而这次的变更就是其中的一部分。

如果我们看到更多问题,会在上面继续添加,以期减少混淆。

[HUMBLE.] 为未来而构建真是令人兴奋。Elasticsearch 回归开源。万岁!这真是一件美妙的事情。今天真是美好的一天。

Forever :elasticheart: Open Source

Shay 2024-08-30


原文地址:https://www.elastic.co/blog/elasticsearch-is-open-source-again/

社区热评

Elasticsearch 再次回归开源的消息迅速引发了技术社区的广泛关注。这不仅是 Elastic 对自身开源信念的重申,也是其在激烈市场竞争中精心策划的一次战略调整。

三年前,Elastic 因与 AWS 的市场竞争而选择更改许可协议,这一决定在当时引发了不小的争议。尽管如此,事实证明,这一策略有效地减少了市场上的混淆,也为 Elastic 与 AWS 的合作奠定了更坚实的基础。如今,Elastic 再度选择开源,并新增 AGPL 作为许可选项,这一举措无疑展现了 Elastic 在市场中更加成熟的定位和对未来发展的自信。

这一变化不仅仅是一个公司的商业决策,更是开源生态系统的一次重要信号。Elastic 的回归开源,传递出一个明确的信息:即使在商业竞争中,开源仍然是企业实现长远发展的重要路径。随着这一决定的落地,其他软件公司可能也会重新审视自身的许可策略,推动更多开源项目的发展与创新。

此外,Elastic 选择 AGPL 作为新许可选项,也显示出其对开源生态未来走向的深刻洞察。AGPL 的引入,表明 Elastic 希望在开源社区中保持灵活性和多样性,同时推动整个行业向更加开放和透明的方向迈进。

总体而言,Elastic 重返开源的举动,不仅意在巩固其在开源社区中的地位,也为行业树立了一个新的标杆。这一事件无疑将成为开源软件发展史上的重要篇章,未来可能会激发更多企业重新考虑其开源战略,进而推动整个技术行业的进一步繁荣与进步。

让我们拭目以待!

继续阅读 »

今日快讯!就在刚刚,开源搜索领域行业巨头 Elastic 官方博客发表了一篇最新公告《Elasticsearch is Open Source, Again》,Elastic 创始人& CTO Shay Banon 宣布 Elasticsearch 和 Kibana 许可证协议修改为 AGPL。

original-elastic-logos.png

以下为搜索客社区从 Elastic 官方博客翻译的原文内容:


Elasticsearch 再次成为开源软件

[D.N.A] Elasticsearch 和 Kibana 现在可以再次被称为开源软件了。这句话让我感到无比的兴奋。真的忍不住跳起来庆祝!我们所有在 Elastic 的人都很高兴。开源精神是我的DNA,也是 Elastic 的DNA。能够再次称 Elasticsearch 为开源软件,真的是一种纯粹的快乐。

[LOVE.] 简而言之,我们将在接下来的几周内,除了 ELv2 和 SSPL 之外,增加 AGPL 作为另一个许可选项。在更改许可后,我们从未停止过像一个开源社区一样相信和行动。但通过使用 AGPL 这一获得开放源码促进会(OSI)批准的许可,消除了人们可能存在的任何疑问或混淆。

[Not Like Us] 我们在 Elastic 从未停止过对开源的信仰。我个人对开源的信仰也从未动摇,至今已有 25 年了。那么为什么三年前我们要做出改变呢?我们遇到了与 AWS 相关的问题,以及他们的服务引发的市场混乱。在尝试了所有能想到的其他选项后,我们更改了许可协议,明知道这会导致 Elasticsearch 被分叉成另一个名称并走上不同的发展轨迹。这是一个漫长的故事。

[Like That] 好消息是,虽然过程痛苦,但结果奏效了。三年后,亚马逊已经完全投入到了他们的分叉项目中,市场的混乱(大部分)得到了缓解,我们与 AWS 的合作伙伴关系比以往更强。我们甚至被评为 AWS 的年度合作伙伴。我一直希望时间能过去得足够久,以至于我们可以安全地回到开源项目的状态——现在终于到了。

[All The Stars] 我们希望尽可能简化用户的使用体验。我们有用户非常喜欢 ELv2(一个受 BSD 启发的许可)。我们也有用户已经批准使用 SSPL(通过 MongoDB 使用)。这就是为什么我们只是增加了一个选项,而不是移除任何东西。如果你已经在使用并喜欢 Elasticsearch,请继续使用,没有任何变化。对于其他人,现在你也可以选择使用 AGPL。

[LOYALTY.] 我们选择 AGPL 而不是其他许可,是因为我们希望通过与 OSI 的合作,能在开源许可领域创造更多的选项。随着我们更改许可以来的发展(例如 Grafana 从 Apache2 转移到 AGPL),也许 AGPL 已经足够适用于像我们这样的基础设施软件了。我们致力于找到最合适的解决方案。

[euphoria] 我非常高兴能够再次称 Elasticsearch 为开源软件。

[Alright] 任何改变都可能引发混淆,当然也可能引来一些网络喷子。(网络喷子总是存在的,对吧?)让我们愉快地回答一些可能出现的问题吧。我可以想象到的一些问题如下,但我们会继续补充。

“更改许可是个错误,Elastic 现在在回撤”:我们在三年前更改许可时消除了很多市场混乱。由于我们的行动,很多事情已经改变。现在是一个完全不同的市场环境。我们不生活在过去。我们希望为用户打造一个更好的未来。正是因为我们当时采取了行动,现在我们才有能力采取新的行动。

“AGPL 不是真正的开源许可,X 才是”:AGPL 是获得 OSI 批准的许可,并且被广泛采用。例如,MongoDB 曾经使用 AGPL,Grafana 现在也是 AGPL。这表明 AGPL 并不影响使用或流行度。我们选择 AGPL 是因为我们认为这是与 OSI 一起为世界开辟更多开源道路的最佳方式,而不是减少开源。

“Elastic 更改许可是因为他们表现不好”:我要说的是,我今天对 Elastic 的未来依然充满期待。我为我们的产品和团队的执行力感到无比自豪。我们发布了无状态的 Elasticsearch ES|QL 和大量用于 GenAI 用例的向量数据库/混合搜索改进。我们在日志记录和可观察性方面大力投入 OTel。我们的安全产品 SIEM 不断添加令人惊叹的功能,并且是市场上增长最快的产品之一。用户的反应让我们感到非常谦卑。股市总有起伏,但我可以向你保证,我们始终着眼于长远发展,而这次的变更就是其中的一部分。

如果我们看到更多问题,会在上面继续添加,以期减少混淆。

[HUMBLE.] 为未来而构建真是令人兴奋。Elasticsearch 回归开源。万岁!这真是一件美妙的事情。今天真是美好的一天。

Forever :elasticheart: Open Source

Shay 2024-08-30


原文地址:https://www.elastic.co/blog/elasticsearch-is-open-source-again/

社区热评

Elasticsearch 再次回归开源的消息迅速引发了技术社区的广泛关注。这不仅是 Elastic 对自身开源信念的重申,也是其在激烈市场竞争中精心策划的一次战略调整。

三年前,Elastic 因与 AWS 的市场竞争而选择更改许可协议,这一决定在当时引发了不小的争议。尽管如此,事实证明,这一策略有效地减少了市场上的混淆,也为 Elastic 与 AWS 的合作奠定了更坚实的基础。如今,Elastic 再度选择开源,并新增 AGPL 作为许可选项,这一举措无疑展现了 Elastic 在市场中更加成熟的定位和对未来发展的自信。

这一变化不仅仅是一个公司的商业决策,更是开源生态系统的一次重要信号。Elastic 的回归开源,传递出一个明确的信息:即使在商业竞争中,开源仍然是企业实现长远发展的重要路径。随着这一决定的落地,其他软件公司可能也会重新审视自身的许可策略,推动更多开源项目的发展与创新。

此外,Elastic 选择 AGPL 作为新许可选项,也显示出其对开源生态未来走向的深刻洞察。AGPL 的引入,表明 Elastic 希望在开源社区中保持灵活性和多样性,同时推动整个行业向更加开放和透明的方向迈进。

总体而言,Elastic 重返开源的举动,不仅意在巩固其在开源社区中的地位,也为行业树立了一个新的标杆。这一事件无疑将成为开源软件发展史上的重要篇章,未来可能会激发更多企业重新考虑其开源战略,进而推动整个技术行业的进一步繁荣与进步。

让我们拭目以待!

收起阅读 »

【第3期】2024 搜索客 Meetup | Elasticsearch 的代码结构和写入查询流程的解读 - 下篇

本次活动由 搜索客社区、极限科技(INFINI Labs)联合举办,活动主题将深入探讨 Elasticsearch 的两个核心方面:代码结构以及写入和查询的关键流程。本次活动将为 Elasticsearch 初学者和有经验的用户提供宝贵的见解,欢迎大家报名参加、交流学习。

活动主题:Elasticsearch 的代码结构和写入查询流程的解读 - 下篇
活动时间:2024 年 8 月 28 日 19:00-20:00(周三)
活动形式:微信视频号(极限实验室)直播
报名方式:关注或扫码海报中的二维码进行预约

嘉宾介绍

张磊,极限科技搜索引擎研发负责人,对 Elasticsearch 和 Lucene 源码比较熟悉,目前主要负责公司的 Easysearch 产品的研发以及客户服务工作。

主题摘要

本次分享将探讨 Elasticsearch 的代码结构及其写入和查询流程。内容包括:项目架构、核心模块、插件系统,以及文档索引和查询的各个阶段与分布式查询协调。

活动亮点

  1. 深入解析 Elasticsearch 代码结构

    • 项目的整体结构:了解 Elasticsearch 项目的组织方式。
    • 核心模块及其职责:学习 Elasticsearch 的核心模块及其在系统中的具体角色。
    • 插件系统的设计:探索 Elasticsearch 灵活的插件系统设计及其扩展方式。
  2. 详细解读 Elasticsearch 写入和查询流程

    • 文档索引过程的各个阶段:跟随文档从初始接收至最终存储的索引过程。
    • 查询解析和执行的步骤:理解 Elasticsearch 中查询解析和执行的各个步骤。
    • 分布式查询的协调过程:学习 Elasticsearch 如何在分布式架构中协调查询,以提供高效且准确的搜索结果。

参与有奖

直播中将设有福袋抽奖环节,参与就有机会获得 INFINI Labs 周边纪念品,包括 T 恤、鸭舌帽、咖啡杯、指甲刀套件等等(图片仅供参考,款式、颜色与尺码随机)。

活动交流

本活动设有 Meetup 技术交流群,可添加小助手微信入群。

本次 Meetup 是深入了解 Elasticsearch 内部工作机制、提升使用技能的绝佳机会。不要错过!

Meetup 讲师招募

搜索客社区 Meetup 的成功举办,离不开社区小伙伴的热情参与。目前社区讲师招募计划也在持续进行中,我们诚挚邀请各位技术大咖、行业精英踊跃提交演讲议题,与大家分享您的经验。

讲师报名链接:http://cfp.searchkit.cn
或扫描下方二维码,立刻报名成为讲师!

Meetup 活动聚焦 AI 与搜索领域的最新动态,以及数据实时搜索分析、向量检索、技术实践与案例分析、日志分析、安全等领域的深度探讨。

我们热切期待您的精彩分享!

往期回顾

关于 搜索客(SearchKit)社区

搜索客社区由 Elasticsearch 中文社区进行全新的品牌升级,以新的 Slogan:“搜索人自己的社区” 为宣言。汇集搜索领域最新动态、精选干货文章、精华讨论、文档资料、翻译与版本发布等,为广大搜索领域从业者提供更为丰富便捷的学习和交流平台。

社区官网:https://searchkit.cn

继续阅读 »

本次活动由 搜索客社区、极限科技(INFINI Labs)联合举办,活动主题将深入探讨 Elasticsearch 的两个核心方面:代码结构以及写入和查询的关键流程。本次活动将为 Elasticsearch 初学者和有经验的用户提供宝贵的见解,欢迎大家报名参加、交流学习。

活动主题:Elasticsearch 的代码结构和写入查询流程的解读 - 下篇
活动时间:2024 年 8 月 28 日 19:00-20:00(周三)
活动形式:微信视频号(极限实验室)直播
报名方式:关注或扫码海报中的二维码进行预约

嘉宾介绍

张磊,极限科技搜索引擎研发负责人,对 Elasticsearch 和 Lucene 源码比较熟悉,目前主要负责公司的 Easysearch 产品的研发以及客户服务工作。

主题摘要

本次分享将探讨 Elasticsearch 的代码结构及其写入和查询流程。内容包括:项目架构、核心模块、插件系统,以及文档索引和查询的各个阶段与分布式查询协调。

活动亮点

  1. 深入解析 Elasticsearch 代码结构

    • 项目的整体结构:了解 Elasticsearch 项目的组织方式。
    • 核心模块及其职责:学习 Elasticsearch 的核心模块及其在系统中的具体角色。
    • 插件系统的设计:探索 Elasticsearch 灵活的插件系统设计及其扩展方式。
  2. 详细解读 Elasticsearch 写入和查询流程

    • 文档索引过程的各个阶段:跟随文档从初始接收至最终存储的索引过程。
    • 查询解析和执行的步骤:理解 Elasticsearch 中查询解析和执行的各个步骤。
    • 分布式查询的协调过程:学习 Elasticsearch 如何在分布式架构中协调查询,以提供高效且准确的搜索结果。

参与有奖

直播中将设有福袋抽奖环节,参与就有机会获得 INFINI Labs 周边纪念品,包括 T 恤、鸭舌帽、咖啡杯、指甲刀套件等等(图片仅供参考,款式、颜色与尺码随机)。

活动交流

本活动设有 Meetup 技术交流群,可添加小助手微信入群。

本次 Meetup 是深入了解 Elasticsearch 内部工作机制、提升使用技能的绝佳机会。不要错过!

Meetup 讲师招募

搜索客社区 Meetup 的成功举办,离不开社区小伙伴的热情参与。目前社区讲师招募计划也在持续进行中,我们诚挚邀请各位技术大咖、行业精英踊跃提交演讲议题,与大家分享您的经验。

讲师报名链接:http://cfp.searchkit.cn
或扫描下方二维码,立刻报名成为讲师!

Meetup 活动聚焦 AI 与搜索领域的最新动态,以及数据实时搜索分析、向量检索、技术实践与案例分析、日志分析、安全等领域的深度探讨。

我们热切期待您的精彩分享!

往期回顾

关于 搜索客(SearchKit)社区

搜索客社区由 Elasticsearch 中文社区进行全新的品牌升级,以新的 Slogan:“搜索人自己的社区” 为宣言。汇集搜索领域最新动态、精选干货文章、精华讨论、文档资料、翻译与版本发布等,为广大搜索领域从业者提供更为丰富便捷的学习和交流平台。

社区官网:https://searchkit.cn

收起阅读 »

Elasticsearch 磁盘空间异常:一次成功的故障排除案例分享

故障现象

近日有客户找到我们,说有个 ES 集群节点,磁盘利用率达到了 82% ,而其节点才 63% ,想处理下这个节点,降低节点的磁盘利用率。

起初以为是没有打开自动平衡导致的,经查询,数据还是比较平衡的。 利用率较高的是 76 节点,如果 76 节点的分片比其他节点多,好像还比较合乎逻辑,但它反而比其他节点少了 12-15 个分片。那是 76 节点上的分片比较大?

索引情况

图中都是较大的索引,1 个索引 25TB 左右,共 160 个分片。

分片大小

节点 64 节点 77 节点 75 问题节点 76 可以看出分片大小没有出现较大的倾斜,分片大小和数据平衡的原因都被排除。

换个方向思考,节点 76 比其他节点多使用了磁盘空间 8 个 TB 左右,集群最大分片大小约 140GB ,8000/140=57 ,即节点 76 至少要比其他节点多 57 个分片才行,啊这...

会不会有其他的文件占用了磁盘空间?

我们登录到节点主机,排查是否有其他文件占用了磁盘空间。

结果:客户的数据路径是单独的数据磁盘,并没有其他文件,都是 ES 集群索引占用的空间。

现象总结

分片大小差不多的情况下,节点 76 的分片数还比别的节点还少 10 个左右,它的磁盘空间反而多占用了 8TB 。

这是不是太奇怪了?事出反常必有妖,继续往下查。

原因定位

通过进一步排查,我们发现节点 76 上有一批索引目录,在其他的节点上没有,而且也不在 GET \_cat/indices?v 命令的结果中。说明这些目录都是 dangling 索引占用的。

dangling 索引产生的原因

当 Elasticsearch 节点脱机时,如果删除的索引数量超过 Cluster.indes.tombstones.size,就会发生这种情况。

解决方案

通过命令删除 dangling 索引:

DELETE /\_dangling/<index-uuid>?accept_data_loss=true

最后

这次的分享就到这里了,欢迎与我一起交流 ES 的各种问题和解决方案。

关于极限科技(INFINI Labs)

INFINI Labs

极限科技,全称极限数据(北京)科技有限公司,是一家专注于实时搜索与数据分析的软件公司。旗下品牌极限实验室(INFINI Labs)致力于打造极致易用的数据探索与分析体验。

极限科技是一支年轻的团队,采用天然分布式的方式来进行远程协作,员工分布在全球各地,希望通过努力成为中国乃至全球企业大数据实时搜索分析产品的首选,为中国技术品牌输出添砖加瓦。

官网:https://infinilabs.cn

继续阅读 »

故障现象

近日有客户找到我们,说有个 ES 集群节点,磁盘利用率达到了 82% ,而其节点才 63% ,想处理下这个节点,降低节点的磁盘利用率。

起初以为是没有打开自动平衡导致的,经查询,数据还是比较平衡的。 利用率较高的是 76 节点,如果 76 节点的分片比其他节点多,好像还比较合乎逻辑,但它反而比其他节点少了 12-15 个分片。那是 76 节点上的分片比较大?

索引情况

图中都是较大的索引,1 个索引 25TB 左右,共 160 个分片。

分片大小

节点 64 节点 77 节点 75 问题节点 76 可以看出分片大小没有出现较大的倾斜,分片大小和数据平衡的原因都被排除。

换个方向思考,节点 76 比其他节点多使用了磁盘空间 8 个 TB 左右,集群最大分片大小约 140GB ,8000/140=57 ,即节点 76 至少要比其他节点多 57 个分片才行,啊这...

会不会有其他的文件占用了磁盘空间?

我们登录到节点主机,排查是否有其他文件占用了磁盘空间。

结果:客户的数据路径是单独的数据磁盘,并没有其他文件,都是 ES 集群索引占用的空间。

现象总结

分片大小差不多的情况下,节点 76 的分片数还比别的节点还少 10 个左右,它的磁盘空间反而多占用了 8TB 。

这是不是太奇怪了?事出反常必有妖,继续往下查。

原因定位

通过进一步排查,我们发现节点 76 上有一批索引目录,在其他的节点上没有,而且也不在 GET \_cat/indices?v 命令的结果中。说明这些目录都是 dangling 索引占用的。

dangling 索引产生的原因

当 Elasticsearch 节点脱机时,如果删除的索引数量超过 Cluster.indes.tombstones.size,就会发生这种情况。

解决方案

通过命令删除 dangling 索引:

DELETE /\_dangling/<index-uuid>?accept_data_loss=true

最后

这次的分享就到这里了,欢迎与我一起交流 ES 的各种问题和解决方案。

关于极限科技(INFINI Labs)

INFINI Labs

极限科技,全称极限数据(北京)科技有限公司,是一家专注于实时搜索与数据分析的软件公司。旗下品牌极限实验室(INFINI Labs)致力于打造极致易用的数据探索与分析体验。

极限科技是一支年轻的团队,采用天然分布式的方式来进行远程协作,员工分布在全球各地,希望通过努力成为中国乃至全球企业大数据实时搜索分析产品的首选,为中国技术品牌输出添砖加瓦。

官网:https://infinilabs.cn

收起阅读 »

构建Elasticsearch专家Bot的详细步骤指南

构建Elasticsearch专家Bot的详细步骤指南

步骤1: 文档搜集

  • 利用专业工具搜集Elasticsearch 8.13.2版本的官方文档,确保文档的完整性和准确性。如:Elasticsearch文档

步骤2: 知识库建立

  • 在coze.cn平台上创建一个专门的知识库,命名清晰,便于管理和识别。

步骤3: 文档上传

  • 将搜集到的Elasticsearch文档上传至新创建的知识库,确保文档格式适合后续的检索和分析。

步骤4: Bot创建

  • 在coze.cn上创建一个新的Bot,命名为“Elasticsearch专家”,为其设定一个专业且引人注目的形象。

步骤5: 知识库配置

  • 将步骤2中的知识库与新创建的Bot进行关联,确保Bot能够访问和利用这些文档资源。

步骤6: 功能插件集成

  • 为Bot添加以下功能插件,以提供更全面的服务:
    • 必应搜索引擎(Bing Web Search):扩展信息检索范围。
    • 代码执行器(CodeRunner):实现代码的即时测试与验证。
    • 微信搜索(WeChat Search):增加中文信息源的覆盖。

步骤7: 人设与回复逻辑定制

  • 设定Bot的人设,明确其专业领域和能力,如:“我是Elasticsearch的专家,随时准备解答你的疑问。”
  • 利用coze平台的AI技术,优化Bot的回复逻辑,确保其回答既准确又具有针对性。

步骤8: 测试与调整

  • 在Bot设置完成后,进行全面的测试,确保其能够正确理解和回应各种查询。
  • 根据测试反馈,调整Bot的交互逻辑和回答内容,以提高用户满意度。

步骤9: 发布与分享

  • 完成所有设置和测试后,点击发布,使Bot正式上线。
  • 通过Bot页面的商店功能,将你的“Elasticsearch专家”Bot分享给你的伙伴们,让他们也能享受到这一强大的学习工具。

步骤10: 持续优化与更新

  • 定期回顾Bot的表现,根据用户反馈进行持续的优化和功能更新。
  • 随着Elasticsearch版本的迭代,及时更新知识库内容,确保Bot提供的信息始终最新。

通过遵循这些步骤,你不仅能够构建一个功能全面的Elasticsearch专家Bot,而且能够确保它随着时间的推移不断进化,满足用户日益增长的需求。这将是一个不仅能提供文档查询,还能执行代码和搜索网络的智能助手,极大地提升你的Elasticsearch学习之旅。

继续阅读 »

构建Elasticsearch专家Bot的详细步骤指南

步骤1: 文档搜集

  • 利用专业工具搜集Elasticsearch 8.13.2版本的官方文档,确保文档的完整性和准确性。如:Elasticsearch文档

步骤2: 知识库建立

  • 在coze.cn平台上创建一个专门的知识库,命名清晰,便于管理和识别。

步骤3: 文档上传

  • 将搜集到的Elasticsearch文档上传至新创建的知识库,确保文档格式适合后续的检索和分析。

步骤4: Bot创建

  • 在coze.cn上创建一个新的Bot,命名为“Elasticsearch专家”,为其设定一个专业且引人注目的形象。

步骤5: 知识库配置

  • 将步骤2中的知识库与新创建的Bot进行关联,确保Bot能够访问和利用这些文档资源。

步骤6: 功能插件集成

  • 为Bot添加以下功能插件,以提供更全面的服务:
    • 必应搜索引擎(Bing Web Search):扩展信息检索范围。
    • 代码执行器(CodeRunner):实现代码的即时测试与验证。
    • 微信搜索(WeChat Search):增加中文信息源的覆盖。

步骤7: 人设与回复逻辑定制

  • 设定Bot的人设,明确其专业领域和能力,如:“我是Elasticsearch的专家,随时准备解答你的疑问。”
  • 利用coze平台的AI技术,优化Bot的回复逻辑,确保其回答既准确又具有针对性。

步骤8: 测试与调整

  • 在Bot设置完成后,进行全面的测试,确保其能够正确理解和回应各种查询。
  • 根据测试反馈,调整Bot的交互逻辑和回答内容,以提高用户满意度。

步骤9: 发布与分享

  • 完成所有设置和测试后,点击发布,使Bot正式上线。
  • 通过Bot页面的商店功能,将你的“Elasticsearch专家”Bot分享给你的伙伴们,让他们也能享受到这一强大的学习工具。

步骤10: 持续优化与更新

  • 定期回顾Bot的表现,根据用户反馈进行持续的优化和功能更新。
  • 随着Elasticsearch版本的迭代,及时更新知识库内容,确保Bot提供的信息始终最新。

通过遵循这些步骤,你不仅能够构建一个功能全面的Elasticsearch专家Bot,而且能够确保它随着时间的推移不断进化,满足用户日益增长的需求。这将是一个不仅能提供文档查询,还能执行代码和搜索网络的智能助手,极大地提升你的Elasticsearch学习之旅。

收起阅读 »

极限网关助力好未来 Elasticsearch 容器化升级

极限网关在好未来的最佳实践案例,轻松扛住日增百 TB 数据的流量,助力 ES 从物理机到云原生架构的改造,实现了流控、请求分析、安全管理、无缝迁移等场景。一次完美的客户体验~

背景

物理机架构时代

2022 年,好未来整个日志 Elasticsearch 拥有数十套服务集群,几百台物理机。这么多台机器耗费成本非常高,而且还要花费很大精力去维护。在人力资源有限情况下,存在非常多的弊端,运行成本高,不仅是机器折旧还有机柜等费用。

流量特征

这是来自某个业务线,如下图 1,真实流量,潮汐性非常明显。好未来有很多条业务线,几乎跟这个趋势都一致的,除了个别业务有“续报”、“开课”等活动特殊情况。潮汐性带来的问题就是高峰期 CPU、内存资源是可以消耗很高;低峰期资源使用量非常低,由于是物理架构,这些资源无法给其他业务线共享。

图1

图1

降本增效-容器化改造原动力

日志服务对成本的空前的压力促使我们推进 Elasticsearch 进行架构改造;如何改造,改造成什么样子,这两个问题一直是推进改造原动力。业界能够同时对水平扩展和垂直扩展就是 K8S,我们开始对 Elasticsearch 改造成能在 K8S 上运行进行探索,从而提升 CPU、内存利用率。

物理机时代,没办法把资源动态的扩缩,动态调配,资源隔离,单靠人力操作调度成本太高,几乎无法完成;集群对内存资源需求要比 CPU 资源大很多,由于机器型号配置是固定的,无法“定制”,这也会导致成本居高不下。所以,无论从那个方面来讲,容器化优势非常明显,既能够优化成本,也能够降低运维复杂度。

ES 容器化改造

进行架构升级重点难点- API 服务

改造过程,我们遇到了很多问题,比如容器 ES 版本和物理机 ES 版本不一致,如何让 ES API 能够兼容不同的 ES 版本,由于版本的不兼容,导致无法直接使用原有的 tribenode 进行服务,怎么提供一个高可用的 Elasticsearch API 服务。我们考虑到多个方面,比如使用官方推荐的 proxy 模式、第三方服务等进行选择,经过多方面对比,选择了极限网关 进行 tribenode 替换。

原始 ES API 服务痛点

  • API 访问没有流量控制
  • 可观测性差,而且稳定性一般
  • 版本兼容性差

物理机时代 API 架构

在物理机时代 ES 集群,API 架构如图 2,可以明显看到 tribe node 对所有 ES 集群的“侵入性”是非常大的,这就带来了很多问题,比较严重的就是单个集群对 ES tribenode 的影响和版本升级带来的不兼容问题。

图2

图2

混合时代 API 架构

通过图 3,我们可以看到,极限网关对于版本兼容性很好,能够适配不同的版本。因此,最终选择极限网关作为下一代 ES API 服务方。

图3

图3

里程碑:全部 ES 集群容器化

在 2023 年 3 月份,通过 Elastic 官方 ECK 模式,完成全部日志 ES 集群容器化改造,拥有数百节点,1PB+ 数据存储,每日新增数据 100T 左右。紧接着,除了日志服务外,同时支持了好未来多条业务线。

图4

图4

极限网关实践

下面主要讲述了,为什么选择极限网关,以及极限网关在好未来落地、应用这些内容。

为什么选择极限网关?

学习成本低

我们可以从文档中看到极限网关,其架构简洁,语法简单,直观易懂。学习成本比较低,上手非常快,对新手友好。

性能强悍

经过压测,发现极限网关速度非常快,且针对 Elasticsearch 做了非常细致的优化,能成倍提升写入和查询的速度。

安全性高

支持多种认证方式,最简单的账号密码认证,可以给自定义多个账户密码,大大简化了 Elasticsearch 的安全设置,同时,还可以支持 LDAP 安全验证。

跨版本支持

我们容器化改造过程需要兼容不同版本的 Elasticsrearch,极限网关针对不同的 Elasticsearch 版本做了兼容和针对性处理,能够让业务代码无缝的进行适配,后端 Elasticsearch 集群版本升级能够做到无缝过渡,降低版本升级和数据迁移的复杂度,非常匹配我们的业务场景。

灵活可扩展

可灵活对每个请求进行干预和路由,支持路由的智能学习,内置丰富的过滤器,通过配置动态修改每个请求的处理逻辑,也支持通过插件来进行扩展,满足我们对流量的控制,尤其是限流、用户、IP 等这些功能非常实用。

启用安全策略-为 API 服务保驾护航

痛点

在升级之前使用 tribe 作为 API 服务提供后端,几乎相当于裸奔,没有任何认证策略;另外,tribe 本身的稳定性也有问题,官方在新版本逐渐废弃这种 CCS(跨集群搜索),期间出现多次服务崩溃。

极限网关解决问题

极限网关通过,“basic_auth” 插件,提供最基本的安全校验,使用起来非常方便;同时,极限网关提供 LDAP 插件,可以接入公共的 LDAP 服务,对所有的访问用户进行校验,安全策略对所有的用户生效,不用担心因为 IP 问题泄漏数据等。

强大的过滤功能

在使用 ES 集群过程中,许多场景,需要对请求进行控制、限制等操作。在这方便,感受到了极限网关强大的产品力。比如下面的两个场景

对异常流量进行限流

  • 支持对 IP 限流
  • 支持对 hostname 限流
  • 支持 header 限流

对异常用户进行封禁

当 Elasticsearch 是通过 Basic Auth 或者 LDAP 方式来进行身份认证的时候,request_user_filter 过滤器可用来按请求的用户名信息来进行过滤。操作起来也非常简单,只需要 request_user_filter 这一个过滤器。

- request_user_filter:
    include:
        - "elastic"
    exclude:
        - "Ryan"

总结来讲,主要有这些方面的功能:

图5

图5

优秀的可观测性

痛点

改造前经常为看不到直观的数据指标感到头疼,查看指标需要多个地方同时打开,去筛选,查找,非常繁琐,付出的成本非常大。为此,大家都再考虑如何优化这种情况,无奈优先级比较低,一直没有真正的投入时间去优化这块。

完美解决

使用了极限网关,通过收集请求日志,非常清晰的收集到想要的数据,具体如下:

  • 总体方面:
    • 流量曲线
    • 状态码占比
    • 缓存统计
    • 每台网关请求流量
  • 细节方面:
    • 打印每次请求语句
    • 可以查看请求到具体 ES 节点流量
    • 可以查看过滤器的列表

通过下图,我们可以从管理视角直观的看到各种信息,这对于管理员来讲,省时省力,方便快捷。

图6

图6

意外收获:无缝迁移业务 Elasticsearch 上云

由于前期日志业务上云,受到非常好的反馈,多个业务线期望能够上云上服务,达到降本增效的目的。

支持双写

数据可以通过极限网关同时写入两个 ES 集群,能够保障数据完全一致,安全可靠。

无缝切换

切换很丝滑,影响非常小,能够让外界几乎感受不到服务波动。

图7

图7

通过使用极限网关,自建 ES 集群可以无缝的迁移上云,在整个迁移的过程中,两套集群通过网关进行了解耦,在迁移的过程中还能实现版本的无缝升级,极大降低了迁移成本,提高迁移效率,多次验证服务稳定可靠。

极限网关流量概览

这是其中一套极限网关的流量统计。用这部分数据进行巡检,一目了然,做到全局的掌控,提高感知力度。

图8

图8

极限网关使用总结

极限网关提供一系列高性能和高可靠性的网关服务。使用这样的服务给我们带来以下好处:

  1. 可观测性好:极限网关可以动态的对 Elasticsearch 运行过程中请求进行拦截和分析,通过指标和日志来了解集群运行状态,这些指标可以用于提升性能和业务优化。
  2. 增强安全性:包含先进的安全机制,如 basicauth、LDAP 等支持,保护用户数据不受未授权访问和各种网络威胁的侵害。
  3. 高稳定性:通过冗余设计和故障转移机制,极限网关能够确保网络服务的高可用性,即使在某些组件发生故障时也能保持服务不中断,单版本最长服务超过 15 个月。
  4. 易于管理:通过提供 INFINI Console 简洁直观的管理界面,让用户能够轻松配置和监控网络状态,提升管理效率。
  5. 客户支持:良好的客户服务支持可以帮助用户快速解决使用过程中遇到的问题,提供专业的技术指导。

综上所述,极限网关为用户提供了一个高速、安全、稳定且易于管理的 ES 网关,适合对网络性能有较高要求的个人和企业用户。

未来规划

第一阶段,完成了日志 ES 集群,所有集群的容器化改造,合并,成功的把成本降低了 60%以上。这期间积累了丰富容器化经验,为业务 ES 集群上容器做了良好的铺垫;成本优势和运维优势吸引越来越多的业务接入到容器化 ES 集群。

提升 ES 集群效能--新技术应用&&版本升级

  • 极限科技官方推荐的 Easysearch 在压缩率,查询速度等等方面有很多的优势,通过长时间的测试稳定性,新特性,对比云原生的 ES 集群,根据测试结果,给“客户”提供多种选择,这也是工作重点之一。
  • 我们当前使用的 ES 版本是 6.8,已经远远落后于官方版本,今年我们计划在选择合适的集群升级 ES 版本,拥抱更多官方提供的特性。

混合(多)云架构支持

随着越来越多的 ES 集群在机房的 K8S 集群部署,这里资源出现了紧张局面。 我们尝试在云上部署自建 ES 集群,弥补机房资源有限,无法大规模扩容,同时能够支持多活场景,满足更多客户的不同需求。混合云主要实现以下几种能力:

1、扩缩容:满足不同业务灵活适配

混合(多)云部署,可以让负载内部私有云 ES,同时部署到公有云,提升扩展 IT 基础设施不仅局限于 CPU、内存,还有存储。比如某一个业务要做活动,预估流量“大爆发”,需要提前准备大规模资源,在机房内根本来不及采购扩容支持,然而在公有云上就能很方便扩容、缩容。在云上搭建 ES 集群,设置满足需求的数量、容量、配置,配合极限网关路由策略,精准的把控流量流向。

图9

图9

2、灾备:紧急情况快速部署,恢复 ES 集群读写

当机房级别大规模故障,部分业务实现了多活,单一的机房故障不会影响其服务能力,而此时比如日志查看等仍有需求,为了满足这部分“客户”需求,可以在云上 K8S 集群,快速搭建 ES 集群,恢复日志读写功能。

图10

图10

参考文档:

作者:张华勋,前新浪 CDN 研发,工作主要涉及 Mysql、MongoDB、Redis、Elasticsearch、流量调度等组件和系统,以及运维自动化、平台化等工作。现就职于好未来。

关于好未来

好未来(NYSE:TAL)是一家以内容能力与科技能力为基础,以科教、科创、科普为战略方向,助力人的终身成长,并持续探索创新的科技公司。 好未来的前身学而思成立于 2003 年,2010 年在美国纽交所正式挂牌交易。好未来以“爱与科技助力终身成长”为使命,致力成为持续创新的组织。更多参见:https://www.100tal.com/

关于极限科技(INFINI Labs)

INFINI Labs

极限科技,全称极限数据(北京)科技有限公司,是一家专注于实时搜索与数据分析的软件公司。旗下品牌极限实验室(INFINI Labs)致力于打造极致易用的数据探索与分析体验。

极限科技是一支年轻的团队,采用天然分布式的方式来进行远程协作,员工分布在全球各地,希望通过努力成为中国乃至全球企业大数据实时搜索分析产品的首选,为中国技术品牌输出添砖加瓦。

官网:https://www.infinilabs.cn

联系我们

继续阅读 »

极限网关在好未来的最佳实践案例,轻松扛住日增百 TB 数据的流量,助力 ES 从物理机到云原生架构的改造,实现了流控、请求分析、安全管理、无缝迁移等场景。一次完美的客户体验~

背景

物理机架构时代

2022 年,好未来整个日志 Elasticsearch 拥有数十套服务集群,几百台物理机。这么多台机器耗费成本非常高,而且还要花费很大精力去维护。在人力资源有限情况下,存在非常多的弊端,运行成本高,不仅是机器折旧还有机柜等费用。

流量特征

这是来自某个业务线,如下图 1,真实流量,潮汐性非常明显。好未来有很多条业务线,几乎跟这个趋势都一致的,除了个别业务有“续报”、“开课”等活动特殊情况。潮汐性带来的问题就是高峰期 CPU、内存资源是可以消耗很高;低峰期资源使用量非常低,由于是物理架构,这些资源无法给其他业务线共享。

图1

图1

降本增效-容器化改造原动力

日志服务对成本的空前的压力促使我们推进 Elasticsearch 进行架构改造;如何改造,改造成什么样子,这两个问题一直是推进改造原动力。业界能够同时对水平扩展和垂直扩展就是 K8S,我们开始对 Elasticsearch 改造成能在 K8S 上运行进行探索,从而提升 CPU、内存利用率。

物理机时代,没办法把资源动态的扩缩,动态调配,资源隔离,单靠人力操作调度成本太高,几乎无法完成;集群对内存资源需求要比 CPU 资源大很多,由于机器型号配置是固定的,无法“定制”,这也会导致成本居高不下。所以,无论从那个方面来讲,容器化优势非常明显,既能够优化成本,也能够降低运维复杂度。

ES 容器化改造

进行架构升级重点难点- API 服务

改造过程,我们遇到了很多问题,比如容器 ES 版本和物理机 ES 版本不一致,如何让 ES API 能够兼容不同的 ES 版本,由于版本的不兼容,导致无法直接使用原有的 tribenode 进行服务,怎么提供一个高可用的 Elasticsearch API 服务。我们考虑到多个方面,比如使用官方推荐的 proxy 模式、第三方服务等进行选择,经过多方面对比,选择了极限网关 进行 tribenode 替换。

原始 ES API 服务痛点

  • API 访问没有流量控制
  • 可观测性差,而且稳定性一般
  • 版本兼容性差

物理机时代 API 架构

在物理机时代 ES 集群,API 架构如图 2,可以明显看到 tribe node 对所有 ES 集群的“侵入性”是非常大的,这就带来了很多问题,比较严重的就是单个集群对 ES tribenode 的影响和版本升级带来的不兼容问题。

图2

图2

混合时代 API 架构

通过图 3,我们可以看到,极限网关对于版本兼容性很好,能够适配不同的版本。因此,最终选择极限网关作为下一代 ES API 服务方。

图3

图3

里程碑:全部 ES 集群容器化

在 2023 年 3 月份,通过 Elastic 官方 ECK 模式,完成全部日志 ES 集群容器化改造,拥有数百节点,1PB+ 数据存储,每日新增数据 100T 左右。紧接着,除了日志服务外,同时支持了好未来多条业务线。

图4

图4

极限网关实践

下面主要讲述了,为什么选择极限网关,以及极限网关在好未来落地、应用这些内容。

为什么选择极限网关?

学习成本低

我们可以从文档中看到极限网关,其架构简洁,语法简单,直观易懂。学习成本比较低,上手非常快,对新手友好。

性能强悍

经过压测,发现极限网关速度非常快,且针对 Elasticsearch 做了非常细致的优化,能成倍提升写入和查询的速度。

安全性高

支持多种认证方式,最简单的账号密码认证,可以给自定义多个账户密码,大大简化了 Elasticsearch 的安全设置,同时,还可以支持 LDAP 安全验证。

跨版本支持

我们容器化改造过程需要兼容不同版本的 Elasticsrearch,极限网关针对不同的 Elasticsearch 版本做了兼容和针对性处理,能够让业务代码无缝的进行适配,后端 Elasticsearch 集群版本升级能够做到无缝过渡,降低版本升级和数据迁移的复杂度,非常匹配我们的业务场景。

灵活可扩展

可灵活对每个请求进行干预和路由,支持路由的智能学习,内置丰富的过滤器,通过配置动态修改每个请求的处理逻辑,也支持通过插件来进行扩展,满足我们对流量的控制,尤其是限流、用户、IP 等这些功能非常实用。

启用安全策略-为 API 服务保驾护航

痛点

在升级之前使用 tribe 作为 API 服务提供后端,几乎相当于裸奔,没有任何认证策略;另外,tribe 本身的稳定性也有问题,官方在新版本逐渐废弃这种 CCS(跨集群搜索),期间出现多次服务崩溃。

极限网关解决问题

极限网关通过,“basic_auth” 插件,提供最基本的安全校验,使用起来非常方便;同时,极限网关提供 LDAP 插件,可以接入公共的 LDAP 服务,对所有的访问用户进行校验,安全策略对所有的用户生效,不用担心因为 IP 问题泄漏数据等。

强大的过滤功能

在使用 ES 集群过程中,许多场景,需要对请求进行控制、限制等操作。在这方便,感受到了极限网关强大的产品力。比如下面的两个场景

对异常流量进行限流

  • 支持对 IP 限流
  • 支持对 hostname 限流
  • 支持 header 限流

对异常用户进行封禁

当 Elasticsearch 是通过 Basic Auth 或者 LDAP 方式来进行身份认证的时候,request_user_filter 过滤器可用来按请求的用户名信息来进行过滤。操作起来也非常简单,只需要 request_user_filter 这一个过滤器。

- request_user_filter:
    include:
        - "elastic"
    exclude:
        - "Ryan"

总结来讲,主要有这些方面的功能:

图5

图5

优秀的可观测性

痛点

改造前经常为看不到直观的数据指标感到头疼,查看指标需要多个地方同时打开,去筛选,查找,非常繁琐,付出的成本非常大。为此,大家都再考虑如何优化这种情况,无奈优先级比较低,一直没有真正的投入时间去优化这块。

完美解决

使用了极限网关,通过收集请求日志,非常清晰的收集到想要的数据,具体如下:

  • 总体方面:
    • 流量曲线
    • 状态码占比
    • 缓存统计
    • 每台网关请求流量
  • 细节方面:
    • 打印每次请求语句
    • 可以查看请求到具体 ES 节点流量
    • 可以查看过滤器的列表

通过下图,我们可以从管理视角直观的看到各种信息,这对于管理员来讲,省时省力,方便快捷。

图6

图6

意外收获:无缝迁移业务 Elasticsearch 上云

由于前期日志业务上云,受到非常好的反馈,多个业务线期望能够上云上服务,达到降本增效的目的。

支持双写

数据可以通过极限网关同时写入两个 ES 集群,能够保障数据完全一致,安全可靠。

无缝切换

切换很丝滑,影响非常小,能够让外界几乎感受不到服务波动。

图7

图7

通过使用极限网关,自建 ES 集群可以无缝的迁移上云,在整个迁移的过程中,两套集群通过网关进行了解耦,在迁移的过程中还能实现版本的无缝升级,极大降低了迁移成本,提高迁移效率,多次验证服务稳定可靠。

极限网关流量概览

这是其中一套极限网关的流量统计。用这部分数据进行巡检,一目了然,做到全局的掌控,提高感知力度。

图8

图8

极限网关使用总结

极限网关提供一系列高性能和高可靠性的网关服务。使用这样的服务给我们带来以下好处:

  1. 可观测性好:极限网关可以动态的对 Elasticsearch 运行过程中请求进行拦截和分析,通过指标和日志来了解集群运行状态,这些指标可以用于提升性能和业务优化。
  2. 增强安全性:包含先进的安全机制,如 basicauth、LDAP 等支持,保护用户数据不受未授权访问和各种网络威胁的侵害。
  3. 高稳定性:通过冗余设计和故障转移机制,极限网关能够确保网络服务的高可用性,即使在某些组件发生故障时也能保持服务不中断,单版本最长服务超过 15 个月。
  4. 易于管理:通过提供 INFINI Console 简洁直观的管理界面,让用户能够轻松配置和监控网络状态,提升管理效率。
  5. 客户支持:良好的客户服务支持可以帮助用户快速解决使用过程中遇到的问题,提供专业的技术指导。

综上所述,极限网关为用户提供了一个高速、安全、稳定且易于管理的 ES 网关,适合对网络性能有较高要求的个人和企业用户。

未来规划

第一阶段,完成了日志 ES 集群,所有集群的容器化改造,合并,成功的把成本降低了 60%以上。这期间积累了丰富容器化经验,为业务 ES 集群上容器做了良好的铺垫;成本优势和运维优势吸引越来越多的业务接入到容器化 ES 集群。

提升 ES 集群效能--新技术应用&&版本升级

  • 极限科技官方推荐的 Easysearch 在压缩率,查询速度等等方面有很多的优势,通过长时间的测试稳定性,新特性,对比云原生的 ES 集群,根据测试结果,给“客户”提供多种选择,这也是工作重点之一。
  • 我们当前使用的 ES 版本是 6.8,已经远远落后于官方版本,今年我们计划在选择合适的集群升级 ES 版本,拥抱更多官方提供的特性。

混合(多)云架构支持

随着越来越多的 ES 集群在机房的 K8S 集群部署,这里资源出现了紧张局面。 我们尝试在云上部署自建 ES 集群,弥补机房资源有限,无法大规模扩容,同时能够支持多活场景,满足更多客户的不同需求。混合云主要实现以下几种能力:

1、扩缩容:满足不同业务灵活适配

混合(多)云部署,可以让负载内部私有云 ES,同时部署到公有云,提升扩展 IT 基础设施不仅局限于 CPU、内存,还有存储。比如某一个业务要做活动,预估流量“大爆发”,需要提前准备大规模资源,在机房内根本来不及采购扩容支持,然而在公有云上就能很方便扩容、缩容。在云上搭建 ES 集群,设置满足需求的数量、容量、配置,配合极限网关路由策略,精准的把控流量流向。

图9

图9

2、灾备:紧急情况快速部署,恢复 ES 集群读写

当机房级别大规模故障,部分业务实现了多活,单一的机房故障不会影响其服务能力,而此时比如日志查看等仍有需求,为了满足这部分“客户”需求,可以在云上 K8S 集群,快速搭建 ES 集群,恢复日志读写功能。

图10

图10

参考文档:

作者:张华勋,前新浪 CDN 研发,工作主要涉及 Mysql、MongoDB、Redis、Elasticsearch、流量调度等组件和系统,以及运维自动化、平台化等工作。现就职于好未来。

关于好未来

好未来(NYSE:TAL)是一家以内容能力与科技能力为基础,以科教、科创、科普为战略方向,助力人的终身成长,并持续探索创新的科技公司。 好未来的前身学而思成立于 2003 年,2010 年在美国纽交所正式挂牌交易。好未来以“爱与科技助力终身成长”为使命,致力成为持续创新的组织。更多参见:https://www.100tal.com/

关于极限科技(INFINI Labs)

INFINI Labs

极限科技,全称极限数据(北京)科技有限公司,是一家专注于实时搜索与数据分析的软件公司。旗下品牌极限实验室(INFINI Labs)致力于打造极致易用的数据探索与分析体验。

极限科技是一支年轻的团队,采用天然分布式的方式来进行远程协作,员工分布在全球各地,希望通过努力成为中国乃至全球企业大数据实时搜索分析产品的首选,为中国技术品牌输出添砖加瓦。

官网:https://www.infinilabs.cn

联系我们

收起阅读 »

记某客户的一次 Elasticsearch 无缝数据迁移

背景

客户需要将 Elasticsearch 集群无缝迁移到移动云,迁移过程要保证业务的最小停机时间。

实现方式

通过采用成熟的 INFINI 网关来进行数据的双写,在集群的切换恢复过程中来记录数据变更,待全量数据恢复之后再追平后面增量数据,追平增量之后,进行校验确保数据一致再进行流量的切换。

总体流程

总体迁移流程如下:

  1. 客户业务代码,切流量,双写。(新增的变更都会记录在网关本地,但是暂停消费到移动云)
  2. 暂停网关移动云这边的增量数据消费。
  3. 迁移 11 月的数据,快照,快照上传到 S3;
  4. 下载 S3 的文件到移动云。
  5. 恢复快照到移动云的 11 月份的索引。
  6. 开启网关移动云这边的增量消费。
  7. 等待增量追平(接近追平)。
  8. 按照时间条件(如:时间 A,当前时间往前 30 分钟),验证文档数据量,Hash 校验等等。
  9. 停业务的写入,网关,腾讯云的写入(10 分钟)。
  10. 等待剩余的增量追完。
  11. 对时间 A 之后的,增量进行校验。
  12. 切换所有流量到移动云,业务端直接访问移动云 ES。

总体的迁移时间:

  1. 11 月备份时间(30 分钟)19 号开始
  2. 备份下载到移动云的时间(2-3 天)
  3. 备份恢复到移动云集群的时间(30 分钟)
  4. 11 月份增量备份(20 分钟)(双写开始)(21 号)
  5. 11 月份增量下载到移动云(6 小时)
  6. 11 月份增量恢复时间(20 分钟)
  7. 追增量数据(8 个小时产生的数据,需要 1 个小时)
  8. 校验比对(存量 1 个小时)
  9. 流量暂停,增量的校验(10 分钟)
  10. 切换(1 分钟)

总体流程如下示意图:

ES 集群信息

  1. ES 版本 7.10.1
  2. 2个热节点 3个温节点  总数 1.9 TB
  3. 索引   1041, 分片2085
  4. 无自定义插件
  5. 有 update_bu_query 使用
  6. 有 delete_by_query 使用
  7. 吞吐量没有测试过,当前日增文档数 1 千多万,目标日增加上亿  

    迁移操作手册(参考)

    环境

  • 自建 ES 5.4.2
  • 自建 ES 5.6.8
  • 自建 ES 7.5.0
  • 极限网关服务器 1
  • 极限网关服务器 2
  • 云端负载均衡 1 (监听 9200 端口,指向极限网关服务器 1/2 的 8000 端口)
  • 云端负载均衡 2 (监听 9200 端口,指向极限网关服务器 1/2 的 8001 端口)

    场景描述

    若干个自建 Elasticsearch 集群需要平滑迁移到移动云,业务不停写、不做代码改动。

    数据架构

    通过将应用端流量走网关的方式,请求同步转发给自建 ES,网关记录所有的写入请求,并确保顺序在云端 ES 上重放请求,两侧集群的各种故障都妥善进行了处理,从而实现透明的集群双写,实现安全无缝的数据迁移。 业务端如果已经部署在云上,可以使用云上的 SLB 服务来访问网关,确保后端网关的高可用,如果业务端和极限网关还在企业内网,可以使用极限网关自带的 4 层浮动 IP 来确保网关的高可用

数据描述

以数据从自建集群 5.4.2 迁移到云上的 5.6.16 为例进行说明,执行步骤依次说明。

执行步骤

部署 INFINI Gateway

为了保证数据的无缝透明迁移,通过 INFINI Gateway 来进行双写。

  1. 系统调优

    参考此文档

  2. 下载程序
    
    [root@iZbp1gxkifg8uetb33pvcoZ ~]# mkdir /opt/gateway
    [root@iZbp1gxkifg8uetb33pvcoZ ~]# cd /opt/gateway/
    [root@iZbp1gxkifg8uetb33pvcoZ gateway]# wget http://release.infinilabs.com/gateway/snapshot/gateway-1.6.0_SNAPSHOT-649-linux-amd64.tar.gz
    --2022-05-19 10:16:25--  http://release.infinilabs.com/gateway/snapshot/gateway-1.6.0_SNAPSHOT-649-linux-amd64.tar.gz
    正在解析主机 release.infinilabs.com (release.infinilabs.com)... 120.79.205.193
    正在连接 release.infinilabs.com (release.infinilabs.com)|120.79.205.193|:80... 已连接。
    已发出 HTTP 请求,正在等待回应... 200 OK
    长度:7430568 (7.1M) [application/octet-stream]
    正在保存至: “gateway-1.6.0_SNAPSHOT-649-linux-amd64.tar.gz”

100%[==============================================================================================================================================>] 7,430,568 22.8MB/s 用时 0.3s

2022-05-19 10:16:25 (22.8 MB/s) - 已保存 “gateway-1.6.0_SNAPSHOT-649-linux-amd64.tar.gz” [7430568/7430568])

[root@iZbp1gxkifg8uetb33pvcoZ gateway]# tar vxzf gateway-1.6.0_SNAPSHOT-649-linux-amd64.tar.gz gateway-linux-amd64 gateway.yml sample-configs/ sample-configs/elasticsearch-with-ldap.yml sample-configs/indices-replace.yml sample-configs/record_and_play.yml sample-configs/cross-cluster-search.yml sample-configs/kibana-proxy.yml sample-configs/elasticsearch-proxy.yml sample-configs/v8-bulk-indexing-compatibility.yml sample-configs/use_old_style_search_response.yml sample-configs/context-update.yml sample-configs/elasticsearch-route-by-index.yml sample-configs/hello_world.yml sample-configs/entry-with-tls.yml sample-configs/javascript.yml sample-configs/log4j-request-filter.yml sample-configs/request-filter.yml sample-configs/condition.yml sample-configs/cross-cluster-replication.yml sample-configs/secured-elasticsearch-proxy.yml sample-configs/fast-bulk-indexing.yml sample-configs/es_migration.yml sample-configs/index-docs-diff.yml sample-configs/rate-limiter.yml sample-configs/async-bulk-indexing.yml sample-configs/elasticssearch-request-logging.yml sample-configs/router_rules.yml sample-configs/auth.yml sample-configs/index-backup.yml


3. 修改配置

将网关提供的示例配置拷贝,并根据实际集群的信息进行相应的修改,如下:

[root@iZbp1gxkifg8uetb33pvcoZ gateway]# cp sample-configs/cross-cluster-replication.yml 5.4.2TO5.6.16.yml

首先修改集群的身份信息,如下:
![](https://www.infinilabs.com/img/blog/2024/seamless-data-migration/3.png)

然后修改集群的注册信息,如下:
![](https://www.infinilabs.com/img/blog/2024/seamless-data-migration/4.png)

根据需要修改网关监听的端口,以及是否开启 TLS (如果应用客户端通过 http 协议访问 ES,请将entry.tls.enabled 值改为 false),如下:
![](https://www.infinilabs.com/img/blog/2024/seamless-data-migration/5.png)
不同的集群可以使用不同的配置,分别监听不同的端口,用于业务的分开访问。

4. 启动网关

启动网关并指定刚刚创建的配置,如下:

[root@iZbp1gxkifg8uetb33pvcoZ gateway]# ./gateway-linux-amd64 -config 5.4.2TO5.6.16.yml


/ \ /\ / \/\/ / /\ \ \/\ /_/\ / /\///\ / /\/\ \ \/ \/ //\_ / / /\/ \/ / // \ /\ / \/ \ ___/\/ \/\/ \/ \/ \/_/ _/_/

[GATEWAY] A light-weight, powerful and high-performance elasticsearch gateway. [GATEWAY] 1.6.0_SNAPSHOT, 2022-05-18 11:09:54, 2023-12-31 10:10:10, 73408e82a0f96352075f4c7d2974fd274eeafe11 [05-19 13:35:43] [INF] [app.go:174] initializing gateway. [05-19 13:35:43] [INF] [app.go:175] using config: /opt/gateway/5.4.2TO5.6.16.yml. [05-19 13:35:43] [INF] [instance.go:72] workspace: /opt/gateway/data1/gateway/nodes/ca2tc22j7ad0gneois80 [05-19 13:35:43] [INF] [app.go:283] gateway is up and running now. [05-19 13:35:50] [INF] [actions.go:358] elasticsearch [primary] is available [05-19 13:35:50] [INF] [api.go:262] api listen at: http://0.0.0.0:2900 [05-19 13:35:50] [INF] [reverseproxy.go:261] elasticsearch [primary] hosts: [] => [192.168.0.19:9200] [05-19 13:35:50] [INF] [reverseproxy.go:261] elasticsearch [backup] hosts: [] => [es-cn-tl32p9fkk0006m56k.elasticsearch.aliyuncs.com:9200] [05-19 13:35:50] [INF] [reverseproxy.go:261] elasticsearch [primary] hosts: [] => [192.168.0.19:9200] [05-19 13:35:50] [INF] [reverseproxy.go:261] elasticsearch [backup] hosts: [] => [es-cn-tl32p9fkk0006m56k.elasticsearch.aliyuncs.com:9200] [05-19 13:35:50] [INF] [reverseproxy.go:261] elasticsearch [primary] hosts: [] => [192.168.0.19:9200] [05-19 13:35:50] [INF] [entry.go:322] entry [my_es_entry/] listen at: https://0.0.0.0:8000 [05-19 13:35:50] [INF] [module.go:116] all modules are started


5. 后台运行

[root@iZbp1gxkifg8uetb33pvcoZ gateway]# nohup ./gateway-linux-amd64 -config 5.4.2TO5.6.16.yml &


6. 应用授权

curl -XPOST http://localhost:2900/_license/apply -d' { "license": "XXXXXXXXXXXXXXXXXXXXXXXXX" }'

#### 部署 INFINI Console
为了方便在多个集群之间快速切换,使用 INFINI [Console](https://infinilabs.cn/products/console/) 来进行管理。

1. 下载安装

[root@iZbp1gxkifg8uetb33pvcpZ console]# wget http://release.infinilabs.com/console/snapshot/console-0.3.0_SNAPSHOT-596-linux-amd64.tar.gz --2022-05-19 10:57:24-- http://release.infinilabs.com/console/snapshot/console-0.3.0_SNAPSHOT-596-linux-amd64.tar.gz 正在解析主机 release.infinilabs.com (release.infinilabs.com)... 120.79.205.193 正在连接 release.infinilabs.com (release.infinilabs.com)|120.79.205.193|:80... 已连接。 已发出 HTTP 请求,正在等待回应... 200 OK 长度:13576234 (13M) [application/octet-stream] 正在保存至: “console-0.3.0_SNAPSHOT-596-linux-amd64.tar.gz”

100%[==============================================================================================================================================>] 13,576,234 33.2MB/s 用时 0.4s

2022-05-19 10:57:25 (33.2 MB/s) - 已保存 “console-0.3.0_SNAPSHOT-596-linux-amd64.tar.gz” [13576234/13576234])

[root@iZbp1gxkifg8uetb33pvcpZ console]# tar vxzf console-0.3.0_SNAPSHOT-596-linux-amd64.tar.gz console-linux-amd64 console.yml


2. 修改配置

[root@iZbp1gxkifg8uetb33pvcpZ console]# cat console.yml

for the system cluster, please use Elasticsearch v7.3+

elasticsearch:

  1. 启动服务

    [root@iZbp1gxkifg8uetb33pvcpZ console]# ./console-linux-amd64 -service install
    Success
    [root@iZbp1gxkifg8uetb33pvcpZ console]# ./console-linux-amd64 -service start
    Success
  2. 访问后台

访问该主机的 9000 端口,即可打开 Console 后台,http://x.x.x.x:9000/ 打开菜单 [System][Cluster] ,注册当前需要管理的 Elasticsearch 集群和网关地址,用来快速管理,如下:

测试 INFINI Gateway

为了验证网关是否正常工作,我们通过 INFINI Console 来快速验证一下。 首先通过走网关的接口来创建一个索引,并写入一个文档,如下: 查看 5.4.2 集群的数据情况,如下: 查看集群 5.6.16 的数据情况,如下: 说明网关配置都正常,验证结束。

调整网关的消费策略

因为我们需要在全量数据迁移之后,才能进行增量数据的追加,在全量数据迁移完成之前,我们应该暂停增量数据的消费。修改网关配置里面 Pipeline consume-queue_backup-to-backupconsume-queue_primary-failure-to-backup的参数 auto_startfalse,表示不自动启动该任务,具体配置方法如下: 修改完配置之后,需要重新启动网关。 为了方便管理,可以使用 INFINI Console 来注册和管理网关,如下: 待全量迁移完成之后,可以通过后台的 Task 管理来进行后续的任务启动、停止,如下:

切换流量

接下来,将业务正常写的流量切换到网关,也就是需要把之前指向 ES 5.4.2 的地址指向网关的地址,如果 5.4.2 集群开启了身份验证,业务端代码同样需要传递身份信息,和 5.4.2 之前的用法保持不变。 切换流量到网关之后,用户的请求还是以同步的方式正常访问自建集群,网关记录到的请求会按顺序记录到 MQ 里面,但是消费是暂停状态。 如果业务端代码使用的 ES 的 SDK 支持 Sniff,并且业务代码开启了 Sniff,那么应该关闭 Sniff,避免业务端通过 Sniff 直接链接到后端的 ES 节点,所有的流量现在应该都只通过网关来进行访问。

全量数据迁移

在流量迁移到网关之后,我们开始对自建 Elasticsearch 集群的数据进行全量迁移到云端 Elasticsearch 集群。 全量迁移已有的数据的方式有很多种:

  • 通过快照的方式进行恢复
  • 使用工具来导出导入,如: ESM

如果索引数量很多的话,可以按照索引依次进行导入,同时需要注意将 Mapping 和 Setting 提前导入。 以现在 5.4 集群的索引来为例,目前的待迁移索引为 demo_5_4_2,只有4 个文档: 我们使用网关自带的迁移功能来进行数据迁移,拷贝自带的样例文件,如下:

[root@iZbp1gxkifg8uetb33pvcpZ gateway]# cp sample-configs/es_migration.yml  5.4TO5.6.yml

修改其中代表集群和索引的相关配置,可以根据需要配置是否需要重命名索引和统一 Type( 用于跨版本统一 Type),如下图红框位置: 创建好模板和索引,如果目标集群不允许动态创建文档,需要提前创建好索引,如下图: 然后就可以开始数据的迁移了,执行网关程序并指定刚刚定义的配置,如下: 执行完成后,可以确认下数据的情况,如下图: 全量数据至此导入完成。

增量数据迁移

在全量导入的过程中,可能存在数据的增量修改,不过这部分请求都已经完整记录下来了,我们只需要开启网关的消费任务即可将挤压的请求应用到云端的 Elasticsearch 集群。 示例操作如下: 如果从 5.6 的集群来看的话,这部分的修改还没同步过来,如下: 这部分增量的数据变更,在网关层面都进行了完整记录,我们只需要开启网关的增量消费任务,如下: 通过观察队列是否消费完成来判断增量数据是否做完,如下: 现在我们再看一下 5.6 集群的数据情况,如下: 数据的增量更新就过来了。

执行数据比对

由于集群内部的数据可能比较多,我们需要进行一个完整的比对才能确保数据的完整性,可以通过网关自带的数据比对工具来进行,将样例自带的文件拷贝一份,如下:

[root@iZbp1gxkifg8uetb33pvcpZ gateway]# cp sample-configs/index-docs-diff.yml  5.4DIFF5.6.yml

修改需要比对的集群和索引信息,可以加上过滤条件,如时间范围窗口来进行增量 Diff,如下图:

执行网关程序,并指定该配置文件,如下图: 如图,两个集群完全一致。

切换集群

如果验证完之后,两个集群的数据已经完全一致了,可以将程序切换到新集群,或者将网关的配置里面的主备进行互换,同步写 5.6 集群。 双集群在线运行一段时间,待业务完全验证之后,再安全下线旧集群,如遇到问题,也可以随时回切到老集群。

小结

通过使用极限网关,自建 ES 集群可以安全无缝的迁移到移动云 ES,在迁移的过程中,两套集群通过网关进行了解耦,两套集群的版本也可以不一样,在迁移的过程中还能实现版本的无缝升级。 如有任何问题,请随时联系我,期待与您交流!

继续阅读 »

背景

客户需要将 Elasticsearch 集群无缝迁移到移动云,迁移过程要保证业务的最小停机时间。

实现方式

通过采用成熟的 INFINI 网关来进行数据的双写,在集群的切换恢复过程中来记录数据变更,待全量数据恢复之后再追平后面增量数据,追平增量之后,进行校验确保数据一致再进行流量的切换。

总体流程

总体迁移流程如下:

  1. 客户业务代码,切流量,双写。(新增的变更都会记录在网关本地,但是暂停消费到移动云)
  2. 暂停网关移动云这边的增量数据消费。
  3. 迁移 11 月的数据,快照,快照上传到 S3;
  4. 下载 S3 的文件到移动云。
  5. 恢复快照到移动云的 11 月份的索引。
  6. 开启网关移动云这边的增量消费。
  7. 等待增量追平(接近追平)。
  8. 按照时间条件(如:时间 A,当前时间往前 30 分钟),验证文档数据量,Hash 校验等等。
  9. 停业务的写入,网关,腾讯云的写入(10 分钟)。
  10. 等待剩余的增量追完。
  11. 对时间 A 之后的,增量进行校验。
  12. 切换所有流量到移动云,业务端直接访问移动云 ES。

总体的迁移时间:

  1. 11 月备份时间(30 分钟)19 号开始
  2. 备份下载到移动云的时间(2-3 天)
  3. 备份恢复到移动云集群的时间(30 分钟)
  4. 11 月份增量备份(20 分钟)(双写开始)(21 号)
  5. 11 月份增量下载到移动云(6 小时)
  6. 11 月份增量恢复时间(20 分钟)
  7. 追增量数据(8 个小时产生的数据,需要 1 个小时)
  8. 校验比对(存量 1 个小时)
  9. 流量暂停,增量的校验(10 分钟)
  10. 切换(1 分钟)

总体流程如下示意图:

ES 集群信息

  1. ES 版本 7.10.1
  2. 2个热节点 3个温节点  总数 1.9 TB
  3. 索引   1041, 分片2085
  4. 无自定义插件
  5. 有 update_bu_query 使用
  6. 有 delete_by_query 使用
  7. 吞吐量没有测试过,当前日增文档数 1 千多万,目标日增加上亿  

    迁移操作手册(参考)

    环境

  • 自建 ES 5.4.2
  • 自建 ES 5.6.8
  • 自建 ES 7.5.0
  • 极限网关服务器 1
  • 极限网关服务器 2
  • 云端负载均衡 1 (监听 9200 端口,指向极限网关服务器 1/2 的 8000 端口)
  • 云端负载均衡 2 (监听 9200 端口,指向极限网关服务器 1/2 的 8001 端口)

    场景描述

    若干个自建 Elasticsearch 集群需要平滑迁移到移动云,业务不停写、不做代码改动。

    数据架构

    通过将应用端流量走网关的方式,请求同步转发给自建 ES,网关记录所有的写入请求,并确保顺序在云端 ES 上重放请求,两侧集群的各种故障都妥善进行了处理,从而实现透明的集群双写,实现安全无缝的数据迁移。 业务端如果已经部署在云上,可以使用云上的 SLB 服务来访问网关,确保后端网关的高可用,如果业务端和极限网关还在企业内网,可以使用极限网关自带的 4 层浮动 IP 来确保网关的高可用

数据描述

以数据从自建集群 5.4.2 迁移到云上的 5.6.16 为例进行说明,执行步骤依次说明。

执行步骤

部署 INFINI Gateway

为了保证数据的无缝透明迁移,通过 INFINI Gateway 来进行双写。

  1. 系统调优

    参考此文档

  2. 下载程序
    
    [root@iZbp1gxkifg8uetb33pvcoZ ~]# mkdir /opt/gateway
    [root@iZbp1gxkifg8uetb33pvcoZ ~]# cd /opt/gateway/
    [root@iZbp1gxkifg8uetb33pvcoZ gateway]# wget http://release.infinilabs.com/gateway/snapshot/gateway-1.6.0_SNAPSHOT-649-linux-amd64.tar.gz
    --2022-05-19 10:16:25--  http://release.infinilabs.com/gateway/snapshot/gateway-1.6.0_SNAPSHOT-649-linux-amd64.tar.gz
    正在解析主机 release.infinilabs.com (release.infinilabs.com)... 120.79.205.193
    正在连接 release.infinilabs.com (release.infinilabs.com)|120.79.205.193|:80... 已连接。
    已发出 HTTP 请求,正在等待回应... 200 OK
    长度:7430568 (7.1M) [application/octet-stream]
    正在保存至: “gateway-1.6.0_SNAPSHOT-649-linux-amd64.tar.gz”

100%[==============================================================================================================================================>] 7,430,568 22.8MB/s 用时 0.3s

2022-05-19 10:16:25 (22.8 MB/s) - 已保存 “gateway-1.6.0_SNAPSHOT-649-linux-amd64.tar.gz” [7430568/7430568])

[root@iZbp1gxkifg8uetb33pvcoZ gateway]# tar vxzf gateway-1.6.0_SNAPSHOT-649-linux-amd64.tar.gz gateway-linux-amd64 gateway.yml sample-configs/ sample-configs/elasticsearch-with-ldap.yml sample-configs/indices-replace.yml sample-configs/record_and_play.yml sample-configs/cross-cluster-search.yml sample-configs/kibana-proxy.yml sample-configs/elasticsearch-proxy.yml sample-configs/v8-bulk-indexing-compatibility.yml sample-configs/use_old_style_search_response.yml sample-configs/context-update.yml sample-configs/elasticsearch-route-by-index.yml sample-configs/hello_world.yml sample-configs/entry-with-tls.yml sample-configs/javascript.yml sample-configs/log4j-request-filter.yml sample-configs/request-filter.yml sample-configs/condition.yml sample-configs/cross-cluster-replication.yml sample-configs/secured-elasticsearch-proxy.yml sample-configs/fast-bulk-indexing.yml sample-configs/es_migration.yml sample-configs/index-docs-diff.yml sample-configs/rate-limiter.yml sample-configs/async-bulk-indexing.yml sample-configs/elasticssearch-request-logging.yml sample-configs/router_rules.yml sample-configs/auth.yml sample-configs/index-backup.yml


3. 修改配置

将网关提供的示例配置拷贝,并根据实际集群的信息进行相应的修改,如下:

[root@iZbp1gxkifg8uetb33pvcoZ gateway]# cp sample-configs/cross-cluster-replication.yml 5.4.2TO5.6.16.yml

首先修改集群的身份信息,如下:
![](https://www.infinilabs.com/img/blog/2024/seamless-data-migration/3.png)

然后修改集群的注册信息,如下:
![](https://www.infinilabs.com/img/blog/2024/seamless-data-migration/4.png)

根据需要修改网关监听的端口,以及是否开启 TLS (如果应用客户端通过 http 协议访问 ES,请将entry.tls.enabled 值改为 false),如下:
![](https://www.infinilabs.com/img/blog/2024/seamless-data-migration/5.png)
不同的集群可以使用不同的配置,分别监听不同的端口,用于业务的分开访问。

4. 启动网关

启动网关并指定刚刚创建的配置,如下:

[root@iZbp1gxkifg8uetb33pvcoZ gateway]# ./gateway-linux-amd64 -config 5.4.2TO5.6.16.yml


/ \ /\ / \/\/ / /\ \ \/\ /_/\ / /\///\ / /\/\ \ \/ \/ //\_ / / /\/ \/ / // \ /\ / \/ \ ___/\/ \/\/ \/ \/ \/_/ _/_/

[GATEWAY] A light-weight, powerful and high-performance elasticsearch gateway. [GATEWAY] 1.6.0_SNAPSHOT, 2022-05-18 11:09:54, 2023-12-31 10:10:10, 73408e82a0f96352075f4c7d2974fd274eeafe11 [05-19 13:35:43] [INF] [app.go:174] initializing gateway. [05-19 13:35:43] [INF] [app.go:175] using config: /opt/gateway/5.4.2TO5.6.16.yml. [05-19 13:35:43] [INF] [instance.go:72] workspace: /opt/gateway/data1/gateway/nodes/ca2tc22j7ad0gneois80 [05-19 13:35:43] [INF] [app.go:283] gateway is up and running now. [05-19 13:35:50] [INF] [actions.go:358] elasticsearch [primary] is available [05-19 13:35:50] [INF] [api.go:262] api listen at: http://0.0.0.0:2900 [05-19 13:35:50] [INF] [reverseproxy.go:261] elasticsearch [primary] hosts: [] => [192.168.0.19:9200] [05-19 13:35:50] [INF] [reverseproxy.go:261] elasticsearch [backup] hosts: [] => [es-cn-tl32p9fkk0006m56k.elasticsearch.aliyuncs.com:9200] [05-19 13:35:50] [INF] [reverseproxy.go:261] elasticsearch [primary] hosts: [] => [192.168.0.19:9200] [05-19 13:35:50] [INF] [reverseproxy.go:261] elasticsearch [backup] hosts: [] => [es-cn-tl32p9fkk0006m56k.elasticsearch.aliyuncs.com:9200] [05-19 13:35:50] [INF] [reverseproxy.go:261] elasticsearch [primary] hosts: [] => [192.168.0.19:9200] [05-19 13:35:50] [INF] [entry.go:322] entry [my_es_entry/] listen at: https://0.0.0.0:8000 [05-19 13:35:50] [INF] [module.go:116] all modules are started


5. 后台运行

[root@iZbp1gxkifg8uetb33pvcoZ gateway]# nohup ./gateway-linux-amd64 -config 5.4.2TO5.6.16.yml &


6. 应用授权

curl -XPOST http://localhost:2900/_license/apply -d' { "license": "XXXXXXXXXXXXXXXXXXXXXXXXX" }'

#### 部署 INFINI Console
为了方便在多个集群之间快速切换,使用 INFINI [Console](https://infinilabs.cn/products/console/) 来进行管理。

1. 下载安装

[root@iZbp1gxkifg8uetb33pvcpZ console]# wget http://release.infinilabs.com/console/snapshot/console-0.3.0_SNAPSHOT-596-linux-amd64.tar.gz --2022-05-19 10:57:24-- http://release.infinilabs.com/console/snapshot/console-0.3.0_SNAPSHOT-596-linux-amd64.tar.gz 正在解析主机 release.infinilabs.com (release.infinilabs.com)... 120.79.205.193 正在连接 release.infinilabs.com (release.infinilabs.com)|120.79.205.193|:80... 已连接。 已发出 HTTP 请求,正在等待回应... 200 OK 长度:13576234 (13M) [application/octet-stream] 正在保存至: “console-0.3.0_SNAPSHOT-596-linux-amd64.tar.gz”

100%[==============================================================================================================================================>] 13,576,234 33.2MB/s 用时 0.4s

2022-05-19 10:57:25 (33.2 MB/s) - 已保存 “console-0.3.0_SNAPSHOT-596-linux-amd64.tar.gz” [13576234/13576234])

[root@iZbp1gxkifg8uetb33pvcpZ console]# tar vxzf console-0.3.0_SNAPSHOT-596-linux-amd64.tar.gz console-linux-amd64 console.yml


2. 修改配置

[root@iZbp1gxkifg8uetb33pvcpZ console]# cat console.yml

for the system cluster, please use Elasticsearch v7.3+

elasticsearch:

  1. 启动服务

    [root@iZbp1gxkifg8uetb33pvcpZ console]# ./console-linux-amd64 -service install
    Success
    [root@iZbp1gxkifg8uetb33pvcpZ console]# ./console-linux-amd64 -service start
    Success
  2. 访问后台

访问该主机的 9000 端口,即可打开 Console 后台,http://x.x.x.x:9000/ 打开菜单 [System][Cluster] ,注册当前需要管理的 Elasticsearch 集群和网关地址,用来快速管理,如下:

测试 INFINI Gateway

为了验证网关是否正常工作,我们通过 INFINI Console 来快速验证一下。 首先通过走网关的接口来创建一个索引,并写入一个文档,如下: 查看 5.4.2 集群的数据情况,如下: 查看集群 5.6.16 的数据情况,如下: 说明网关配置都正常,验证结束。

调整网关的消费策略

因为我们需要在全量数据迁移之后,才能进行增量数据的追加,在全量数据迁移完成之前,我们应该暂停增量数据的消费。修改网关配置里面 Pipeline consume-queue_backup-to-backupconsume-queue_primary-failure-to-backup的参数 auto_startfalse,表示不自动启动该任务,具体配置方法如下: 修改完配置之后,需要重新启动网关。 为了方便管理,可以使用 INFINI Console 来注册和管理网关,如下: 待全量迁移完成之后,可以通过后台的 Task 管理来进行后续的任务启动、停止,如下:

切换流量

接下来,将业务正常写的流量切换到网关,也就是需要把之前指向 ES 5.4.2 的地址指向网关的地址,如果 5.4.2 集群开启了身份验证,业务端代码同样需要传递身份信息,和 5.4.2 之前的用法保持不变。 切换流量到网关之后,用户的请求还是以同步的方式正常访问自建集群,网关记录到的请求会按顺序记录到 MQ 里面,但是消费是暂停状态。 如果业务端代码使用的 ES 的 SDK 支持 Sniff,并且业务代码开启了 Sniff,那么应该关闭 Sniff,避免业务端通过 Sniff 直接链接到后端的 ES 节点,所有的流量现在应该都只通过网关来进行访问。

全量数据迁移

在流量迁移到网关之后,我们开始对自建 Elasticsearch 集群的数据进行全量迁移到云端 Elasticsearch 集群。 全量迁移已有的数据的方式有很多种:

  • 通过快照的方式进行恢复
  • 使用工具来导出导入,如: ESM

如果索引数量很多的话,可以按照索引依次进行导入,同时需要注意将 Mapping 和 Setting 提前导入。 以现在 5.4 集群的索引来为例,目前的待迁移索引为 demo_5_4_2,只有4 个文档: 我们使用网关自带的迁移功能来进行数据迁移,拷贝自带的样例文件,如下:

[root@iZbp1gxkifg8uetb33pvcpZ gateway]# cp sample-configs/es_migration.yml  5.4TO5.6.yml

修改其中代表集群和索引的相关配置,可以根据需要配置是否需要重命名索引和统一 Type( 用于跨版本统一 Type),如下图红框位置: 创建好模板和索引,如果目标集群不允许动态创建文档,需要提前创建好索引,如下图: 然后就可以开始数据的迁移了,执行网关程序并指定刚刚定义的配置,如下: 执行完成后,可以确认下数据的情况,如下图: 全量数据至此导入完成。

增量数据迁移

在全量导入的过程中,可能存在数据的增量修改,不过这部分请求都已经完整记录下来了,我们只需要开启网关的消费任务即可将挤压的请求应用到云端的 Elasticsearch 集群。 示例操作如下: 如果从 5.6 的集群来看的话,这部分的修改还没同步过来,如下: 这部分增量的数据变更,在网关层面都进行了完整记录,我们只需要开启网关的增量消费任务,如下: 通过观察队列是否消费完成来判断增量数据是否做完,如下: 现在我们再看一下 5.6 集群的数据情况,如下: 数据的增量更新就过来了。

执行数据比对

由于集群内部的数据可能比较多,我们需要进行一个完整的比对才能确保数据的完整性,可以通过网关自带的数据比对工具来进行,将样例自带的文件拷贝一份,如下:

[root@iZbp1gxkifg8uetb33pvcpZ gateway]# cp sample-configs/index-docs-diff.yml  5.4DIFF5.6.yml

修改需要比对的集群和索引信息,可以加上过滤条件,如时间范围窗口来进行增量 Diff,如下图:

执行网关程序,并指定该配置文件,如下图: 如图,两个集群完全一致。

切换集群

如果验证完之后,两个集群的数据已经完全一致了,可以将程序切换到新集群,或者将网关的配置里面的主备进行互换,同步写 5.6 集群。 双集群在线运行一段时间,待业务完全验证之后,再安全下线旧集群,如遇到问题,也可以随时回切到老集群。

小结

通过使用极限网关,自建 ES 集群可以安全无缝的迁移到移动云 ES,在迁移的过程中,两套集群通过网关进行了解耦,两套集群的版本也可以不一样,在迁移的过程中还能实现版本的无缝升级。 如有任何问题,请随时联系我,期待与您交流!

收起阅读 »

7 年+积累、 Elastic 创始人Shay Banon 等 15 位专家推荐的 Elasticsearch 8.X新书《一本书讲透Elasticsearch》已上线...

今天,非常高兴地跟大家宣布,经过 7 年多的努力和精心准备,我们的新书《一本书讲透 Elasticsearch》已正式出版上线! ​​

1.png

​​​​​​ 我从 2016 年接触 Elasticsearch 1.X、2.X 的版本,到现在已经接近 8 年+的时间。在这期间,我常常被问到:

如何系统性地学习 Elasticsearch ?

如何将现有的关系型数据库迁移到 ES ?

如何选择合适的版本?

如何规划和监控集群?

如何进行数据建模?

如何选择合适的检索方式?

如何基于现有数据进行可视化分析?

等一系列问题.......

这些问题促使我将之前的产品开发、项目实战经验和咨询经验进行全面整合,并精心梳理,融入到这本新书中,希望能让大家少走不必要的弯路。

一、书籍特点 本书具有以下几个显著特点:

最新版本,前沿知识点

本书基于 8.x 版本编写,涵盖了如索引生命周期管理、快照生命周期管理、数据流 datastream 等至关重要的新特性。

核心知识,系统认知

我们为您提供了清晰的学习路径,保留了最核心的“最少必要”知识点,并通过思维导图和大量图解内容,帮助读者更易理解和吸收。

实际应用,超越认证

覆盖Elastic官方认证的核心知识点,已帮助近200人通过Elastic专家认证考试。内容不仅限于认证,更注重实际应用。

来源于实战,应用于实战

书中内容源自真实项目案例和企业级问题解答(问题来自于Elasticsearch中文社区、死磕Elasticsearch知识星球、微信群、QQ群等)。涵盖3个实战项目,助力读者将技能应用到企业实战环境中。

代码开源,答疑服务

全书的代码、脚本在GitHub上开源,便于初学者通过实践学习。我们的答疑社群将持续跟踪最新问题,不断迭代更新内容。

二、5 个最尖锐问题快问快答 如下的问题来自 ChatGPT 4.0 的作为专业读者提出的 5 个最尖锐问题。

2.png

我快速回答一下:

2.1 问题1:市场竞争和定位问题 “市面上已有接近10本关于Elasticsearch的书籍,您的书与这些现有书籍相比有何独特之处?您是如何确保您的书在内容上与其他书籍区别开来,满足读者新的或更深入的需求的?”

铭毅天下:

1、独特之处:版本咱们是目前市场唯一的 8.X 版本。

2、区别开来:我从 2016 年开始搞 ElasticStack 到现在几乎平均每周一篇技术博客,从未间断。无需多说,时间能证明一切!这是咱们最大的不同之一。

3、还有不同:我自己公众号+博客有累计近 4.5 万+关注读者,知识星球有近2000人付费用户,这些大量的实战问题促使我唯有“自我革命”才能生存和成长!

2.2 问题2:实用性和更新性问题 “鉴于Elasticsearch技术持续发展和迭代,您的书籍是如何处理和包含最新版本的特性和变化的?在提供最新信息的同时,您如何保证书中内容的长期有效性和实用性?”

铭毅天下:

1、实话说结论,我做不到,市面上任何纸质书都不可能做到。受限于撰写、出版等相较于 Elastic技术栈体系更新的滞后性。

2、但是,我在筛选知识点的时候已充分考虑结合企业级实战以及 Elastic 官方认证考试的最核心、最关键的“最少必要知识”作为咱们的提纲,并且承诺后面继续根据读者反馈迭代和升级。

2.3 问题3:作者经验和权威性问题 “您能否分享一些您个人在Elasticsearch领域的实战经验或特殊贡献,这些经验如何在您的书中得到体现?作为作者,您相比其他书籍作者有哪些独特的优势或视角?”

铭毅天下:

1、本人持续深耕大数据存储和检索领域 7 年+,有博客为证!有丰富的项目实战经验和企业级实战问题咨询经验,已带领近200人+通过 Elastic 认证专家考试。

2、独特视角就是:来自全国乃至全球多个国家的实战问题——自己运营的知识星球、微信群、QQ群多达数千人,每天都有大量实战问题涌现。

3、作者是坚定的长期主义者:博客已写12年+,从未间断!相信积累的力量、相信坚持的力量、相信相信的力量!

2.4 问题4:读者受益问题 “您认为读者在阅读您的书籍之后,最具体和显著的收获会是什么?有哪些实际的技能或知识可以直接应用到他们的工作和项目中?”

铭毅天下:

1、少走不必要的弯路!

2、能获得属于自己的专属学习路线,能建立专属的知识体系,能将 Elasticsearch 原理、开发、运维、架构技能应用于实战。

2.5 问题5:内容深度和广度问题 “您的书籍是如何平衡Elasticsearch的基础知识和高级技术的?它是否适合所有水平的读者,从初学者到高级用户?对于那些已经具有深厚Elasticsearch知识背景的读者,您的书提供了哪些更深入的见解或独特内容?”

铭毅天下:

1、适合大数据存储和检索领域的初学者,也同样适合有工作经验的中级、高级工程师、架构师等。

2、对于深厚Elasticsearch知识背景的读者,本书可以当做工具书,需要时备查、常翻常新。

三、行业顶级大佬的推荐

3.png

值得一提的是,这本书获得了 Elastic 创始人兼CTO Shay Banon 、Elastic中文社区创始人兼极限科技CTO等15位顶级专家的强力推荐,是一本不可多得的Elasticsearch学习材料。

I am very happy to see that Elasticsearch has been widely used in China, which fully reflects the open source, free and open power of Elastic. This book is derived from the author's 7 years of technical accumulation and embodies the author's love for ElasticStack open source technology. I hope this book can help more people understand Elasticsearch and search technology, so as to discover the great value of data. I am convinced that this book will have a profound impact on Elastic's Chinese community.

我很高兴看到Elasticsearch在中国得到了广泛的应用,这充分体现了Elastic开源、自由、开放的力量。本书源自作者7年的技术积累,体现了作者对ElasticStack开源技术的热爱。希望这本书能够帮助更多的人了解Elasticsearch和搜索技术,从而发现数据的巨大价值。我相信这本书将对 Elastic 的中文社区产生深远的影响。

4.png

——Shay Banon Elastic公司创始人兼首席技术官

很高兴看到铭毅天下的新书出版,《一本书讲透Elasticsearch:原理、进阶与工程实践》是一本值得推荐的新书。它汇集了作者丰富的实战经验,深入探讨 Elasticsearch的 核心原理。书中丰富的图解和清晰的结构使得复杂的知识易于理解和吸收。同时,它覆盖了 Elastic 认证考试的所有考点,助力读者建立全面的认知。此外,书中还包含实战项目,帮助读者将所学技能应用到实际场景中。作者拥有多年实战经验和广泛的影响力,这本书将成为学习和应用 Elasticsearch 的重要指南。

——Medcl,Elastic 中文社区创始人、极限科技创始人

铭毅天下是ES中文社区里少有的常年坚持写作的技术博主,尤其擅长将点状发散的社区讨论进行归纳总结,结合自己的实践和再思考,形成系统性的系列技术文章。本书成于作者在Elasticsearch领域多年的理论知识沉淀,并涵盖了实际应用场景的最佳实践。无论你是Elasticsearch初学者还是有一定经验的开发者,相信都能通过阅读本书而受益匪浅。

—— 吴晓刚 (Wood大叔)携程旅行网 企业数字化平台部 研发总监

在大数据检索和分析领域,Elastic Stack 技术栈有广泛应用,本书从业务场景出发详细介绍了在 Elasticsearch 擅长的各类场景中完成业务系统开发所需的技术栈和技术手段,为用户系统选型和了解整体技术架构提供了指导,可以帮助用户少走弯路,快速完成系统建设。

——张超 《Elasticsearch 源码解析与优化实战》作者, Elasticsearch 内核资深研发工程师

本书基于Elasticsearch最新的8.X版本,涵盖了Elasticsearch更加完整、实时的功能。作者拥有丰富的Elasticsearch和写作经验,语言通俗易懂,内容详尽全面。无论你是初学者还是有一定经验的开发人员,本书都能够为你提供更深入的内容和最佳实践。如果你想系统地学习、掌握Elasticsearch,那么这本书绝对是你不可错过的参考书籍。

—— 魏子珺,阿里巴巴elasticsearch内核专家

很高兴为大家推荐这本关于Elasticsearch的技术书籍。本书涵盖了相当丰富的原理讲解和实现技术,更重要的是对实战场景给出了明确的指导案例和代码片段可供参考和使用。即面向开发人员深入讲解了搜索引擎的核心算法与数据结构,也同时给运维人员提供了关键指标的定义和解读。对于想系统学习的初、中级用户,可以按照章节循序渐进的阅读。对于高级用户来说,也可以从 遇到的问题为切入点,直接从某个具体章节入手来测试、寻求解决方案。铭毅天下是Elastic中文社区长期活跃和积极贡献的明星成员。非常兴奋看到他把自己日积月累的知识精华和经验总结在书中分享给广大读者。我相信本书一定可以帮助到处在任何阶段想学习探索Elasticsearch的用户。

——吴斌,Elastic中文社区主席

《一本书讲透Elasticsearch:原理、进阶与工程实践》是一本由一线开发人员撰写的实战指南。作者凭借多年的 Elasticsearch 咨询和教学经验,将复杂的概念以简明易懂的方式呈现给读者。这本书将帮助你深入了解 Elasticsearch,并理解其背后的原理和逻辑。通过学习本书,你将获得全面的知识,从而能够灵活应用 Elasticsearch 解决各种实际问题。相信这本书将成为你掌握 Elasticsearch 的必备工具。

——阮一鸣,eBay 高级研发经理、极客时间『Elasticsearch 核心技术与实战』课程讲师

铭毅在 Elasticsearch 领域深耕多年,勤奋且专注, 同时运营着国内最大的 ES 社群 ,帮助许多同学成功通过了有难度的 Elastic 认证工程师考试。很高兴看到他的新书出版,都说万事开头难,但我相信这本书能够为ES 初学者铺平道路,扫除障碍,澄清疑虑,快速上手!推荐大家阅读!

——魏彬,中国首位 Elastic 认证工程师

《一本书讲透Elasticsearch:原理、进阶与工程实践 》这本书是我极力推荐的一部作品!

我认识铭毅天下很久了,第一次见面记得是2019年在北京的Elastic开发者大会上,但在这之前,我就经常阅读他关于Elasticsearch的技术分享而神交已久。我了解的铭毅天下是一位拥有丰富的Elasticsearch领域知识和经验的专家,他曾在PB级大数据系统项目中发挥关键作用。实施这种大规模,长周期的复杂项目是非常不容易的,无论从系统设计,到实施过程中的问题解决。因此,来自于实践的真知产出,值得我们开卷。

多年来,铭毅天下一直积极、高效地在各种博客和社交媒体上分享与Elasticsearch相关的内容,并密切同步每个版本的更新。在Elasticsearch上,他不仅持续自我精进,还组织了学习小组和社区,帮助其他对Elasticsearch感兴趣的伙伴一起进步。他还带领150多人通过Elastic工程师认证,为许多人的职业发展贡献了力量。

这本书是铭毅天下多年经验的总结,内容涵盖了几乎全部的Elastic认证考点,而且它来自铭毅天下近7年的博客积累,每一章节都经得起时间的考验。因为抓住了平时学习和使用Elasticsearch当中痛点并总结了最佳实践,这些内容不仅阅读量高,而且转发度也很广泛。无论你是想深入了解Elasticsearch的基础知识还是应用实践,这本书都能满足你的需求。

我相信这本书将为读者提供一次全面而深入的学习体验,帮助他们在Elasticsearch领域取得突破。无论你是初学者还是有经验的专业人士,这本书都是不可或缺的指南。我由衷地推荐这本书,相信它会成为你在Elasticsearch学习和实践中的得力伙伴!

——李捷,Elastic 解决方案架构师 Principle Solution Architect

当得知本书成稿的消息时,我的心情是非常激动的,不管是作为一名技术人,还是作为一名搜索引擎的从业者,以及作为一名Elasticsearch中文社区的参与者和建设者。本书作者与我们一起见证了Elastic生态在国内的起步、发展以及到今天的繁荣;有所不同的是,作者有超强的毅力(就像铭毅天下的名字一样),坚持在这个技术方向上深耕了7年之久,在知识、技术和实践等方面有着深厚的经验积累,不但亲力亲为,而且深谙知识社群与实践社区CoP的操盘之道,在自我成长的同时也打造了优质的同行网络,积极影响了一批技术人,其中的优秀者更是通过了Elatics官方认证,极具含金量。本书的出版,一定会给更多技术人带来直接或间接的帮助,同时在个人成长、知识共享与实践社区等方面在业内树立成功的榜样。让我们一起用技术影响世界影响人!

—— 杨振涛,Elastisearch中文社区深圳主席|vivo互联网 研发总监

Elasticsearch是人工智能和大数据时代不可或缺的重要产品,已经成为开发者必备技能。本书汇集了作者多年开发经验、咨询经验、数千个Elasticsearch爱好者的最佳实战。因此在讲解原理的同时,能深入到最佳实践中去,做到深入浅出,非常适合Elasticsearch的初学者以及进阶者。

—— 付磊,快手Elasticsearch负责人,《Redis开发与运维》作者

Elasticsearch 作为一款强大又灵活的数据分析检索工具,值得每一位后端程序员认真学习。铭毅天下的这本《一本书讲透Elasticsearch:原理、进阶与工程实践》,用浅显易懂的语言介绍了Elasticsearch的概念、原理和实践,非常值得阅读!

—— 程序员小灰,公众号【程序员小灰】运营者,畅销书《漫画算法》作者

铭毅是我的老友,他是一个及其认证踏实和执着追究技术的人,这七年来他一直热心Elasticstack相关技术的步道,热忱帮助社区和公众号里的伙伴,成就不俗。本书是一本实用性极高的Elasticsearch的实践类书籍,更是铭毅倾尽所学之作。通读原稿后,让我非常欣赏的地方在于,它是市面上难得一见的把Elasticsearch原理,实现方式,最佳实践,以及实战案例串联在一起实操类书籍,无论是初学者还是需要进阶学习的人员都能从中获取想要的内容。十分适合想要在企业环境中落地Elasticsearch的人们,因此我诚意把它推荐给广大的技术爱好者和相关从业人员。

——周钰, IBM中国 企业架构师 中国前50 Elastic持证者

Elasticsearch作为一款优秀的开源分布式搜索引擎,被广泛应用在日志分析、站内搜索、指标监控、数据加速等场景,学习并掌握ES,已经成为一个技术工作人员不可或缺的重要技能之一。而本书深入浅出,对Elasticsearch的基本概念、设计原理及实践进行了详细介绍,是学习Elasticsearch的必备资料。诚挚推荐。

—— 吴荣,Elasticsearch平台资深研发工程师

一份专业、细致、用户友好的技术文档能给我们技术人员的日常工作带来多大的帮助,相信大家都有深刻的体会,特别是像Elasticsearch这种在搜索引擎领域最广泛应用的解决方案更是如此。虽然官方文档内容很详尽,更新很及时,但是限于语言、网速等问题,广大国内开发者并不能很准确高效的找到自己需要的内容。铭毅老师这本,兼顾了内容的专业性、严谨性、完整性,围绕着Elasticsearch及其相关组件所撰写,覆盖了从基础概念到高级用法的方方面面内容的专业书籍,能给各位带来的价值就不言而喻了。这本书适合从入门使用到高级调优的各层次的读者,是一本少有的适合放在案头常看常新的书。

—— 陈晨(死敌wen),资深搜索架构师、Elastic认证专家

5.png

15位大佬评价批量导入 Elasticsearch

15位大佬评价 Kibana 可视化

6.png

15位大佬评价词云图

7.png

无论您是大数据检索领域的初学者、开发和运维人员,还是架构师和管理人员,这本书都将成为实战路上的得力助手和“避坑指南”。

8.png

立即购买以获取专属福利:不论您从哪里购买、不论多少费用购买,记得保留购物链接和发票,费用都可以折算同等价格的星球优惠券。

私V信:elastic6 搞定后续一切流程。 ————————————————

                        本文为博主原创文章,未经博主书面授权不得转载。书面授权后方可转载,但转载请务必加上原作者:铭毅天下,原文地址:blog.csdn.net/laoyang360

原文链接:https://blog.csdn.net/laoyang360/article/details/135614659

继续阅读 »

今天,非常高兴地跟大家宣布,经过 7 年多的努力和精心准备,我们的新书《一本书讲透 Elasticsearch》已正式出版上线! ​​

1.png

​​​​​​ 我从 2016 年接触 Elasticsearch 1.X、2.X 的版本,到现在已经接近 8 年+的时间。在这期间,我常常被问到:

如何系统性地学习 Elasticsearch ?

如何将现有的关系型数据库迁移到 ES ?

如何选择合适的版本?

如何规划和监控集群?

如何进行数据建模?

如何选择合适的检索方式?

如何基于现有数据进行可视化分析?

等一系列问题.......

这些问题促使我将之前的产品开发、项目实战经验和咨询经验进行全面整合,并精心梳理,融入到这本新书中,希望能让大家少走不必要的弯路。

一、书籍特点 本书具有以下几个显著特点:

最新版本,前沿知识点

本书基于 8.x 版本编写,涵盖了如索引生命周期管理、快照生命周期管理、数据流 datastream 等至关重要的新特性。

核心知识,系统认知

我们为您提供了清晰的学习路径,保留了最核心的“最少必要”知识点,并通过思维导图和大量图解内容,帮助读者更易理解和吸收。

实际应用,超越认证

覆盖Elastic官方认证的核心知识点,已帮助近200人通过Elastic专家认证考试。内容不仅限于认证,更注重实际应用。

来源于实战,应用于实战

书中内容源自真实项目案例和企业级问题解答(问题来自于Elasticsearch中文社区、死磕Elasticsearch知识星球、微信群、QQ群等)。涵盖3个实战项目,助力读者将技能应用到企业实战环境中。

代码开源,答疑服务

全书的代码、脚本在GitHub上开源,便于初学者通过实践学习。我们的答疑社群将持续跟踪最新问题,不断迭代更新内容。

二、5 个最尖锐问题快问快答 如下的问题来自 ChatGPT 4.0 的作为专业读者提出的 5 个最尖锐问题。

2.png

我快速回答一下:

2.1 问题1:市场竞争和定位问题 “市面上已有接近10本关于Elasticsearch的书籍,您的书与这些现有书籍相比有何独特之处?您是如何确保您的书在内容上与其他书籍区别开来,满足读者新的或更深入的需求的?”

铭毅天下:

1、独特之处:版本咱们是目前市场唯一的 8.X 版本。

2、区别开来:我从 2016 年开始搞 ElasticStack 到现在几乎平均每周一篇技术博客,从未间断。无需多说,时间能证明一切!这是咱们最大的不同之一。

3、还有不同:我自己公众号+博客有累计近 4.5 万+关注读者,知识星球有近2000人付费用户,这些大量的实战问题促使我唯有“自我革命”才能生存和成长!

2.2 问题2:实用性和更新性问题 “鉴于Elasticsearch技术持续发展和迭代,您的书籍是如何处理和包含最新版本的特性和变化的?在提供最新信息的同时,您如何保证书中内容的长期有效性和实用性?”

铭毅天下:

1、实话说结论,我做不到,市面上任何纸质书都不可能做到。受限于撰写、出版等相较于 Elastic技术栈体系更新的滞后性。

2、但是,我在筛选知识点的时候已充分考虑结合企业级实战以及 Elastic 官方认证考试的最核心、最关键的“最少必要知识”作为咱们的提纲,并且承诺后面继续根据读者反馈迭代和升级。

2.3 问题3:作者经验和权威性问题 “您能否分享一些您个人在Elasticsearch领域的实战经验或特殊贡献,这些经验如何在您的书中得到体现?作为作者,您相比其他书籍作者有哪些独特的优势或视角?”

铭毅天下:

1、本人持续深耕大数据存储和检索领域 7 年+,有博客为证!有丰富的项目实战经验和企业级实战问题咨询经验,已带领近200人+通过 Elastic 认证专家考试。

2、独特视角就是:来自全国乃至全球多个国家的实战问题——自己运营的知识星球、微信群、QQ群多达数千人,每天都有大量实战问题涌现。

3、作者是坚定的长期主义者:博客已写12年+,从未间断!相信积累的力量、相信坚持的力量、相信相信的力量!

2.4 问题4:读者受益问题 “您认为读者在阅读您的书籍之后,最具体和显著的收获会是什么?有哪些实际的技能或知识可以直接应用到他们的工作和项目中?”

铭毅天下:

1、少走不必要的弯路!

2、能获得属于自己的专属学习路线,能建立专属的知识体系,能将 Elasticsearch 原理、开发、运维、架构技能应用于实战。

2.5 问题5:内容深度和广度问题 “您的书籍是如何平衡Elasticsearch的基础知识和高级技术的?它是否适合所有水平的读者,从初学者到高级用户?对于那些已经具有深厚Elasticsearch知识背景的读者,您的书提供了哪些更深入的见解或独特内容?”

铭毅天下:

1、适合大数据存储和检索领域的初学者,也同样适合有工作经验的中级、高级工程师、架构师等。

2、对于深厚Elasticsearch知识背景的读者,本书可以当做工具书,需要时备查、常翻常新。

三、行业顶级大佬的推荐

3.png

值得一提的是,这本书获得了 Elastic 创始人兼CTO Shay Banon 、Elastic中文社区创始人兼极限科技CTO等15位顶级专家的强力推荐,是一本不可多得的Elasticsearch学习材料。

I am very happy to see that Elasticsearch has been widely used in China, which fully reflects the open source, free and open power of Elastic. This book is derived from the author's 7 years of technical accumulation and embodies the author's love for ElasticStack open source technology. I hope this book can help more people understand Elasticsearch and search technology, so as to discover the great value of data. I am convinced that this book will have a profound impact on Elastic's Chinese community.

我很高兴看到Elasticsearch在中国得到了广泛的应用,这充分体现了Elastic开源、自由、开放的力量。本书源自作者7年的技术积累,体现了作者对ElasticStack开源技术的热爱。希望这本书能够帮助更多的人了解Elasticsearch和搜索技术,从而发现数据的巨大价值。我相信这本书将对 Elastic 的中文社区产生深远的影响。

4.png

——Shay Banon Elastic公司创始人兼首席技术官

很高兴看到铭毅天下的新书出版,《一本书讲透Elasticsearch:原理、进阶与工程实践》是一本值得推荐的新书。它汇集了作者丰富的实战经验,深入探讨 Elasticsearch的 核心原理。书中丰富的图解和清晰的结构使得复杂的知识易于理解和吸收。同时,它覆盖了 Elastic 认证考试的所有考点,助力读者建立全面的认知。此外,书中还包含实战项目,帮助读者将所学技能应用到实际场景中。作者拥有多年实战经验和广泛的影响力,这本书将成为学习和应用 Elasticsearch 的重要指南。

——Medcl,Elastic 中文社区创始人、极限科技创始人

铭毅天下是ES中文社区里少有的常年坚持写作的技术博主,尤其擅长将点状发散的社区讨论进行归纳总结,结合自己的实践和再思考,形成系统性的系列技术文章。本书成于作者在Elasticsearch领域多年的理论知识沉淀,并涵盖了实际应用场景的最佳实践。无论你是Elasticsearch初学者还是有一定经验的开发者,相信都能通过阅读本书而受益匪浅。

—— 吴晓刚 (Wood大叔)携程旅行网 企业数字化平台部 研发总监

在大数据检索和分析领域,Elastic Stack 技术栈有广泛应用,本书从业务场景出发详细介绍了在 Elasticsearch 擅长的各类场景中完成业务系统开发所需的技术栈和技术手段,为用户系统选型和了解整体技术架构提供了指导,可以帮助用户少走弯路,快速完成系统建设。

——张超 《Elasticsearch 源码解析与优化实战》作者, Elasticsearch 内核资深研发工程师

本书基于Elasticsearch最新的8.X版本,涵盖了Elasticsearch更加完整、实时的功能。作者拥有丰富的Elasticsearch和写作经验,语言通俗易懂,内容详尽全面。无论你是初学者还是有一定经验的开发人员,本书都能够为你提供更深入的内容和最佳实践。如果你想系统地学习、掌握Elasticsearch,那么这本书绝对是你不可错过的参考书籍。

—— 魏子珺,阿里巴巴elasticsearch内核专家

很高兴为大家推荐这本关于Elasticsearch的技术书籍。本书涵盖了相当丰富的原理讲解和实现技术,更重要的是对实战场景给出了明确的指导案例和代码片段可供参考和使用。即面向开发人员深入讲解了搜索引擎的核心算法与数据结构,也同时给运维人员提供了关键指标的定义和解读。对于想系统学习的初、中级用户,可以按照章节循序渐进的阅读。对于高级用户来说,也可以从 遇到的问题为切入点,直接从某个具体章节入手来测试、寻求解决方案。铭毅天下是Elastic中文社区长期活跃和积极贡献的明星成员。非常兴奋看到他把自己日积月累的知识精华和经验总结在书中分享给广大读者。我相信本书一定可以帮助到处在任何阶段想学习探索Elasticsearch的用户。

——吴斌,Elastic中文社区主席

《一本书讲透Elasticsearch:原理、进阶与工程实践》是一本由一线开发人员撰写的实战指南。作者凭借多年的 Elasticsearch 咨询和教学经验,将复杂的概念以简明易懂的方式呈现给读者。这本书将帮助你深入了解 Elasticsearch,并理解其背后的原理和逻辑。通过学习本书,你将获得全面的知识,从而能够灵活应用 Elasticsearch 解决各种实际问题。相信这本书将成为你掌握 Elasticsearch 的必备工具。

——阮一鸣,eBay 高级研发经理、极客时间『Elasticsearch 核心技术与实战』课程讲师

铭毅在 Elasticsearch 领域深耕多年,勤奋且专注, 同时运营着国内最大的 ES 社群 ,帮助许多同学成功通过了有难度的 Elastic 认证工程师考试。很高兴看到他的新书出版,都说万事开头难,但我相信这本书能够为ES 初学者铺平道路,扫除障碍,澄清疑虑,快速上手!推荐大家阅读!

——魏彬,中国首位 Elastic 认证工程师

《一本书讲透Elasticsearch:原理、进阶与工程实践 》这本书是我极力推荐的一部作品!

我认识铭毅天下很久了,第一次见面记得是2019年在北京的Elastic开发者大会上,但在这之前,我就经常阅读他关于Elasticsearch的技术分享而神交已久。我了解的铭毅天下是一位拥有丰富的Elasticsearch领域知识和经验的专家,他曾在PB级大数据系统项目中发挥关键作用。实施这种大规模,长周期的复杂项目是非常不容易的,无论从系统设计,到实施过程中的问题解决。因此,来自于实践的真知产出,值得我们开卷。

多年来,铭毅天下一直积极、高效地在各种博客和社交媒体上分享与Elasticsearch相关的内容,并密切同步每个版本的更新。在Elasticsearch上,他不仅持续自我精进,还组织了学习小组和社区,帮助其他对Elasticsearch感兴趣的伙伴一起进步。他还带领150多人通过Elastic工程师认证,为许多人的职业发展贡献了力量。

这本书是铭毅天下多年经验的总结,内容涵盖了几乎全部的Elastic认证考点,而且它来自铭毅天下近7年的博客积累,每一章节都经得起时间的考验。因为抓住了平时学习和使用Elasticsearch当中痛点并总结了最佳实践,这些内容不仅阅读量高,而且转发度也很广泛。无论你是想深入了解Elasticsearch的基础知识还是应用实践,这本书都能满足你的需求。

我相信这本书将为读者提供一次全面而深入的学习体验,帮助他们在Elasticsearch领域取得突破。无论你是初学者还是有经验的专业人士,这本书都是不可或缺的指南。我由衷地推荐这本书,相信它会成为你在Elasticsearch学习和实践中的得力伙伴!

——李捷,Elastic 解决方案架构师 Principle Solution Architect

当得知本书成稿的消息时,我的心情是非常激动的,不管是作为一名技术人,还是作为一名搜索引擎的从业者,以及作为一名Elasticsearch中文社区的参与者和建设者。本书作者与我们一起见证了Elastic生态在国内的起步、发展以及到今天的繁荣;有所不同的是,作者有超强的毅力(就像铭毅天下的名字一样),坚持在这个技术方向上深耕了7年之久,在知识、技术和实践等方面有着深厚的经验积累,不但亲力亲为,而且深谙知识社群与实践社区CoP的操盘之道,在自我成长的同时也打造了优质的同行网络,积极影响了一批技术人,其中的优秀者更是通过了Elatics官方认证,极具含金量。本书的出版,一定会给更多技术人带来直接或间接的帮助,同时在个人成长、知识共享与实践社区等方面在业内树立成功的榜样。让我们一起用技术影响世界影响人!

—— 杨振涛,Elastisearch中文社区深圳主席|vivo互联网 研发总监

Elasticsearch是人工智能和大数据时代不可或缺的重要产品,已经成为开发者必备技能。本书汇集了作者多年开发经验、咨询经验、数千个Elasticsearch爱好者的最佳实战。因此在讲解原理的同时,能深入到最佳实践中去,做到深入浅出,非常适合Elasticsearch的初学者以及进阶者。

—— 付磊,快手Elasticsearch负责人,《Redis开发与运维》作者

Elasticsearch 作为一款强大又灵活的数据分析检索工具,值得每一位后端程序员认真学习。铭毅天下的这本《一本书讲透Elasticsearch:原理、进阶与工程实践》,用浅显易懂的语言介绍了Elasticsearch的概念、原理和实践,非常值得阅读!

—— 程序员小灰,公众号【程序员小灰】运营者,畅销书《漫画算法》作者

铭毅是我的老友,他是一个及其认证踏实和执着追究技术的人,这七年来他一直热心Elasticstack相关技术的步道,热忱帮助社区和公众号里的伙伴,成就不俗。本书是一本实用性极高的Elasticsearch的实践类书籍,更是铭毅倾尽所学之作。通读原稿后,让我非常欣赏的地方在于,它是市面上难得一见的把Elasticsearch原理,实现方式,最佳实践,以及实战案例串联在一起实操类书籍,无论是初学者还是需要进阶学习的人员都能从中获取想要的内容。十分适合想要在企业环境中落地Elasticsearch的人们,因此我诚意把它推荐给广大的技术爱好者和相关从业人员。

——周钰, IBM中国 企业架构师 中国前50 Elastic持证者

Elasticsearch作为一款优秀的开源分布式搜索引擎,被广泛应用在日志分析、站内搜索、指标监控、数据加速等场景,学习并掌握ES,已经成为一个技术工作人员不可或缺的重要技能之一。而本书深入浅出,对Elasticsearch的基本概念、设计原理及实践进行了详细介绍,是学习Elasticsearch的必备资料。诚挚推荐。

—— 吴荣,Elasticsearch平台资深研发工程师

一份专业、细致、用户友好的技术文档能给我们技术人员的日常工作带来多大的帮助,相信大家都有深刻的体会,特别是像Elasticsearch这种在搜索引擎领域最广泛应用的解决方案更是如此。虽然官方文档内容很详尽,更新很及时,但是限于语言、网速等问题,广大国内开发者并不能很准确高效的找到自己需要的内容。铭毅老师这本,兼顾了内容的专业性、严谨性、完整性,围绕着Elasticsearch及其相关组件所撰写,覆盖了从基础概念到高级用法的方方面面内容的专业书籍,能给各位带来的价值就不言而喻了。这本书适合从入门使用到高级调优的各层次的读者,是一本少有的适合放在案头常看常新的书。

—— 陈晨(死敌wen),资深搜索架构师、Elastic认证专家

5.png

15位大佬评价批量导入 Elasticsearch

15位大佬评价 Kibana 可视化

6.png

15位大佬评价词云图

7.png

无论您是大数据检索领域的初学者、开发和运维人员,还是架构师和管理人员,这本书都将成为实战路上的得力助手和“避坑指南”。

8.png

立即购买以获取专属福利:不论您从哪里购买、不论多少费用购买,记得保留购物链接和发票,费用都可以折算同等价格的星球优惠券。

私V信:elastic6 搞定后续一切流程。 ————————————————

                        本文为博主原创文章,未经博主书面授权不得转载。书面授权后方可转载,但转载请务必加上原作者:铭毅天下,原文地址:blog.csdn.net/laoyang360

原文链接:https://blog.csdn.net/laoyang360/article/details/135614659

收起阅读 »

从白日梦到现实:推出 Elastic 的管道查询语言 ES|QL

原文:https://elasticstack.blog.csdn ... 86439


!(https://img-blog.csdnimg.cn/a5 ... 63.png)

今天,我们很高兴地宣布 Elastic® 的新管道查询语言 [ES|QL](https://www.elastic.co/guide/e ... .html "ES|QL")(Elasticsearch 查询语言)的技术预览版,它可以转换、丰富和简化数据调查。 ES|QL 由新的查询引擎提供支持,通过并发处理提供高级搜索功能,无论数据源和结构如何,都可以提高速度和效率。 通过在单个屏幕上创建聚合和可视化来快速解决问题,以实现迭代和流畅的工作流程。

ES|QL 介绍

Elasticsearch 的演变
-----------------

在过去 13 年中,[Elasticsearch®](https://www.elastic.co/elasticsearch/ "Elasticsearch®") 取得了显着发展,适应了用户需求和不断变化的数字环境。 Elasticsearch 最初用于全文搜索,后来根据用户反馈扩展到支持更广泛的用例。 在整个过程中,Elasticsearch [Query DSL](https://www.elastic.co/guide/e ... .html "Query DSL")(我们第一个采用的搜索语言)为过滤器、聚合和其他操作提供了丰富的查询集。 这种基于 JSON 的 DSL 最终成为我们 [_search](https://www.elastic.co/guide/e ... .html "_search") API 端点的基础。

随着时间的推移和需求的多样化,逐渐显现出用户需要的不仅仅是查询 DSL 所提供的功能。我们开始在查询 DSL 下引入和融合了其他 DSL,用于[脚本编写](https://www.elastic.co/guide/e ... .html "脚本编写")、安全调查中的[事件](https://www.elastic.co/guide/e ... .html "事件")等等。然而,尽管这些扩展功能非常多才多艺,它们并没有完全满足用户的一些需求。

用户想要一种能够:

*   简化威胁和安全调查,同时通过提供全面和迭代方法的单个查询观察和解决生产问题
*   通过单一界面搜索、丰富、聚合和可视化更多内容来简化数据调查
*   使用高级搜索功能(例如带有并发处理的查找)提高查询大量数据的速度和效率,无论来源和结构如何

更多阅读,请点击 https://elasticstack.blog.csdn ... 86439
继续阅读 »
原文:https://elasticstack.blog.csdn ... 86439


!(https://img-blog.csdnimg.cn/a5 ... 63.png)

今天,我们很高兴地宣布 Elastic® 的新管道查询语言 [ES|QL](https://www.elastic.co/guide/e ... .html "ES|QL")(Elasticsearch 查询语言)的技术预览版,它可以转换、丰富和简化数据调查。 ES|QL 由新的查询引擎提供支持,通过并发处理提供高级搜索功能,无论数据源和结构如何,都可以提高速度和效率。 通过在单个屏幕上创建聚合和可视化来快速解决问题,以实现迭代和流畅的工作流程。

ES|QL 介绍

Elasticsearch 的演变
-----------------

在过去 13 年中,[Elasticsearch®](https://www.elastic.co/elasticsearch/ "Elasticsearch®") 取得了显着发展,适应了用户需求和不断变化的数字环境。 Elasticsearch 最初用于全文搜索,后来根据用户反馈扩展到支持更广泛的用例。 在整个过程中,Elasticsearch [Query DSL](https://www.elastic.co/guide/e ... .html "Query DSL")(我们第一个采用的搜索语言)为过滤器、聚合和其他操作提供了丰富的查询集。 这种基于 JSON 的 DSL 最终成为我们 [_search](https://www.elastic.co/guide/e ... .html "_search") API 端点的基础。

随着时间的推移和需求的多样化,逐渐显现出用户需要的不仅仅是查询 DSL 所提供的功能。我们开始在查询 DSL 下引入和融合了其他 DSL,用于[脚本编写](https://www.elastic.co/guide/e ... .html "脚本编写")、安全调查中的[事件](https://www.elastic.co/guide/e ... .html "事件")等等。然而,尽管这些扩展功能非常多才多艺,它们并没有完全满足用户的一些需求。

用户想要一种能够:

*   简化威胁和安全调查,同时通过提供全面和迭代方法的单个查询观察和解决生产问题
*   通过单一界面搜索、丰富、聚合和可视化更多内容来简化数据调查
*   使用高级搜索功能(例如带有并发处理的查找)提高查询大量数据的速度和效率,无论来源和结构如何

更多阅读,请点击 https://elasticstack.blog.csdn ... 86439 收起阅读 »

ES 关于 remote_cluster 的一记小坑

最近有小伙伴找到我们说 Kibana 上添加不了 Remote Cluster,填完信息点 Save 直接跳回原界面了。具体页面,就和没添加前一样。

我们和小伙伴虽然隔着网线但还是进行了深入、详细的交流,梳理出来了如下信息:

  1. 两个集群:集群 A 和集群 B ,版本都是 7.10.0 ;
    1. 集群 A 没区分节点角色;
    2. 集群 B 设置了 独立的 master 节点、coordinator 节点和 data 节点,其中 data 节点还带 remote_cluster_client 角色;
  2. 在集群 A 的 Kibana 可以添加 集群 B 为远程集群;
  3. 在集群 B 添加 集群 A 就不行,Kibana 跳回之前的页面;
  4. 网络组确认已经放开策略,网络测试也正常;

翻看了 ES 和 Kibana 的日志, ES 日志中有连接失败的错误信息, Kibana 日志中无对应输出。

[2023-09-13T11:38:41,055][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,055][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:41,056][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,056][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:41,057][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,057][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:41,093][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,094][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:41,094][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,094][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:41,095][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,096][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:51,099][WARN ][o.e.t.RemoteClusterService] [710-1] failed to connect to new remote cluster test within 10s
[2023-09-13T11:39:11,101][WARN ][o.e.t.SniffConnectionStrategy] [710-1] fetching nodes from external cluster [test] failed
org.elasticsearch.transport.ConnectTransportException: [][127.0.0.1:7102] handshake_timeout[30s]
    at org.elasticsearch.transport.TransportHandshaker.lambda$sendHandshake$1(TransportHandshaker.java:73) ~[elasticsearch-7.10.2.jar:7.10.2]
    at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:684) ~[elasticsearch-7.10.2.jar:7.10.2]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) [?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) [?:?]
    at java.lang.Thread.run(Thread.java:832) [?:?]

已经测试过网络是通的,开始尝试把集群 B 的角色配置统统去掉再尝试。
嘿,添加成功了。
接下来为了找出问题,开始一步一步给每个节点再加回原来的角色。而且如果节点原来没有 remote_cluster_client 角色,这次也一并加上。
操作过程

  • 先从 data 节点开始,恢复角色,尝试添加远程集群,失败。
  • 接着 coordinate 节点 , 恢复角色且新增 remote_cluster_client 角色,尝试添加远程集群,失败。
  • 最后 master 节点,恢复角色且新增 remote_cluster_client 角色,尝试添加远程集群,成功。

最终直到所有节点都有 remote_cluster_client 角色后,才成功添加远程集群。
结论: ES 集群添加远程集群所有节点都必须拥有 remote_cluster_client 角色。
事情到这里,似乎没什么问题。但当我们对这个结论进行检验时,又有了新发现。
上面的场景忽视了一个因素 -- Kibana 。于是我们搭建了一个两个节点的集群,其中节点 A 是全角色节点,节点 B 只是 data 节点。让 Kibana 分别连接两个节点进行测试。
验证结果

  • 当 Kibana 连接节点 A 时,可以正常添加。
  • Kibana 连接节点 B 时,添加失败,跳回界面。

结论:ES 集群添加远程集群时,Kibana 连接的 ES 节点必须拥有 remote_cluster_client 角色。
很显然,这个结论更合理。

原因分析
我们是通过 Kibana 界面操作去添加远程集群的, Kibana 连接的节点就被当作 remote_client 。该节点要向远程集群发起连接并执行相关调用。但这一切有个前提,该节点必须有 remote_cluster_client 角色才能向远程集群发起连接。 引申
我们的 CCS 操作也必须发送到一个具有 remote_cluster_client 角色的节点,才能成功执行。

参考连接 https://www.elastic.co/guide/en/elasticsearch/reference/7.10/modules-node.html

继续阅读 »

最近有小伙伴找到我们说 Kibana 上添加不了 Remote Cluster,填完信息点 Save 直接跳回原界面了。具体页面,就和没添加前一样。

我们和小伙伴虽然隔着网线但还是进行了深入、详细的交流,梳理出来了如下信息:

  1. 两个集群:集群 A 和集群 B ,版本都是 7.10.0 ;
    1. 集群 A 没区分节点角色;
    2. 集群 B 设置了 独立的 master 节点、coordinator 节点和 data 节点,其中 data 节点还带 remote_cluster_client 角色;
  2. 在集群 A 的 Kibana 可以添加 集群 B 为远程集群;
  3. 在集群 B 添加 集群 A 就不行,Kibana 跳回之前的页面;
  4. 网络组确认已经放开策略,网络测试也正常;

翻看了 ES 和 Kibana 的日志, ES 日志中有连接失败的错误信息, Kibana 日志中无对应输出。

[2023-09-13T11:38:41,055][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,055][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:41,056][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,056][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:41,057][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,057][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:41,093][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,094][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:41,094][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,094][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:41,095][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.mode] from [SNIFF] to [sniff]
[2023-09-13T11:38:41,096][INFO ][o.e.c.s.ClusterSettings  ] [710-1] updating [cluster.remote.test.seeds] from [[]] to [["127.0.0.1:7102"]]
[2023-09-13T11:38:51,099][WARN ][o.e.t.RemoteClusterService] [710-1] failed to connect to new remote cluster test within 10s
[2023-09-13T11:39:11,101][WARN ][o.e.t.SniffConnectionStrategy] [710-1] fetching nodes from external cluster [test] failed
org.elasticsearch.transport.ConnectTransportException: [][127.0.0.1:7102] handshake_timeout[30s]
    at org.elasticsearch.transport.TransportHandshaker.lambda$sendHandshake$1(TransportHandshaker.java:73) ~[elasticsearch-7.10.2.jar:7.10.2]
    at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:684) ~[elasticsearch-7.10.2.jar:7.10.2]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) [?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) [?:?]
    at java.lang.Thread.run(Thread.java:832) [?:?]

已经测试过网络是通的,开始尝试把集群 B 的角色配置统统去掉再尝试。
嘿,添加成功了。
接下来为了找出问题,开始一步一步给每个节点再加回原来的角色。而且如果节点原来没有 remote_cluster_client 角色,这次也一并加上。
操作过程

  • 先从 data 节点开始,恢复角色,尝试添加远程集群,失败。
  • 接着 coordinate 节点 , 恢复角色且新增 remote_cluster_client 角色,尝试添加远程集群,失败。
  • 最后 master 节点,恢复角色且新增 remote_cluster_client 角色,尝试添加远程集群,成功。

最终直到所有节点都有 remote_cluster_client 角色后,才成功添加远程集群。
结论: ES 集群添加远程集群所有节点都必须拥有 remote_cluster_client 角色。
事情到这里,似乎没什么问题。但当我们对这个结论进行检验时,又有了新发现。
上面的场景忽视了一个因素 -- Kibana 。于是我们搭建了一个两个节点的集群,其中节点 A 是全角色节点,节点 B 只是 data 节点。让 Kibana 分别连接两个节点进行测试。
验证结果

  • 当 Kibana 连接节点 A 时,可以正常添加。
  • Kibana 连接节点 B 时,添加失败,跳回界面。

结论:ES 集群添加远程集群时,Kibana 连接的 ES 节点必须拥有 remote_cluster_client 角色。
很显然,这个结论更合理。

原因分析
我们是通过 Kibana 界面操作去添加远程集群的, Kibana 连接的节点就被当作 remote_client 。该节点要向远程集群发起连接并执行相关调用。但这一切有个前提,该节点必须有 remote_cluster_client 角色才能向远程集群发起连接。 引申
我们的 CCS 操作也必须发送到一个具有 remote_cluster_client 角色的节点,才能成功执行。

参考连接 https://www.elastic.co/guide/en/elasticsearch/reference/7.10/modules-node.html

收起阅读 »

如何在ES中搜索值为空的键值对

问题背景

今天早上,接到开发那边一个特殊的查询需求,在 Kibana 中搜索一个 json 类型日志中值为一个空大括号的键值对, 具体的日志示例如下:

{
    "clientIp": "10.111.121.51",
    "query": "{}",
    "serviceUrl": "/aaa/bbb/cc",
}

也就是说针对这个类型的日志过滤出 query 值为空的请求 "query": "{}", 开发同学测试了直接在 kibana 中查询这个字符串 "query": "{}" 根本查不到我们想要的结果。 我们使用的是 ELK 8.3 的全家桶, 这个日志数据使用的默认 standard analyzer 的分词器。

初步分析

我们先对这个要查询的字符串进行下分词测试:

GET /_analyze
{
"analyzer" : "standard",
"text": "\"query\":\"{}\""
}

结果不出所料,我们想要空大括号在分词的时候直接就被干掉了,仅保留了 query 这一个 token:

{
  "tokens": [{
    "token": "query",
    "start_offset": 1,
    "end_offset": 6,
    "type": "<ALPHANUM>",
    "position": 0
  }]
}

我们使用的 standard analyzer 在数据写入分词时直接抛弃掉{}等特殊字符,看来直接搜索 "query": "{}" 关键词这条路肯定是走不通。

换个思路

在网上搜索了一下解决的办法,有些搜索特殊字符的办法,但需要修改分词器,我们已经写入的日志数据量比较大,不太愿意因为这个搜索请求来修改分词器再 reindex。 但是我们的日志格式是固定的,serviceUrl 这个键值对总是在 query 后面的,那么我们可以结合前后文实现相同的 搜索效果:

GET /_analyze
{
"analyzer" : "standard",
"text": "\"query\":\"{}\",\"serviceUrl\""
}

可以看到这段被分为 2 个相邻的单词

{
"tokens": [{
"token": "query",
"start_offset": 1,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "serviceurl",
"start_offset": 14,
"end_offset": 24,
"type": "<ALPHANUM>",
"position": 1
}
]
}

那么通过搜索 query 和 serviceUrl 为相邻的 2 个字是完全可以实现 query 的值为空的同样的查询效果。 为了确认在我们已经写入的数据中 query 和 serviceurl 也是相邻的,我们通过 ES termvectors API 确认了已经在 es 中的数据和我们这里测试的情况相同:

GET /<index>/_termvectors/<_id>?fields=message

"query" : {
  "term_freq" : 1,
  "tokens" : [
    {
      "position" : 198,
      "start_offset" : 2138,
      "end_offset" : 2143
    }
  ]
},
"serviceurl" : {
  "term_freq" : 1,
  "tokens" : [
    {
      "position" : 199,
      "start_offset" : 2151,
      "end_offset" : 2161
    }
  ]
},

这里我们可以看到 query 在 message 字段里面出现一次,其 end_offset 和 serviceurl 的 start_offset 之前也是相差 8, 和我们测试的结果相同。 这个时候我们就将原来的查询需求,转化为了对 "query serviceurl" 进行按顺序的精准查询就行了, 使用 match_phrase 可以达到我们的目的。

GET /_search
"query": {
    "match_phrase": {
        "message": {
            "query": "query serviceurl",
            "slop" : 0

        }
    }
}

这里顺便说一下,slop 这个参数,slop=n 表示,表示可以隔 n 个字(英文词)进行匹配, 这里设置为 0 就强制要求 query 和 serviceurl 这 2 个单词必须相邻,0 也是 slop 的默认值,在这个请求中是可以省略的,这是为什么 match_phrase 是会获得精准查询的原因之一。 好了,我们通过 console 确定了有效的 query 之后,对于开发同学查看日志只需要在 Kibana 的搜索栏中直接使用双引号引起来的精确搜索 "query serviceurl" 就可以了。

继续深挖一下,ngram 分词器

虽然开发同学搜索的问题解决了,但我仍然不太满意,毕竟这次的问题我们的日志格式是固定的,如果我们一定要搜索到 "query": "{}" 这个应该怎么办呢? 首先很明确,使用我们默认的 standard analyzer 不修改任何参数肯定是不行的,"{}" 这些特殊字符都直接被干掉了, 参考了网上找到的这篇文章,https://blog.csdn.net/fox_233/article/details/127388058 按照这个 ngram 分词器的思路,我动手对我们的需求进行了下测试

首先先看看我们使用 ngram 分词器的分词效果, 我们这里简化了一下,去掉了原来的双引号,以避免过多 \:

GET _analyze
{
  "tokenizer": "ngram",
  "text": "query:{}"
}

{
  "tokens" : [
    {
      "token" : "q",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "word",
      "position" : 0
    },
    ...
    {
      "token" : "{",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "word",
      "position" : 12
    },
    {
      "token" : "{}",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "word",
      "position" : 13
    },
    {
      "token" : "}",
      "start_offset" : 7,
      "end_offset" : 8,
      "type" : "word",
      "position" : 14
    }
  ]
}

可以很明显的看到大括号被成功的分词了,果然是有戏。 直接定义一个 index 实战一下搜索效果

PUT specialchar_debug
{
  "settings": {
    "analysis": {
      "analyzer": {
        "specialchar_analyzer": {
          "tokenizer": "specialchar_tokenizer"
        }
      },
      "tokenizer": {
        "specialchar_tokenizer": {
          "type": "ngram",
          "min_gram": 1,
          "max_gram": 2
        }
      }
    }
  },
  "mappings": {
      "properties": {
        "text": {
          "analyzer": "specialchar_analyzer",
          "type": "text"
        }
      }
    }
}

插入几条测试数据:

PUT specialchar_debug/_doc/1
{  "text": "query:{},serviceUrl"
}

PUT specialchar_debug/_doc/2
{  "text": "query:{aaa},serviceUrl"
}

PUT specialchar_debug/_doc/3
{  "text": "query:{bbb}, ccc, serviceUrl"
}

我们再测试一下搜索效果,

GET specialchar_debug/_search
{
  "query": {
    "match_phrase": {
      "text": "query:{}"
    }
  }
}

结果完全是我们想要的,看来这个方案可行

"hits" : [
  {
    "_index" : "specialchar_debug",
    "_id" : "1",
    "_score" : 2.402917,
    "_source" : {
      "text" : "query:{},serviceUrl"
    }
  }
]

小结

对于日志系统,我们一直在使用 ES 默认的 standard analyzer 的分词器, 基本上满足我们生产遇到的 99% 的需求,但面对特殊字符的这种搜索请求,确实比较无奈。这次遇到的空键值对的需求,我们通过搜索 2 个相邻的键绕过了问题。 如果一定要搜索这个字符串的话,我们也可以使用 ngram 分词器重新进行分词再进行处理, 条条大路通罗马。

作者介绍

卞弘智,研发工程师,10 多年的 SRE 经验,工作经历涵盖 DevOps,日志处理系统,监控和告警系统研发,WAF 和网关等系统基础架构领域,致力于通过优秀的开源软件推动自动化和智能化基础架构平台的演进。

继续阅读 »

问题背景

今天早上,接到开发那边一个特殊的查询需求,在 Kibana 中搜索一个 json 类型日志中值为一个空大括号的键值对, 具体的日志示例如下:

{
    "clientIp": "10.111.121.51",
    "query": "{}",
    "serviceUrl": "/aaa/bbb/cc",
}

也就是说针对这个类型的日志过滤出 query 值为空的请求 "query": "{}", 开发同学测试了直接在 kibana 中查询这个字符串 "query": "{}" 根本查不到我们想要的结果。 我们使用的是 ELK 8.3 的全家桶, 这个日志数据使用的默认 standard analyzer 的分词器。

初步分析

我们先对这个要查询的字符串进行下分词测试:

GET /_analyze
{
"analyzer" : "standard",
"text": "\"query\":\"{}\""
}

结果不出所料,我们想要空大括号在分词的时候直接就被干掉了,仅保留了 query 这一个 token:

{
  "tokens": [{
    "token": "query",
    "start_offset": 1,
    "end_offset": 6,
    "type": "<ALPHANUM>",
    "position": 0
  }]
}

我们使用的 standard analyzer 在数据写入分词时直接抛弃掉{}等特殊字符,看来直接搜索 "query": "{}" 关键词这条路肯定是走不通。

换个思路

在网上搜索了一下解决的办法,有些搜索特殊字符的办法,但需要修改分词器,我们已经写入的日志数据量比较大,不太愿意因为这个搜索请求来修改分词器再 reindex。 但是我们的日志格式是固定的,serviceUrl 这个键值对总是在 query 后面的,那么我们可以结合前后文实现相同的 搜索效果:

GET /_analyze
{
"analyzer" : "standard",
"text": "\"query\":\"{}\",\"serviceUrl\""
}

可以看到这段被分为 2 个相邻的单词

{
"tokens": [{
"token": "query",
"start_offset": 1,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "serviceurl",
"start_offset": 14,
"end_offset": 24,
"type": "<ALPHANUM>",
"position": 1
}
]
}

那么通过搜索 query 和 serviceUrl 为相邻的 2 个字是完全可以实现 query 的值为空的同样的查询效果。 为了确认在我们已经写入的数据中 query 和 serviceurl 也是相邻的,我们通过 ES termvectors API 确认了已经在 es 中的数据和我们这里测试的情况相同:

GET /<index>/_termvectors/<_id>?fields=message

"query" : {
  "term_freq" : 1,
  "tokens" : [
    {
      "position" : 198,
      "start_offset" : 2138,
      "end_offset" : 2143
    }
  ]
},
"serviceurl" : {
  "term_freq" : 1,
  "tokens" : [
    {
      "position" : 199,
      "start_offset" : 2151,
      "end_offset" : 2161
    }
  ]
},

这里我们可以看到 query 在 message 字段里面出现一次,其 end_offset 和 serviceurl 的 start_offset 之前也是相差 8, 和我们测试的结果相同。 这个时候我们就将原来的查询需求,转化为了对 "query serviceurl" 进行按顺序的精准查询就行了, 使用 match_phrase 可以达到我们的目的。

GET /_search
"query": {
    "match_phrase": {
        "message": {
            "query": "query serviceurl",
            "slop" : 0

        }
    }
}

这里顺便说一下,slop 这个参数,slop=n 表示,表示可以隔 n 个字(英文词)进行匹配, 这里设置为 0 就强制要求 query 和 serviceurl 这 2 个单词必须相邻,0 也是 slop 的默认值,在这个请求中是可以省略的,这是为什么 match_phrase 是会获得精准查询的原因之一。 好了,我们通过 console 确定了有效的 query 之后,对于开发同学查看日志只需要在 Kibana 的搜索栏中直接使用双引号引起来的精确搜索 "query serviceurl" 就可以了。

继续深挖一下,ngram 分词器

虽然开发同学搜索的问题解决了,但我仍然不太满意,毕竟这次的问题我们的日志格式是固定的,如果我们一定要搜索到 "query": "{}" 这个应该怎么办呢? 首先很明确,使用我们默认的 standard analyzer 不修改任何参数肯定是不行的,"{}" 这些特殊字符都直接被干掉了, 参考了网上找到的这篇文章,https://blog.csdn.net/fox_233/article/details/127388058 按照这个 ngram 分词器的思路,我动手对我们的需求进行了下测试

首先先看看我们使用 ngram 分词器的分词效果, 我们这里简化了一下,去掉了原来的双引号,以避免过多 \:

GET _analyze
{
  "tokenizer": "ngram",
  "text": "query:{}"
}

{
  "tokens" : [
    {
      "token" : "q",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "word",
      "position" : 0
    },
    ...
    {
      "token" : "{",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "word",
      "position" : 12
    },
    {
      "token" : "{}",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "word",
      "position" : 13
    },
    {
      "token" : "}",
      "start_offset" : 7,
      "end_offset" : 8,
      "type" : "word",
      "position" : 14
    }
  ]
}

可以很明显的看到大括号被成功的分词了,果然是有戏。 直接定义一个 index 实战一下搜索效果

PUT specialchar_debug
{
  "settings": {
    "analysis": {
      "analyzer": {
        "specialchar_analyzer": {
          "tokenizer": "specialchar_tokenizer"
        }
      },
      "tokenizer": {
        "specialchar_tokenizer": {
          "type": "ngram",
          "min_gram": 1,
          "max_gram": 2
        }
      }
    }
  },
  "mappings": {
      "properties": {
        "text": {
          "analyzer": "specialchar_analyzer",
          "type": "text"
        }
      }
    }
}

插入几条测试数据:

PUT specialchar_debug/_doc/1
{  "text": "query:{},serviceUrl"
}

PUT specialchar_debug/_doc/2
{  "text": "query:{aaa},serviceUrl"
}

PUT specialchar_debug/_doc/3
{  "text": "query:{bbb}, ccc, serviceUrl"
}

我们再测试一下搜索效果,

GET specialchar_debug/_search
{
  "query": {
    "match_phrase": {
      "text": "query:{}"
    }
  }
}

结果完全是我们想要的,看来这个方案可行

"hits" : [
  {
    "_index" : "specialchar_debug",
    "_id" : "1",
    "_score" : 2.402917,
    "_source" : {
      "text" : "query:{},serviceUrl"
    }
  }
]

小结

对于日志系统,我们一直在使用 ES 默认的 standard analyzer 的分词器, 基本上满足我们生产遇到的 99% 的需求,但面对特殊字符的这种搜索请求,确实比较无奈。这次遇到的空键值对的需求,我们通过搜索 2 个相邻的键绕过了问题。 如果一定要搜索这个字符串的话,我们也可以使用 ngram 分词器重新进行分词再进行处理, 条条大路通罗马。

作者介绍

卞弘智,研发工程师,10 多年的 SRE 经验,工作经历涵盖 DevOps,日志处理系统,监控和告警系统研发,WAF 和网关等系统基础架构领域,致力于通过优秀的开源软件推动自动化和智能化基础架构平台的演进。

收起阅读 »