【ES三周年】ES元信息

2023-02-17 23:07:46 浏览数 (2)

背景

在ES中,涉及元信息主要有三种,分别为分片元信息、索引元信息、集群元信息(节点元信息),并且这些元信息会保留在磁盘上,这样在节点重启时即可从磁盘上读取对应元信息并恢复。

分片元信息

1、具体内容

集群中每个分片都有属于自己的元信息,该元信息包括:

代码语言:txt复制
public final String indexUUID;
public final boolean primary;                        
public final AllocationId allocationId;

对应的类图如下:

image.pngimage.png

分片元信息在shard恢复时会被用到:

  • 首先是GateWayAllocator在恢复主备分片时,会从集群各个节点获取对应分片元信息(节点读取分片元信息时会判断本地分片的indexUUID和索引的UUID相同),用于判断是否可以本地恢复,如果满足条件(如分片的allocatId在in_sync_allocations中)则会从本地恢复分片;
  • 其次是在创建IndexShard时,会判断本地分片的indexUUID是否和索引的UUID相同,如果不同则报错(避免分片或索引出现异常)。
2、持久化

分片元信息会保存在磁盘上,作用:,对应文件路径路径:${data.path}/nodes/${node.id}/indices/${index.UUID}/${shard.id}/_state/state-xxx.st

实现元信息序列化的代码:

代码语言:txt复制
public void toXContent(XContentBuilder builder, ShardStateMetaData shardStateMetaData) throws IOException {
    builder.field(PRIMARY_KEY, shardStateMetaData.primary);
    builder.field(INDEX_UUID_KEY, shardStateMetaData.indexUUID);
    if (shardStateMetaData.allocationId != null) {
        builder.field(ALLOCATION_ID_KEY, shardStateMetaData.allocationId);
    }
}

分片被持久化的时机有两种方式,其一是分片被创建的时候,此时会分片的元信息持久化,其二是集群状态变化的时候(集群状态变化的时候,会判断分片状态是否变化,只有在当前分片的状态发生变化才更新本地文件,避免大量无效的IO)。

分片持久化的作用前面也提到了,主要是用于分片的恢复。

索引元信息

1、具体内容

集群中每个索引都有属于自己的元信息,该元信息包括:

代码语言:txt复制
private final int routingNumShards; 

private final int routingPartitionSize;
private final int numberOfShards;
private final int numberOfReplicas; 
private final Index index; 
private final long version;
private final long[] primaryTerms;
private final State state;
private final ImmutableOpenMap<String, AliasMetaData> aliases;
private final Settings settings;
private final ImmutableOpenMap<String, MappingMetaData> mappings;
private final ImmutableOpenMap<String, Custom> customs;
private final ImmutableOpenIntMap<Set<String>> inSyncAllocationIds;

对应类图如下:

evernotecid://9B7AC1A3-2163-4103-A68D-1127DA246949/appyinxiangcom/8902081/ENResource/p3135

image.pngimage.png

索引元信息主要是用于提供索引的配置信息以及mapping信息,以便对索引执行相应操作。

2、持久化

索引元信息会保存在磁盘上,作用:,对应文件路径路径:${data.path}/nodes/${node.id}/indices/${index.UUID}/_state/state-xxx.st

实现元信息序列化的代码:

代码语言:txt复制
public static void toXContent(IndexMetaData indexMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException {
    builder.startObject(indexMetaData.getIndex().getName()); 
    builder.field(KEY_VERSION, indexMetaData.getVersion());
    builder.field(KEY_ROUTING_NUM_SHARDS, indexMetaData.getRoutingNumShards());
    builder.field(KEY_STATE, indexMetaData.getState().toString().toLowerCase(Locale.ENGLISH));
    boolean binary = params.paramAsBoolean("binary", false); 
    builder.startObject(KEY_SETTINGS);
    indexMetaData.getSettings().toXContent(builder, new MapParams(Collections.singletonMap("flat_settings", "true")));
    builder.endObject();
    builder.startArray(KEY_MAPPINGS); 
    for (ObjectObjectCursor<String, MappingMetaData> cursor : indexMetaData.getMappings()) {
        if (binary) {
            builder.value(cursor.value.source().compressed());
        } else {
            builder.map(XContentHelper.convertToMap(new BytesArray(cursor.value.source().uncompressed()), true).v2());
        }
    }
    builder.endArray();
    for (ObjectObjectCursor<String, Custom> cursor : indexMetaData.getCustoms()) {
        builder.startObject(cursor.key);
        cursor.value.toXContent(builder, params);
        builder.endObject();
    }
    builder.startObject(KEY_ALIASES);
    for (ObjectCursor<AliasMetaData> cursor : indexMetaData.getAliases().values()) {
        AliasMetaData.Builder.toXContent(cursor.value, builder, params);
    }
    builder.endObject();
    builder.startArray(KEY_PRIMARY_TERMS);
    for (int i = 0; i < indexMetaData.getNumberOfShards(); i  ) {
        builder.value(indexMetaData.primaryTerm(i));
    }
    builder.endArray();
    builder.startObject(KEY_IN_SYNC_ALLOCATIONS);
    for (IntObjectCursor<Set<String>> cursor : indexMetaData.inSyncAllocationIds) {
        builder.startArray(String.valueOf(cursor.key)); 
        for (String allocationId : cursor.value) {
            builder.value(allocationId);
        }
        builder.endArray();
    }
    builder.endObject();
    builder.endObject();
}

索引原型被持久化的时机有两种方式,其一是节点启动时,此时如果如果索引元信息有发生变化,则会更新索引原型;其二是集群中索引的元信息变化时(如索引的mapping信息变化),此时会更新对应索引元信息;

索引元信息读取时机:

  • 节点启动时用于恢复索引元信息:
  • 索引配置信息变更时判断索引元信息是否需要再次持久化:如果原来索引元信息不存在或发生变化则再次持久化
  • 分片删除时判断本节点索引元信息是否存在
  • GateWayAllocator在恢复主备分片时,会从集群各个节点获取对应分片元信息(节点读取分片元信息时会判断本地分片的indexUUID和索引的UUID相同)

集群元信息

1、具体内容

集群的元信息包括:

代码语言:txt复制
private final String clusterUUID;
private final long version;
private final Settings transientSettings; 
private final Settings persistentSettings; 
private final Settings settings;
private final ImmutableOpenMap<String, IndexMetaData> indices; 
private final ImmutableOpenMap<String, IndexTemplateMetaData> templates;
private final ImmutableOpenMap<String, Custom> customs;
private final int numberOfShards;

对应类图如下:

evernotecid://9B7AC1A3-2163-4103-A68D-1127DA246949/appyinxiangcom/8902081/ENResource/p3147

image.pngimage.png

集群元信息主要是用于提供集群以及索引相关的配置信息信息,以便对集群或索引上执行相应操作提供信息。

2、持久化

集群元信息会保存在磁盘上,作用:,对应文件路径路径:${data.path}/nodes/${node.id}/_state/global-xxx.st

实现元信息序列化的代码:

代码语言:txt复制
public static void toXContent(MetaData metaData, XContentBuilder builder, ToXContent.Params params) throws IOException {  
    XContentContext context = XContentContext.valueOf(params.param(CONTEXT_MODE_PARAM, "API"));
    builder.startObject("meta-data"); 
    builder.field("version", metaData.version());
    builder.field("cluster_uuid", metaData.clusterUUID); 
    if (!metaData.persistentSettings().isEmpty()) {
        builder.startObject("settings"); 
        metaData.persistentSettings().toXContent(builder, new MapParams(Collections.singletonMap("flat_settings", "true")));
        builder.endObject();
    }
    if (context == XContentContext.API && !metaData.transientSettings().isEmpty()) { 
        builder.startObject("transient_settings"); 
        metaData.transientSettings().toXContent(builder, new MapParams(Collections.singletonMap("flat_settings", "true")));
        builder.endObject();
    }
    builder.startObject("templates"); 
    for (ObjectCursor<IndexTemplateMetaData> cursor : metaData.templates().values()) {
        IndexTemplateMetaData.Builder.toXContent(cursor.value, builder, params);
    }
    builder.endObject();
    if (context == XContentContext.API && !metaData.indices().isEmpty()) {
        builder.startObject("indices");
        for (IndexMetaData indexMetaData : metaData) {
            IndexMetaData.Builder.toXContent(indexMetaData, builder, params);
        }
        builder.endObject();
    }
    for (ObjectObjectCursor<String, Custom> cursor : metaData.customs()) {
        if (cursor.value.context().contains(context)) {
            builder.startObject(cursor.key);
            cursor.value.toXContent(builder, params);
            builder.endObject();
        }
    }
    builder.endObject();
}

集群元信息持久化时机有两个:其一是节点启动时验证集群的元信息有变化则会重新持久化,其二是集群的元信息发生变化(集群的配置发生变化)则会重新初始化。

索引元信息读取时机:节点启动时用于恢复索引集群元信息用于数据恢复。

节点元信息

1、具体内容

节点的元信息包括:

代码语言:txt复制
private final String nodeId;

对应类图如下:

evernotecid://9B7AC1A3-2163-4103-A68D-1127DA246949/appyinxiangcom/8902081/ENResource/p3148

image.pngimage.png

节点元信息主要是用于在集群中唯一标记节点,以便ES在进行各项操作时能唯一区分节点。

2、持久化

节点元信息会保存在磁盘上,作用:,对应文件路径路径:${data.path}/nodes/${node.id}/_state/node-xxx.st

实现元信息序列化的代码:

代码语言:txt复制
public void toXContent(XContentBuilder builder, NodeMetaData nodeMetaData) throws IOException {
    builder.field(NODE_ID_KEY, nodeMetaData.nodeId);
}

节点元信息持久化时机:节点启动时会持久化,并且及时已经持久化了会再次写入目的是保证所有的路径上有最新的节点元信息。

索引元信息读取时机:节点启动时读取,如果节点元信息不存在则会为节点生成新的节点元信息。

0 人点赞