Estudamos a frente ES de get api
toda a idéia como uma referência ao escrever plug-ES. Naquele tempo o foco na compreensão do processo global, principalmente shardOperation()
a lógica interna da chamada do método, ele enfraqueceu shards()
método. Na verdade shards()
método em compreender os ES nível estrutural, papel maior. Nós ainda, get api
para entender o início shards()
.
Primeiro, olhe para get api
o uso do processo:
添加文档到ES:
curl -XPUT 'http://localhost:9200/test1/type1/1' -d '{"name":"hello"}'
根据文档ID读取数据:
curl -XGET 'http://localhost:9200/test1/type1/1'
Muito simples de usar. Mas se distribuídos lógica por trás tendo em conta não é simples. Se aglomerado ES tem três nós, onde o índice de dados tem três fragmentos, uma cópia de cada fatia. Esse índice é definido da seguinte forma:
{
"test1" : {
"settings" : {
"index" : {
"number_of_replicas" : "1",
"number_of_shards" : "3"
}
}
}
}
Assim, com id doc 1 desta distribuição para essa fatia dele? Esta questão precisa de um blog resposta detalhada, onde nós primeiro dar uma conclusão simples:
默认情况下,ES会按照文档id计算一个hash值, 采用的是Murmur3HashFunction,然后根据这个id跟分片数取模。实现代码是MathUtils.mod(hash, indexMetaData.getNumberOfShards()); 最后的结果作为文档所在的分片id,所以ES的分片标号是从0开始的。
Eu não sei existir, como você pode saber a tomar.
E depois resolver os principais processos de acesso aos dados:
s1: 根据文档id定位到数据所在分片。由于可以设为多个副本,所以一个分片会映射到多个节点。
s2: 根据分片节点的映射信息,选择一个节点,去获取数据。 这里重点关注的是节点的选择方式,简而言之,我们需要负载均衡,不然设置副本就没有意义了。
Os dois passos acima está associada com uma estrutura de dados de núcleo ClusterState
, que pode utilizar _cluster/state?pretty
para visualizar esta estrutura de dados:
# 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"
}
} ]
}
}
}
Toda a estrutura é mais complexo, que são desmontagem lentamente, passo a passo, uma por uma pausa. Partindo da idéia de desmantelamento ou a utilização de cenários.
- IndexMetaData aprender
metaData o seguinte formato:"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" : [ ] } } }
Que os metadados é armazenado num estado em que o conjunto de cada fatia e o índice do número de cópias, o índice, o mapeamento de índice, pseudónimos de índice. Esta configuração pode fornecer essa função para fora 根据索引名称获取索引元数据
, como se segue:
# 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();
Nossa preocupação aqui é que clusterState.metaData().index(index)
este código, ele implementa 根据索引名称获取索引元数据的功能
. Pelo número de metadados fragmentados de ligação ID do documento, que será capaz de localizar os fragmentos das reside documentos. Esta função Excluir, Index, Get três da API são necessárias. Aqui podemos entender por que o número de índice de fragmentação não pode ser modificado ES: Se você tiver modificado, em seguida, a função hash não seria capaz localizar os dados corretos onde a fragmentação.
- aprendizagem 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
Fragmentação de informações armazenadas para cada índice, por essa estrutura, podemos entender claramente as seguintes informações:
1. 索引分片在各个节点的分布
2. 索引分片是否为主分片
Se uma fatia tem duas cópias, e são alocados em um nó diferente, get api
um total de três nós de dados para escolher, escolher qual deles fazer? Aqui não considerar com preference
parâmetros.
Para fazer com que cada nó pode razoavelmente ser selecionado para alcançar carga fins de equilíbrio, um número aleatório é usado aqui. RotateShuffer referência
/**
* 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);
}
}
Que é usado ThreadLocalRandom.current().nextInt()
para gerar um número aleatório como uma semente, e, em seguida, tomar o tempo sequencialmente rodados. Collections.rotate()
O efeito pode ser usado como código demonstra:
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]
Uma solicitação, tal como uma lista de nós é obtido [b, c, a], então a lista de pedidos de nó B é obtido [c, a, b]. Isso vai atingir o objectivo de balanceamento de carga.
- DiscoveryNodes aprendendo.
Uma vez que orouting_table
tempo é armazenado na ID de nó, em seguida, envia uma solicitação para o nó de destino, mas também precisa saber o outro ip nó e configuração da porta. Esta informação é armazenada emnodes
o.
"nodes" : {
"KnEE25tzRjaXblFJq5jqRA" : {
"name" : "Mysterio",
"transport_address" : "127.0.0.1:9300",
"attributes" : { }
}
}
Por este nodes
informações do nó adquirida, um pedido pode ser enviado, todos os nós internos da ES de comunicação são baseadas transportService.sendRequest()
.
Em resumo, este trabalho baseado em get api
classificar para fora um pouco a estrutura do núcleo poucos em ClusterState ES: metadata
, nodes
, routing_table
. Há também um routing_nodes
não usados aqui. Nos bastidores e, em seguida, usar o registro claro pente.