ITPub博客

首页 > IT基础架构 > > NetDevOps随笔/监控与数据分析/Elastic_Stack/Elasticsearch_02

NetDevOps随笔/监控与数据分析/Elastic_Stack/Elasticsearch_02

作者:格伯纳 时间:2020-05-29 13:36:43 0 删除 编辑

上文中, 我们了解了Elasticsearch集群的基本概念并搭建了一个基础集群:

辣不麻:NetDevOps随笔/监控与数据分析/Elastic_Stack/Elasticsearch_01​zhuanlan.zhihu.com图标

本文着重介绍Elasticsearch数据存储与索引的最基本概念: 文档, 索引, 分片, 和副本分片.

申明:
- 本入门自学笔记基于Elasticsearch:7.6.2, 不保证实时随新版本更新.
- 本入门自学笔记包含基于辣不麻理解的中英文翻译, 不保证与官网中文文档完全匹配.

文档

申明: 本入门自学笔记不涵盖数据结构, 比如说json的基础知识, 请移步自学

文档(Document)是Elasticsearch中对一份数据的称呼, 可以是一条系统日志, 或者是一个路由器的Telemetry事件. 根据需求, 用户也可以选择将一条系统日志拆分成多份文档进行存储.
那既然都是收存系统日志, 和传统的rsyslog等日志服务器有什么区别呢? 根据需求, 为了方便实现将来的排序, 筛选, 统计等操作, 文档必须是json格式结构化的数据, 举个栗子, 下面是一条grpc Telemetry 事件, 事件路径为: /bgp-rib/afi-safis/afi-safi/ipv4-unicast/neighbors/neighbor/adj-rib-in-post/num-routes/

{
  "system_id": "vMX9",
  "description": "routing protocol bgp adjacency rib in routes from vMX9",
  "timestamp": "20200228T103332Z",
  "bgp_ipv4uni_adj_rib_in_post": [
    {
      "__prefix__": "7.7.7.7",
      "adj_rib_in_postnum_routes": 9
    },
    {
      "__prefix__": "8.8.8.8",
      "adj_rib_in_postnum_routes": 1
    }
  ]
}

有心人可能会发现此路径对应的事件格式并没有这个简洁, 那是因为辣不麻为了自己的需求对文档进行了一定程度的过滤和重组. 结构化数据带来显而易见的好处就是层次分明, 内容精确. 如果我需要查找从7.7.7.7收到的路由, 我完全不需要使用正则表达式去进行匹配, 我只需要去查找bgp_ipv4uni_adj_rib_in_post下__prefix__为7.7.7.7的那部分就可以了.
还有一个好处就是结构化的数据配合适当的数据类型申明(Mapping)可以指导Elasticsearch生成反向索引表/反向哈希表(Inverted Index), 这张表是用户可以实现高效查找与过滤的灵魂. 以后我们会细讲数据类型申明和反向索引表.

或者你也可以将这份数据拆成2份文档:

{
  "system_id": "vMX9",
  "description": "routing protocol bgp adjacency rib in routes from vMX9",
  "timestamp": "20200228T103332Z",
  "bgp_ipv4uni_adj_rib_in_post": [
    {
      "__prefix__": "7.7.7.7",
      "adj_rib_in_postnum_routes": 9
    }
  ]
}

和

{
  "system_id": "vMX9",
  "description": "routing protocol bgp adjacency rib in routes from vMX9",
  "timestamp": "20200228T103332Z",
  "bgp_ipv4uni_adj_rib_in_post": [
    {
      "__prefix__": "8.8.8.8",
      "adj_rib_in_postnum_routes": 1
    }
  ]
}

到底是存一份还是拆多份需要根据用户需求, 性能, 容量等方面去进行决策.

索引

索引(Index), 不同与前面提到过的反向索引表(Inverted Index), 概念上不要搞混.
随着存入的文档的格式越来越不同, 数量越来越多, 会遇到下列潜在问题:
- 越来越难设计出只搜索某一特定格式文档的条件
- 搜索越来越慢
- 数据无限膨胀, 吃存储空间


聪明人一定已经想到了, 为什么不把文档进行分组呢? 不同格式的文档分成不同的组, 组中又可以根据文档数量, 或者文档日期去细分成小组, 可以选择性的归档或删除陈旧小组. 没错, 这个小组就叫做索引.

索引就是一定数量文档的集合, 也是一部分配置的最小配置单位, 这个怎么理解?
比如说前文提到的数据类型申明(Mapping), 对于结构化数据的每一个元素, 我可以申明是字符串, 也可以申明是正整数. Elasticsearch允许用户定义全局的默认数据类型申明, 也可以根据正则表达式定义一系列索引的申明, 但是, 用户无法对单一文档数据类型进行申明. 也就是说最小, 最细的数据类型申明只能是索引层面.
当然, 除了数据类型申明(Mapping), 还有许多其他配置, 我们以后慢慢道来

分片

分片(Shards), 是为了实现数据冗余, 提高性能的一层设计. 前一篇笔记我们有提到过一个健康的集群至少有三个节点, 根据配置, Elasticsearch可以把一个索引掰成多个分片(Shards)然后存到不同的节点上, 有啥好处?
当你针对某个索引做搜索或者统计的时候, 你会使用全部三个节点的硬盘读写和CPU, 相当于用户指令被分布到三个节点同时执行.

自主思考: 既然分片提升了查询统计性能, 是不是越多分片就越好呢?

副本分片

副本分片(Replica)与分片(Shards)团结协作, 那么工程师们最关心的问题, 冗余也就有着落了. 根据默认配置, Elasticsearch会为每个分片创建一个副本并且保证正本和副本不会存在于同一个节点. Elasticsearch会在有新文档, 新索引, 配置更改, 或者节点宕机等种种情况下动态的对分片和副本分片进行分配(Allocation)和重分布(Rebalancing)

自主思考: 每分片一份副本的配置下集群最多可以容忍多少个节点宕机?

相关的REST API

GET IP:port/_cat/indices API可以以表单形式查看目前已存储的所有索引, 这里的indices是索引(Index)的复数形式.

  • 红线部分pri, 指的是primary shards(主分片), 也就是这个索引(Index)的配置, 表示这个索引(Index)将被掰成多少个分片, 辣不麻记得从某个版本开始默认分片数就从5变成了1. 用户也可以根据自己的需求去更改
  • 蓝线部分rep, 指的是replica shards(副本分片), 也是这个索引(Index)的配置, 表示这个索引的每个分片会有多少个副本, 默认为1.
  • 黄线部分docs.count, 不难理解指的是这个索引下目前有多少个文档, 这个是索引的元数据(metadata), 并不是配置, 不可更改.
题外话: 辣不麻遇到自己客户公司许多网络工程师并不理解元数据(metadata)是几个意思. 这里让辣不麻举个栗子: 有这么个购物清单: "牛小排: 2斤, 土豆: 8两, 迷迭香: 5克" (肚子饿了).
那么"买什么"和"买多少"毋庸置疑就是这个购物清单的数据, 而用来描述这份购物清单却又没写在购物清单上的内容, 比如"字数: 19, 语言: 中文" 等等就叫做这份数据的元数据啦(metadata)
大家不要小看元数据的作用, 在网络工程这个领域全球的数据是不断膨胀的, 许多几十年前开发的网络技术所反馈给用户的数据量与颗粒度是不足以满足现在越来越繁琐的应用需求的. 辣不麻最近就遇到关于运营商DNS黑客防护的需求就需要第三方工具去预分析每个DNS请求并且反馈额外的元数据供分析软件进行分析.

POST IP:port/索引名/_doc API可以用来向某个索引存入文档, 如果索引名不存在, 则会创建一个新的索引. 让我们创建一个新的索引叫做bgp_routes, 为了实现一个有限静态的实验环境, 我们不从路由器实时传输Telemetry过来, 而是选取其中的一部分文档, 手动存入.

文档储存成功的话我们会收到HTTP Response代码201, 见下图红线部分. 这个文档包含了一个时间戳, 以及这个时间点vMX9从不同的BGP邻居学习到的路由条目数量.

GET IP:port/_cat/shards/索引名 API可以以表单形式查看该索引所有分片的分配情况, 我们可以看到之前新建的索引主分片在es01这个节点上, 而副本分片在es02上

GET IP:port/索引名/_settings API可以用来查看某个索引的配置, Elasitsearch默认会刷入一小段的配置. GET IP:port/索引名/_settings?include_defaults则看一看到所有的隐性默认配置.

  • "number_of_shards"指该索引会被掰成几个分片, 无法在存入文档后更改
  • "number_of_replicas"指每个分片会对应几个副本, 可以在存入文档后更改
自主思考: 如果将number_of_shards和number_of_replicas全部更改为2, 该索引算上主分片和副本分片总共有几个分片?

POST IP:port/索引名/_bulk API, 为后续的学习和实验做准备, 让我们再多存入一些文档, 这个时候我们可以利用批量操作的API. Bulk API的格式为一行指令, 一行内容, 下图中红线部分为指令: Index. 这里的Index不是名词"索引", 而是要作为动词"索引ing"来理解.

GET IP:port/索引名/_count API可以查看单一索引的文档数量, 如下图, 辣不麻的实验集群目前有6个文档在bgp_routes里.

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31509949/viewspace-3157098/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
管理员

注册时间:2018-03-30

  • 博文量
    2383
  • 访问量
    983897