ES学习笔记之-ClusterState的学习

前面研究过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);}@Overridepublic int nextSeed() {return seed.getAndIncrement();}@Overridepublic 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这里没有用到。后面梳理清楚使用场景后再记录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/576595.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最优化学习笔记(九)——基本的共轭方向算法

一、基本共轭方向算法 对于n维二次型函数的最小化问题: f(x)=12xTQx−xTb f(x)=\frac{1}{2}\boldsymbol{x^TQx-x^Tb}其中&#xff0c;QQT>0,x∈Rn。因为Q>0,所以函数f有一个全局极小点,可以通过求解Qx=b得到。 基本共轭方向算法 给定初始点x(0)和一组关于Q共轭的方向…

HTML简单实例加表单的显示效果

HTML可以说是一种十分简单的标记语言&#xff0c;但是对于Web开发还是必不可少的&#xff0c;所以对HTML的标记进行适当的了解 还是十分有必要的。下面我们来演示一下基本的HTML效果和一些简单的标签&#xff0c;以及在表单界面的各种提交方式。 首先是HTML的常用简单标签。 &l…

机器学习笔记(十二)——马尔科夫模型

马尔科夫模型是一种概率图模型&#xff0c;它描述了一类重要的随机过程(随机过程又称为随机函数&#xff0c;是随时间而随机变化的过程)。我们常常需要考察一个随机变量序列&#xff0c;这些随机变量序列并不是相互独立的&#xff0c;每个随机变量的值都依赖于这个序列前边的状…

用Java代码在ElasticSearch中索引PDF文件?

以下是我的代码&#xff1a; InputStream inputStream new FileInputStream(new File("mypdf.pdf"));try {byte[] fileByteStream IOUtils.toByteArray(inputStream );String base64String new String(Base64.getEncoder().encodeToString(fileByteStream).getBy…

美国影视演员协会选择了Windows Azure

娱乐行业的主要组织之一的美国影视演员协会&#xff08;SAG&#xff09;最近因云计算的需要选择Windows Azure解决方案。美国影视演员协会将他们的网站从基于Linux的服务器迁移到支持他们的最大年度事件——美国演员工会奖的Windows Azure上。 每年的年度颁奖典礼的到来标志着一…

最优化学习笔记(十)——对偶线性规划

一、对偶问题 每个线性规划问题都有一个与之对应的对偶问题。对偶问题是以原问题的约束条件和目标函数为基础构造而来的。对偶问题也是一个线性规划问题&#xff0c;因此可以采用单纯形法&#xff08;有关单纯形法会在以后的笔记中补充&#xff09;求解。对偶问题的最优解也可以…

elasticsearch基本查询二(英文分词)term和terms查询

term和terms查询(查找zhaoliu这个人的信息) term query会去倒排索弓|中寻找确切的term,它并不知道分词器的存在。这种查询适合keyword、numeric. date. term:查询某个字段里含有某个关键词的文档 GET /lib3/user/_search/ { "query":{ "term": {interests&…

Iphone开发之音频101(part 2):转换和录音

iPhone开发之音频101(Part 2)&#xff1a;转换和录音 译者&#xff1a;大侠自来也 免责申明&#xff08;必读&#xff01;&#xff09;&#xff1a;本博客提供的所有教程的翻译原稿均来自于互联网&#xff0c;仅供学习交流之用&#xff0c;切勿进行商业传播。同时&#xff0c;转…

机器学习笔记(十三)——隐马尔科夫模型

一、隐马尔科夫模型 在马尔科夫模型中&#xff0c;每一个状态代表了一个可以观察的事件&#xff0c;所以&#xff0c;马尔科夫模型有时称为可视马尔科夫模型&#xff08;visible Markov model&#xff0c;VMM&#xff09;&#xff0c;这在某种程度上限制了模型的适应性。在隐马…

elasticsearch基本查询三(英文分词)match查询

#match查询 #match query知道分词器的存在&#xff0c;会对filed进行分词操作, 然后再查询 GET /ib3/user/_search { "query":{ "match":{ "name": "zhaoliu" }} } GET /lib3/user/_search { "query":{ "match"…

solr 3.5 配置及应用(二)

在 solr 3.5 配置及应用(一) 讲过一了 solr 3.5的详细配置&#xff0c;本节我们讲利用solr 的客户端调用solr的应用了&#xff01; 一、利用SolrJ操作solr API 使用SolrJ操作Solr会比利用httpClient来操作Solr要简单。SolrJ是封装了httpClient方法&#xff0c;来操作solr的API的…

elasticsearch控制返回字段查询三(英文分词)match查询

#_source指定查询返回的字段信息 #_source指定查询返回的字段信息 GET /lib3/user/_search {"from":0, "size": 2, "_source": ["address" , "name"] ,"query": {"match": {"interests": &…

通过日志恢复MSSQL数据例子

这段时间看了关于在SQL server 中通过日志和时间点来恢复数据。也看了一些网上的例子&#xff0c;看如何通过日志来恢复数据。 前提条件&#xff1a; 数据库的故障恢复改为非简单模式&#xff0c;去掉自动关闭和自动收缩两个选项 如果是简单模式&#xff1a; 类似下面的语…

最优化学习笔记(十一)——对偶问题的例子

某线性规划问题为&#xff1a; mincTxst.Ax≤b\min \boldsymbol{c}^T\boldsymbol{x} \\ st. \boldsymbol{Ax} \le \boldsymbol{b}这个例子和上节中的表2非对称形式的对偶关系比较接近&#xff0c;将上式改写为&#xff1a; maxxT(−c)st.xTAT≤bT\max \boldsymbol{x^T(-c)}\\ …

ElasticSearch查询返回信息根据字段排序(英文检索)

根据年龄降序排序 #排序 GET /lib3/user/_search {"query": {"match_all": {}},"sort":[{"age": {"order" :"desc"}}] } {"took" : 1,"timed_out" : false,"_shards" : {"t…

机器学习笔记(十四)——HMM估计问题和前向后向算法

一、隐马尔科夫链的第一个基本问题 估计问题&#xff1a;给定一个观察序列OO1O2…OT和模型u(A,B,π),如何快速地计算出给定模型u情况下,观察序列O的概率&#xff0c; 即P(O|u)? 二、求解观察序列的概率 其实&#xff0c;求解这个问题就是一个解码问题。 对于任意的状态序列Q…

windows中架设基于Apache的svn服务器

1.安装apache及svn的windows版我安装的版本是:httpd-2.2.22-win32-x86-openssl-0.9.8t.msi 和svn-win32-1.5.0.zipsvn是解压就可以了2. 解svn安装目录下\bin下的mod_authz_svn.so、mod_dav_svn.so拷贝到apache/modules下3.将 svn安装目录下\bin下的libdb44.dll拷贝到apache/bin…

ElasticSearch通配符 * 查询(英文检索)

#如果你要查询的字段信息记得不太清楚, 我们也可以使用通配符 * GET /lib3/user/_search {"from":0, "size": 2,"_source": {"includes": "addr*","excludes": ["name" , "bir*"]},"…

sqlserver agent不能启动

我启动了 event log 服务 &#xff0c;就好了&#xff0c;不知什么原因转载于:https://www.cnblogs.com/laogao/archive/2012/03/11/2390794.html

机器学习笔记(十五)——HMM序列问题和维特比算法

一、引言 这篇blog主要讲序列问题和其解法——维特比算法。 二、HMM中的第二个基本问题 序列问题&#xff1a;给定一个观察序列OO1O2…OT和模型u(A,B,π)&#xff0c;如何快速有效地选择在一定意义下”最优”的状态序列Qq1q2…qT,使得该状态序列“最好地解释”观察序列&#…