ES学习笔记之-ClusterState的学习

2023-11-16

前面研究过ES的get api的整体思路,作为编写ES插件时的借鉴。当时的重点在与理解整体流程,主要是shardOperation()的方法内部的调用逻辑,就弱化了shards()方法。实际上shards()方法在理解ES的结构层面,作用更大一些。我们还是从get api入手来理解shards()

先回顾一下get api的使用流程:

 添加文档到ES:
 curl -XPUT 'http://localhost:9200/test1/type1/1' -d '{"name":"hello"}'

 根据文档ID读取数据:
 curl -XGET 'http://localhost:9200/test1/type1/1' 

使用很简单。但是如果考虑到分布式,背后的逻辑就不简单了。 假如ES集群有3个节点,数据所在的索引也有3个分片,每个分片一个副本。即index的设置如下:

{
  "test1" : {
    "settings" : {
      "index" : {
        "number_of_replicas" : "1",
        "number_of_shards" : "3"
      }
    }
  }
}

那么id为1的doc该分发到那个分片呢? 这个问题需要一篇详细的博文解答,这里我们先简单给一个结论:

默认情况下,ES会按照文档id计算一个hash值, 采用的是Murmur3HashFunction,然后根据这个id跟分片数取模。实现代码是MathUtils.mod(hash, indexMetaData.getNumberOfShards()); 最后的结果作为文档所在的分片id,所以ES的分片标号是从0开始的。

不知存,焉知取。

再整理一下取数据的核心流程:

s1: 根据文档id定位到数据所在分片。由于可以设为多个副本,所以一个分片会映射到多个节点。

s2: 根据分片节点的映射信息,选择一个节点,去获取数据。 这里重点关注的是节点的选择方式,简而言之,我们需要负载均衡,不然设置副本就没有意义了。

上面两步都关联着一个核心的数据结构ClusterState, 我们可以使用_cluster/state?pretty来查看这个数据结构:

# http://localhost:9200/_cluster/state?pretty

{
  "cluster_name" : "elasticsearch",
  "version" : 4,
  "state_uuid" : "b6B739p5SbanNLyKxTMHfQ",
  "master_node" : "KnEE25tzRjaXblFJq5jqRA",
  "blocks" : { },
  "nodes" : {
    "KnEE25tzRjaXblFJq5jqRA" : {
      "name" : "Mysterio",
      "transport_address" : "127.0.0.1:9300",
      "attributes" : { }
    }
  },
  "metadata" : {
    "cluster_uuid" : "ZIl7g86YRiGv8Dqz4DCoAQ",
    "templates" : { },
    "indices" : {
      "test1" : {
        "state" : "open",
        "settings" : {
          "index" : {
            "creation_date" : "1553995485603",
            "uuid" : "U7v5t_T7RG6rNU3JlGCCBQ",
            "number_of_replicas" : "1",
            "number_of_shards" : "1",
            "version" : {
              "created" : "2040599"
            }
          }
        },
        "mappings" : { },
        "aliases" : [ ]
      }
    }
  },
  "routing_table" : {
    "indices" : {
      "test1" : {
        "shards" : {
          "0" : [ {
            "state" : "STARTED",
            "primary" : true,
            "node" : "KnEE25tzRjaXblFJq5jqRA",
            "relocating_node" : null,
            "shard" : 0,
            "index" : "test1",
            "version" : 2,
            "allocation_id" : {
              "id" : "lcSHbfWDRyOKOhXAf3HXLA"
            }
          }, {
            "state" : "UNASSIGNED",
            "primary" : false,
            "node" : null,
            "relocating_node" : null,
            "shard" : 0,
            "index" : "test1",
            "version" : 2,
            "unassigned_info" : {
              "reason" : "INDEX_CREATED",
              "at" : "2019-03-31T01:24:45.845Z"
            }
          } ]
        }
      }
    }
  },
  "routing_nodes" : {
    "unassigned" : [ {
      "state" : "UNASSIGNED",
      "primary" : false,
      "node" : null,
      "relocating_node" : null,
      "shard" : 0,
      "index" : "test1",
      "version" : 2,
      "unassigned_info" : {
        "reason" : "INDEX_CREATED",
        "at" : "2019-03-31T01:24:45.845Z"
      }
    } ],
    "nodes" : {
      "KnEE25tzRjaXblFJq5jqRA" : [ {
        "state" : "STARTED",
        "primary" : true,
        "node" : "KnEE25tzRjaXblFJq5jqRA",
        "relocating_node" : null,
        "shard" : 0,
        "index" : "test1",
        "version" : 2,
        "allocation_id" : {
          "id" : "lcSHbfWDRyOKOhXAf3HXLA"
        }
      } ]
    }
  }
}

整个结构比较复杂,我们慢慢拆解, 一步步逐个击破。 拆解的思路还是从使用场景入手。

  1. IndexMetaData的学习
    metaData的格式如下:
    "metadata" : {
    "cluster_uuid" : "ZIl7g86YRiGv8Dqz4DCoAQ",
    "templates" : { },
    "indices" : {
      "test1" : {
        "state" : "open",
        "settings" : {
          "index" : {
            "creation_date" : "1553995485603",
            "uuid" : "U7v5t_T7RG6rNU3JlGCCBQ",
            "number_of_replicas" : "1",
            "number_of_shards" : "1",
            "version" : {
              "created" : "2040599"
            }
          }
        },
        "mappings" : { },
        "aliases" : [ ]
      }
    }
    }

即metadata中存储了集群中每个索引的分片和副本数量, 索引的状态, 索引的mapping, 索引的别名等。这种结构,能提供出来的功能就是根据索引名称获取索引元数据, 代码如下:

# OperationRouting.generateShardId()

        IndexMetaData indexMetaData = clusterState.metaData().index(index);
        if (indexMetaData == null) {
            throw new IndexNotFoundException(index);
        }
        final Version createdVersion = indexMetaData.getCreationVersion();
        final HashFunction hashFunction = indexMetaData.getRoutingHashFunction();
        final boolean useType = indexMetaData.getRoutingUseType();

这里我们关注点就是clusterState.metaData().index(index)这句代码,它实现了根据索引名称获取索引元数据的功能。 通过元数据中的分片数结合文档id,我们就能定位出文档所在的分片。 这个功能在Delete, Index, Get 三类API中都是必须的。 这里我们也能理解为什么ES的索引分片数量不能修改: 如果修改了,那么hash函数就没法正确定位数据所在分片。

  1. IndexRoutingTable的学习
"routing_table" : {
    "indices" : {
      "test1" : {
        "shards" : {
          "0" : [ {
            "state" : "STARTED",
            "primary" : true,
            "node" : "KnEE25tzRjaXblFJq5jqRA",
            "relocating_node" : null,
            "shard" : 0,
            "index" : "test1",
            "version" : 2,
            "allocation_id" : {
              "id" : "lcSHbfWDRyOKOhXAf3HXLA"
            }
          }, {
            "state" : "UNASSIGNED",
            "primary" : false,
            "node" : null,
            "relocating_node" : null,
            "shard" : 0,
            "index" : "test1",
            "version" : 2,
            "unassigned_info" : {
              "reason" : "INDEX_CREATED",
              "at" : "2019-03-31T01:24:45.845Z"
            }
          } ]
        }
      }
    }
  }

routing_table存储着每个索引的分片信息,通过这个结构,我们能清晰地了解如下的信息:

1. 索引分片在各个节点的分布
2. 索引分片是否为主分片

假如一个分片有2个副本,且都分配在不同的节点上,那么get api一共有三个数据节点可供选择, 选择哪一个呢?这里暂时不考虑带preference参数。
为了使每个节点都能公平被选择到,达到负载均衡的目的,这里用到了随机数。参考RotateShuffer

/**
 * Basic {@link ShardShuffler} implementation that uses an {@link AtomicInteger} to generate seeds and uses a rotation to permute shards.
 */
public class RotationShardShuffler extends ShardShuffler {

    private final AtomicInteger seed;

    public RotationShardShuffler(int seed) {
        this.seed = new AtomicInteger(seed);
    }

    @Override
    public int nextSeed() {
        return seed.getAndIncrement();
    }

    @Override
    public List<ShardRouting> shuffle(List<ShardRouting> shards, int seed) {
        return CollectionUtils.rotate(shards, seed);
    }

}

也就是说使用ThreadLocalRandom.current().nextInt()生成随机数作为种子, 然后取的时候依次旋转。
Collections.rotate()的效果可以用如下的代码演示:

    public static void main(String[] args) {

        List<String> list = Lists.newArrayList("a","b","c");
        int a = ThreadLocalRandom.current().nextInt();
        List<String> l2 = CollectionUtils.rotate(list, a );
        List<String> l3 = CollectionUtils.rotate(list, a+1);
        System.out.println(l2);
        System.out.println(l3);

    }

-----
[b, c, a]
[c, a, b]

比如请求A得到的节点列表是[b,c,a], 那么请求B得到的节点列表是[c,a,b]。这样就达到了负载均衡的目的。

  1. DiscoveryNodes的学习。
    由于routing_table中存储的是节点的id, 那么将请求发送到目标节点时,还需要知道节点的ip及端口等配置信息。 这些信息存储在nodes中。
  "nodes" : {
    "KnEE25tzRjaXblFJq5jqRA" : {
      "name" : "Mysterio",
      "transport_address" : "127.0.0.1:9300",
      "attributes" : { }
    }
  }

通过这个nodes获取到节点信息后,就可以发送请求了,ES所有内部节点的通信都是基于transportService.sendRequest()

总结一下,本文基于get api 梳理了一下ES的ClusterState中的几个核心结构: metadata,nodesrouting_table。 还有一个routing_nodes这里没有用到。后面梳理清楚使用场景后再记录。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ES学习笔记之-ClusterState的学习 的相关文章

  • 分割多重多边形

    我可以直接取出零件并把它们取出来作为它们自己的功能吗 或者这会涉及更复杂的东西吗 我正在尝试将其中一张地图拆分为较小的部分以对它们进行索引 https github com simonepri geo maps https github c
  • Logstash删除类型并保留_type

    我有一个logstash 客户端和服务器 客户端将带有logstash的udp输出的日志文件发送到服务器 服务器也运行logstash来获取这些日志 在服务器上 我有一个 json 过滤器 它会在实际日志的字段中提取 json 格式的消息
  • 如何在弹性搜索中生成多个布尔查询的查询

    我想使用 spring 框架在 elasticsearch 中动态生成多个布尔运算的查询 我在elasticsearch中的数据就像 masterID
  • 如何在 kibana 中自动配置索引模式

    是否可以在 kibana 中自动配置索引模式 要么通过一些设置文件 要么通过rest api 安装后可以手动完成 Kibana 5 x 公开了这样的 API 来管理索引模式 要创建索引模式 可以发出以下命令来 kibana 访问 url 只
  • 在 Elasticsearch 中对具有一个值的属性进行多个值查询

    我正在尝试在这个查询的基础上进行一些构建 我正在搜索的索引还有一个带有 id 的 实体 字段 因此 一些记录将具有 实体 16 实体 156 等 具体取决于实体的 ID 我需要以这样的方式扩展此查询 以便可以传递数组或某些值列表 例如 te
  • elasticsearch查询字符串分析器针对不同字段使用不同的分析器

    当对具有不同分析器 stem ngram等 的多个字段执行查询时 elasticsearch是否对每个字段的查询字符串执行特定的分析 是的 除非您在查询中指定分析器 这请求参数 http www elasticsearch org guid
  • 从中间部分匹配完成建议elasticsearch

    我有一个名为搜索建议具有以下 search suggest type completion analyzer simple payloads true preserve separators false preserve position
  • 局部敏感哈希 - Elasticsearch

    有没有允许在 Elasticsearch 上使用 LSH 的插件 如果是的话 您能否指出该位置并告诉我如何使用它 谢谢 编辑 我发现ES使用了MinHash插件 我怎样才能用这个来比较文件呢 查找重复项的最佳设置是什么 有一个Elastic
  • 从 App Engine 连接到 Kubernetes 引擎

    我们希望使用应用程序引擎灵活的流程来更新位于 Google Kubernetes Engine 上的 ElasticSearch 索引 我们需要通过 http s 地址连接到 ElasticSearch 推荐的方法是什么 我们不想将集群暴露
  • 在 Elastic 搜索中加载示例数据集时出错

    您好 我正在尝试加载示例数据集参考弹性搜索文档 https www elastic co guide en elasticsearch reference current exploring your data html但是当我尝试运行指示
  • ElasticSearch 嵌套查询 - 排除父文档

    尝试排除其中子文档之一与查询不匹配的顶级文档 对于下面的示例 我尝试排除其嵌套作业之一具有的所有文档current true 并与company name Elastic 但由于嵌套作业文档之一与current false和公司name E
  • Elasticsearch 单个字段的多个分析器

    我使用严格的预定义映射将不同类型的文档存储在单个索引中 它们都有一些字段 例如 body 但我希望在索引时对它们进行稍微不同的分析 例如 对特定文档使用不同的标记过滤器 并在搜索时以相同的方式处理 据我所知 分析器不能按文档指定 我还考虑使
  • 在 ElasticSearch API 应用程序中找不到 NodeBuilder

    我正在尝试实现 Elasticsearch API 我的系统接受 nodeBuilder 时出现错误 这是代码 import org elasticsearch action index IndexResponse import org e
  • 如何修复从 React 对 Elasticsearch 进行 API 调用时的“混合内容:”错误

    我正在使用 firebase 的 elasticsearch 的 bitnami 版本 我发现它只能连接到http并不是https当我使用邮递员尝试时 我的create react app已部署到 firebase 我得到Mixed Con
  • Elasticsearch 关于“空索引”的查询

    在我的应用程序中 我使用了几个elasticsearch索引 它们在初始状态下不包含索引文档 我认为这可以称为 空 该文档的映射是正确且有效的 该应用程序还有一个包含实体的关系数据库 这些实体可能具有在 elasticsearch 中关联的
  • NEST 1.0:请参阅 Fiddler 上的请求

    我刚刚更新到 NEST 1 0 我在远程服务器 不是本地主机 上有 Elastic Search 通常我在使用 Fiddler 发送和接收请求时没有任何问题 更新后 bammm 没有检测到任何请求 但我的应用程序发出这些请求没有任何问题 你
  • Elasticsearch:根据类型对不同字段进行排序

    我的索引中有两种类型 Event and City 我正在尝试按日期将它们全部排序 但是 每种类型的日期字段名称都不同 为了Event该值是在updated at领域和City日期是在update at其嵌套对象之一中的字段city eve
  • Elasticsearch:预期的字段名称,但得到了 START_OBJECT

    我一直在尝试运行以下查询 但每次运行时都会收到以下错误 nested ElasticsearchParseException Expected field name but got START OBJECT field value fact
  • Java ElasticSearch 配置的节点均不可用

    过去一小时刚刚下载并安装了elasticsearch 1 3 2 打开 IPtables 端口 9200 和 9300 9400 在 etc hosts 中设置我的计算机名称和 ip 头部模块和护理人员安装并运行顺利 本地主机上的curl
  • 使用文件的 AWS Elasticsearch 同义词

    我正在尝试使用文件将同义词添加到弹性搜索 如本链接所示 但它给了我以下错误https www elastic co guide en elasticsearch reference 5 2 analysis synonym tokenfil

随机推荐

  • 终端上使用脚本隔一定时间进行重复reboot和ping

    bin sh 设置 so的路径 export LD LIBRARY PATH usrdata LD LIBRARY PATH export LD LIBRARY PATH LD LIBRARY PATH usrdata 设置 usrdata
  • 在navcat中清空数据后,设置id归零方法

    写后台完成后 需要清空Mysql数据库中的测试数据 但是后面新增的数据 一直是以原来所删除数据的最大id为增量基本 比如 对于一些id敏感的项 十分不便 如图 原有10条数据 清空后 新增一两条 手动改了11为1后 再增一条 自动成了12
  • 将Vmware虚拟机磁盘映射到本地实现文件传输

    文章目录 前言 一 在ubuntu上搭建samba服务器并设置共享文件夹 二 查询虚拟机ip 三 确保本地和虚拟机网络互通 四 映射网络驱动器 五 文件传输测试 前言 将虚拟机磁盘映射到本地 可以实现文件互传 更方便使用 在开发时可以替代S
  • python实现GA-GRU遗传算法优化门控循环单元多变量时间序列预测

    GA GRU遗传算法优化门控循环单元多变量时间序列预测是一个比较复杂的问题 需要一定的编程和数学基础 下面是一个简单的Python实现 供参考 首先 我们需要导入相关的库 python import numpy as np import p
  • setGeometry Unable to set geometry问题记录

    问题描述 为了添加美化效果 重写了QMainWindow等窗口的标题栏 通过自定义标题栏窗口实现最大化 最小化 还原 关闭等操作 这些操作涉及到窗口的尺寸变化 在调试过程中出现以下问题 打开一个QMainWindow后 窗口正常显示 最大化
  • connect时使用Qt::DirectConnection,导致多线程时UI线程还是卡顿

    如果槽函数是耗时会导致UI假死的任务 connect时不能使用Qt DirectConnection 该参数The slot is invoked immediately when the signal is emitted The slo
  • ValueError: Input contains NaN, infinity or a value too large for dtype('float32').

    ValueError Input contains NaN infinity or a value too large for dtype float32 64 一般处理方式 对于以上问题其原因一般是数据集中存在nan值 以下假设数据用nu
  • Python+Appium实现控制app

    在这之前需要做好以下几个步骤 1 java开发环境JDK 2 android SDK platform platform tools tools build tools 3 python下载安装 pip 4 appium下载安装 服务端 客
  • js -- constructor构造方法

    let aaa name Lifan age 18 class Polygon constructor aaa this name aaa name const poly1 new Polygon aaa console log poly1
  • Spring IoC容器

    转自 Spring IoC容器 一 Ioc简介 IoC容器是Spring中的核心 我们通常也将其称之为Spring容器 Spring使用IoC容器对对象的实例化和初始化的操作 及管理对象的创建到销毁的生命周期 Spring中使用的对象全部由
  • OSI网络模型(TCP/IP五层模型)

    互联网由一系列的网络协议组成 这些协议的集合叫做OSI协议 按照功能可以划分为七层 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 也就是我们常说的OSI七层模型 每一层使用下层提供的服务 并向上层提供服务 OSI七层模型只是一
  • uni-app store 状态管理学习,多写几遍就会了

    uni app使用了一段时间了 一直没有用到store 状态管理 还是应该学习一下 以后会用到的 1 使用hbuiderx创建uni app项目 2 与static同级创建store文件夹 store文件夹下创建index js 3 关键i
  • sqlserver数据类型转换(将 nvarchar 转换为数据类型 numeric 时出现算术溢出错误)

    一般情况下 sqlserver会自动完成数据转换 但这种转换有时候很容易出错 尤其是nvarchar转换为numeric时 如果能够明确数据类型 最好显式转换 举个我遇到的例子 SELECT FROM ITEM INFO TEST WHER
  • BLE学习(4):蓝牙地址类型和设备的隐私

    蓝牙地址也被称为蓝牙MAC地址 它能唯一标识一个蓝牙设备的48位的值 在蓝牙规范中 它被称为BD ADDR 蓝牙的地址类型可以分为两种 public addresses和random addresses 其中random addresses
  • visual studio2019创建运行第一个C++详细步骤与断点调试的简单认识

    是去官网下的社区版 可以用自己的微软账号登录也不需要网上找破解版了 安装过程还是很顺利的 下面在第一次使用vs2019下创建C 项目 依次helloworld 计算器类 首先明确 在vs中是使用项目来组织代码 使用解决方案来组织项目 所以首
  • adb连接及常用命令

    adb命令连接模拟器设备 以夜神模拟器为例 夜神模拟器默认端口为62001 adb connect 127 0 0 1 62001 当打开了多个模拟器 设备连接失败时 解决方法 查看连接的设备 可以查看连接的adb的设备情况 如果连接多个设
  • 02_计算机网络笔记-网络拓扑-交换机-VLAN

    文章目录 一般家庭的网络拓扑 交换机的基本原理与配置 虚拟局域网VLAN 个人博客 https blog csdn net cPen web 一般家庭的网络拓扑 光猫 调制解调器 1 光信号和电信号的转换 2 路由器的功能 可以拨号 账号和
  • MyBatis 采用注解方式批量更新数据 @Mapper @Update (包含2种方法)

    批量更新数据方法 1 注释db filed name 表示的是的数据库字段名字 entity name 表示的是你的实体字段 table name 表示你的表名 Update
  • ONNXRUNTUIME c++使用(分割网络)与相关资料(暂记)

    下面的教程是在linux系统上运行的 如果想在windows系统上运行 可以看官方链接或中文教程https bbs huaweicloud com blogs 335706 官方链接中有完整的VS的带 sln的项目 ONNXRUNTUIME
  • ES学习笔记之-ClusterState的学习

    前面研究过ES的get api的整体思路 作为编写ES插件时的借鉴 当时的重点在与理解整体流程 主要是shardOperation 的方法内部的调用逻辑 就弱化了shards 方法 实际上shards 方法在理解ES的结构层面 作用更大一些