前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Elasticsearch最佳实践:不同版本之间的存储成本对比

Elasticsearch最佳实践:不同版本之间的存储成本对比

原创
作者头像
点火三周
修改2023-10-25 20:58:57
2.7K0
修改2023-10-25 20:58:57
举报
文章被收录于专栏:Elastic Stack专栏Elastic Stack专栏

作为日志分析场景中最广泛使用的技术解决方案之一,Elasticsearch经常被竞争对手进行比较。特别是随着日志数据量的增加,日志场景中广泛比较的核心指标包括数据写入吞吐量、存储成本、查询速度和分析能力。作为一个不断创新和迭代的产品,Elasticsearch 在日志分析场景中不断引入不同的新功能,以满足客户在日志场景中不断增长的需求。

Elasticsearch多版本间的性能更新
Elasticsearch多版本间的性能更新

然而,竞争对手常常误导性地使用低版本的 Elasticsearch 进行基准测试,然后进行指标对比,并得出其比 Elasticsearch 更为优秀的结论。这种比较大多数时候是非常不客观的,也是具有误导的,要知道 6.x 版本已经过时,而 7.10 版本也已经发布了很长一段时间。在8.8到7.10之间的15个版本当中,Elasticsearch 发布了非常多的性能优化特性,因此,为了帮助用户更好地了解最新版本的Elasticsearch所具备的功能,我将在本文之后的一系列文章中从多个维度比较旧版本和新版本的 Elasticsearch,以帮助我们的用户在进行技术选择时做出更准确的评估,并提供精确的数据。

测试前置条件

在本文中,我们将比较 Elasticsearch 在存储日志数据和指标数据方面,在版本6、版本7和版本8之间的差异。注意,这里的比较,将不做任何的配置上的优化,也就是说,在不开启任何场景调优选项的情况下,单纯比较版本间,在相同数据集上的默认存储消耗。而在接下去的系列文章中,我们再根据场景,进行场景优化。

数据源和版本选择

为了尽可能真实地呈现实际环境中的情况,我们将使用由 Apache SkyWalking showcase 生成的日志和指标数据作为我们的数据来源。在选择 Elasticsearch 的版本时,我们会选择最广泛使用的版本,而不会涉及所有子版本。对于6.x版本,我们将选择6.8作为测试版本;对于7.x版本,我们将选择7.10。这主要是因为在7.10版本中,Elastic进行了许可证的更改,使其成为许多云服务提供商支持的 Elasticsearch 版本的分水岭。同时,我们注意到 Opensearch 也是从这个版本中分支出来的。至于8.x版本,我们将使用腾讯云提供的最新版本8.8.1。

配置

在测试过程中,我们将专注于对 SkyWalking 的原始配置进行测试,而不涉及任何索引层面的优化。我们这样做的目的是为了验证在不掌握专业 Elasticsearch 调优知识的情况下,仅通过对Elasticsearch进行升级,是否能够达到预期的效果。这种方法能够提供清晰而直观的结果,同时也帮助我们了解在不进行索引层面的优化情况下,Elasticsearch的性能表现如何。

在测试开始之前,我们会确保不同版本的集群使用相同的数据结构来存储数据。这意味着我们会将索引的mapping分别拷贝到三个集群上,并使用同样的数据,即将相同的索引数据写入三个集群。

这里,我们首先将 SkyWalking 上的数据写入Elasticsearch 8.8.1集群,然后进行数据镜像,将数据拷贝到6.8和7.10集群。这样,数据的模式、数量和内容都是相同的。同时,我们将配置相同的压缩参数(默认值)并将索引进行一次段合并。

日志数据对比

以下是 SkyWalking 日志数据的schema:

代码语言:json
复制
{
  "settings": {
    "number_of_shards": 5,
    "number_of_replicas": 1,
    "analysis": {
        "analyzer": {
          "oap_log_analyzer": {
            "type": "standard"
          }
        }
      }
  }, 
  "mappings": {
    "_source": {
      "excludes": [
        "tags"
      ]
    },
    "properties": {
      "content": {
        "type": "text",
        "copy_to": [
          "content_match"
        ]
      },
      "content_match": {
        "type": "text",
        "analyzer": "oap_log_analyzer"
      },
      "content_type": {
        "type": "integer",
        "index": false
      },
      "endpoint_id": {
        "type": "keyword"
      },
      "service_id": {
        "type": "keyword"
      },
      "service_instance_id": {
        "type": "keyword"
      },
      "span_id": {
        "type": "integer"
      },
      "tags": {
        "type": "keyword"
      },
      "tags_raw_data": {
        "type": "binary"
      },
      "time_bucket": {
        "type": "long"
      },
      "timestamp": {
        "type": "long"
      },
      "trace_id": {
        "type": "keyword"
      },
      "trace_segment_id": {
        "type": "keyword"
      },
      "unique_id": {
        "type": "keyword"
      }
    }
  }
}
  • 这个索引有5个分片和0个副本,使用了一个自定义的分析器oap_log_analyzer
  • 这个索引有15个字段,大致可以分为以下几类:
    • 文本类型(text):这些字段用来存储需要分词的字符串,比如content。这些字段可以用来进行全文检索、模糊匹配等操作。
    • 关键词类型(keyword):这些字段用来存储不需要分词的字符串,比如endpoint_idservice_id等。这些字段可以用来进行精确匹配、排序、聚合等操作。
    • 数值类型(integer、long等):这些字段用来存储整数或长整数,比如content_typespan_id等。这些字段可以用来进行数值比较、范围查询、聚合等操作。
    • 二进制类型(binary):这些字段用来存储二进制数据,比如tags_raw_data。这些字段不会被索引或搜索,只能用于存储或检索。
    • 复制类型(copy_to):这些字段用来存储其他字段的值的副本,比如content_match。这些字段可以用来进行多字段查询。
    • 分析器类型(analyzer):这些字段用来指定使用哪种分析器来处理文本,比如content_match。这些字段可以用不同的分词规则来影响搜索结果。

样例为:

代码语言:javascript
复制
      {
        "_index": "sw_log-20231023",
        "_id": "fe620a61abca48b394358015a04a55b8",
        "_score": 1,
        "_source": {
          "trace_id": "9ad5dfed-1def-4ed3-b233-5dce5afa66c8",
          "unique_id": "fe620a61abca48b394358015a04a55b8",
          "span_id": 0,
          "endpoint_id": "c29uZ3M=.1_VW5kZXJ0b3dEaXNwYXRjaA==",
          "service_instance_id": "c29uZ3M=.1_Mzg0ZWZlYWE2NzFjNGFhYjg2ZGFmZjA3OWE4YjljYzZAMTcyLjIyLjAuNg==",
          "content": """2023-10-23 23:59:49.247 [TID:9ad5dfed-1def-4ed3-b233-5dce5afa66c8] [XNIO-1 task-2] INFO  o.a.s.s.s.s.c.SongController -Listing top songs
""",
          "trace_segment_id": "7e097591b9b74531a14df130f17087a8.54.16981055892474632",
          "content_type": 1,
          "tags_raw_data": "Cg0KBWxldmVsEgRJTkZPClAKBmxvZ2dlchJGb3JnLmFwYWNoZS5za3l3YWxraW5nLnNob3djYXNlLnNlcnZpY2VzLnNvbmcuY29udHJvbGxlci5Tb25nQ29udHJvbGxlcgoXCgZ0aHJlYWQSDVhOSU8tMSB0YXNrLTI=",
          "service_id": "c29uZ3M=.1",
          "time_bucket": 20231023235949,
          "timestamp": 1698105589247
        }
      }

我们分别在6.8,7.10,8.8的集群上写入相同的数据,通过_stats/store,segments接口,我们得到三个版本的索引统计信息的区别:

版本

文档数量

存储大小

段数量

内存占用

6.8

166138

91888073字节

5

420658字节

7.10

166138

89639942字节

5

16580字节

8.8

166138

78307161字节

5

0字节

从表格中可以看出,以下是一些主要的区别:

  • 存储大小随着版本的升级而减少,这是因为Elasticsearch对索引结构和压缩算法进行了优化。
    • 相对于6.8版本,8.8版本的存储优化百分比为 ≈14.78%
    • 相对于7.10版本,8.8版本的存储优化百分比为 ≈12.64%
  • 内存占用从6.8到7.10大幅减少,再到到8.8变为0,这是因为Elasticsearch对内存管理进行了改进,即进行了heap-offload,也更改了加载的方式

日志 6.8
日志 6.8
日志 7.10
日志 7.10
日志 8.8
日志 8.8

指标数据对比

以下是 SkyWalking 指标数据的schema:

代码语言:json
复制
{
  "settings": {
    "number_of_replicas": 1,
    "number_of_shards": 1,
    "analysis": {
        "analyzer": {
          "oap_analyzer": {
            "type": "standard"
          }
        }
      }
  }, 
  "mappings": {
    "properties": {
      "address": {
        "type": "keyword"
      },
      "agent_id": {
        "type": "keyword"
      },
      "component_id": {
        "type": "integer",
        "index": false
      },
      "component_ids": {
        "type": "keyword",
        "index": false
      },
      "count": {
        "type": "long",
        "index": false
      },
      "dataset": {
        "type": "text",
        "index": false
      },
      "datatable_count": {
        "type": "text",
        "index": false
      },
      "datatable_summation": {
        "type": "text",
        "index": false
      },
      "datatable_value": {
        "type": "text",
        "index": false
      },
      "denominator": {
        "type": "long"
      },
      "dest_endpoint": {
        "type": "keyword"
      },
      "dest_process_id": {
        "type": "keyword"
      },
      "dest_service_id": {
        "type": "keyword"
      },
      "dest_service_instance_id": {
        "type": "keyword"
      },
      "detect_type": {
        "type": "integer"
      },
      "double_summation": {
        "type": "double",
        "index": false
      },
      "double_value": {
        "type": "double"
      },
      "ebpf_profiling_schedule_id": {
        "type": "keyword"
      },
      "end_time": {
        "type": "long"
      },
      "endpoint": {
        "type": "keyword"
      },
      "endpoint_traffic_name": {
        "type": "keyword",
        "copy_to": [
          "endpoint_traffic_name_match"
        ]
      },
      "endpoint_traffic_name_match": {
        "type": "text",
        "analyzer": "oap_analyzer"
      },
      "entity_id": {
        "type": "keyword"
      },
      "instance_id": {
        "type": "keyword"
      },
      "instance_traffic_name": {
        "type": "keyword",
        "index": false
      },
      "int_value": {
        "type": "integer"
      },
      "label": {
        "type": "keyword"
      },
      "labels_json": {
        "type": "keyword",
        "index": false
      },
      "last_ping": {
        "type": "long"
      },
      "last_update_time_bucket": {
        "type": "long"
      },
      "layer": {
        "type": "integer"
      },
      "match": {
        "type": "long",
        "index": false
      },
      "message": {
        "type": "keyword"
      },
      "metric_table": {
        "type": "keyword"
      },
      "name": {
        "type": "keyword"
      },
      "numerator": {
        "type": "long"
      },
      "parameters": {
        "type": "keyword",
        "index": false
      },
      "percentage": {
        "type": "integer"
      },
      "precision": {
        "type": "integer",
        "index": false
      },
      "process_id": {
        "type": "keyword"
      },
      "profiling_support_status": {
        "type": "integer"
      },
      "properties": {
        "type": "text",
        "index": false
      },
      "remote_service_name": {
        "type": "keyword"
      },
      "represent_service_id": {
        "type": "keyword"
      },
      "represent_service_instance_id": {
        "type": "keyword"
      },
      "s_num": {
        "type": "long",
        "index": false
      },
      "service": {
        "type": "keyword"
      },
      "service_group": {
        "type": "keyword"
      },
      "service_id": {
        "type": "keyword"
      },
      "service_instance": {
        "type": "keyword"
      },
      "service_instance_id": {
        "type": "keyword"
      },
      "service_name": {
        "type": "keyword"
      },
      "service_traffic_name": {
        "type": "keyword",
        "copy_to": [
          "service_traffic_name_match"
        ]
      },
      "service_traffic_name_match": {
        "type": "text",
        "analyzer": "oap_analyzer"
      },
      "short_name": {
        "type": "keyword"
      },
      "source_endpoint": {
        "type": "keyword"
      },
      "source_process_id": {
        "type": "keyword"
      },
      "source_service_id": {
        "type": "keyword"
      },
      "source_service_instance_id": {
        "type": "keyword"
      },
      "span_name": {
        "type": "keyword"
      },
      "start_time": {
        "type": "long"
      },
      "summation": {
        "type": "long",
        "index": false
      },
      "t_num": {
        "type": "long",
        "index": false
      },
      "tag_key": {
        "type": "keyword"
      },
      "tag_type": {
        "type": "keyword"
      },
      "tag_value": {
        "type": "keyword"
      },
      "task_id": {
        "type": "keyword"
      },
      "time_bucket": {
        "type": "long"
      },
      "total": {
        "type": "long",
        "index": false
      },
      "total_num": {
        "type": "long",
        "index": false
      },
      "type": {
        "type": "keyword"
      },
      "uuid": {
        "type": "keyword"
      },
      "value": {
        "type": "long"
      }
    }
  }
}
  • 这个索引有一个副本和一个分片,使用了一个自定义的分析器oap_analyzer
  • 这个索引有很多字段,大致可以分为以下几类:
    • 关键词类型(keyword):这些字段用来存储不需要分词的字符串,比如addressagent_iddest_endpoint等。这些字段可以用来进行精确匹配、排序、聚合等操作。
    • 文本类型(text):这些字段用来存储需要分词的字符串,比如datasetdatatable_countdatatable_summation等。这些字段可以用来进行全文检索、模糊匹配等操作。
    • 数值类型(integer、long、double等):这些字段用来存储整数或浮点数,比如component_idcountdouble_value等。这些字段可以用来进行数值比较、范围查询、聚合等操作。
    • 二进制类型(binary):这些字段用来存储二进制数据,比如uuid。这些字段不会被索引或搜索,只能用于存储或检索。
    • 复制类型(copy_to):这些字段用来存储其他字段的值的副本,比如endpoint_traffic_name_matchservice_traffic_name_match等。这些字段可以用来进行多字段查询。
    • 分析器类型(analyzer):这些字段用来指定使用哪种分析器来处理文本,比如endpoint_traffic_name_matchservice_traffic_name_match等。这些字段可以用不同的分词规则来影响搜索结果。

样例数据为:

代码语言:json
复制
{
        "_index": "sw_metrics-all-20231023",
        "_id": "meter_datasource_202310230003_c29uZ3M=.1_Mzg0ZWZlYWE2NzFjNGFhYjg2ZGFmZjA3OWE4YjljYzZAMTcyLjIyLjAuNg==",
        "_score": 1,
        "_source": {
          "metric_table": "meter_datasource",
          "datatable_summation": "8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-minimumIdle,30|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-threadsAwaitingConnection,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-connectionTimeout,90000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleConnections,30|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleTimeout,1800000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-validationTimeout,15000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-activeConnections,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-leakDetectionThreshold,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-maximumPoolSize,30|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-totalConnections,30",
          "datatable_value": "8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-minimumIdle,10|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-threadsAwaitingConnection,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-connectionTimeout,30000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleConnections,10|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleTimeout,600000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-validationTimeout,5000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-activeConnections,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-leakDetectionThreshold,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-maximumPoolSize,10|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-totalConnections,10",
          "service_id": "c29uZ3M=.1",
          "datatable_count": "8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-minimumIdle,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-threadsAwaitingConnection,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-connectionTimeout,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleConnections,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleTimeout,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-validationTimeout,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-activeConnections,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-leakDetectionThreshold,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-maximumPoolSize,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-totalConnections,3",
          "time_bucket": 202310230003,
          "entity_id": "c29uZ3M=.1_Mzg0ZWZlYWE2NzFjNGFhYjg2ZGFmZjA3OWE4YjljYzZAMTcyLjIyLjAuNg=="
        }
      }

我们分别在6.8,7.10,8.8的集群上写入相同的数据,通过_stats/store,segments接口,我们得到三个版本的索引统计信息的区别:

版本

文档数量

存储大小

段数量

内存占用

6.8

1672526

273004812字节

2

43509字节

7.10

1672526

171867470字节

2

53304字节

8.8

1672526

157943758字节

2

0字节

从表格中可以看出,以下是一些主要的区别:

  • 存储大小随着版本的升级而减少,8.8版本的存储大小是157943758字节,比6.8版本的存储大小减少了41.2%,比7.10版本的存储大小减少了8.2%。这说明8.8版本在文档压缩和索引优化方面有很大的改进,特别是当索引中含有比较多的keyword和数值类型字段时。

指标 6.8
指标 6.8
指标 7.10
指标 7.10
指标 8.8
指标 8.8

总结

Elasticsearch 是一个强大的分布式搜索和分析引擎,它可以帮助用户快速地处理海量的日志数据,并从中发现有价值的洞察。随着 Elasticsearch 的不断更新和优化,它在日志分析场景中的表现也越来越出色,无论是在存储空间、查询效率还是分析功能方面,都有着显著的提升。本文通过对比 Elasticsearch 的三个版本(6.8、7.10和8.8)在同样数据上的索引大小,展示了它们在日志分析场景中存储成本差异。

在测试结果中,我们可以看到,在未经过任何优化的情况下:

  • 日志场景中,相对于6.8版本,8.8版本的存储优化百分比约为14.78%。相对于7.10版本,8.8版本的存储优化百分比约为12.64%。从6.8版本到7.10版本,内存占用大幅减少,而到了8.8版本则为0。这是因为Elasticsearch对内存管理进行了改进,采用了堆外内存加载的方式。
  • 在指标数据方面,8.8版本,比6.8版本减少了41.2%,比7.10版本减少了8.2%。这表明8.8版本在文档压缩和索引优化方面有了显著的改进,尤其是在索引中包含大量关键字和数值类型字段时。

(请注意,以上结果仅针对当前测试数据,实际结果可能会因环境和数据特征而有所不同)

我们希望本文能够帮助用户更好地了解最新版本 Elasticsearch 的优势和潜力,并在选择技术时做出更明智的决策。如果你对本文的内容有任何疑问或建议,欢迎在评论区留言,我们将尽快回复你。同时,也请继续关注我们这一系列主题的文章。

感谢你的阅读和支持!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 测试前置条件
    • 数据源和版本选择
      • 配置
      • 日志数据对比
      • 指标数据对比
      • 总结
      相关产品与服务
      Elasticsearch Service
      腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档