elasticsearch
1、索引入口RestIndexAction方法中prepareRequest,封装IndexRequest,并由NodeClient调用index方法
client.index(indexRequest, new RestStatusToXContentListener<>(channel, r -> r.getLocation(indexRequest.routing())));
2、中间经过一些抽象类中方法调用后来到NodeClient类中的executeLocally方法,经过一系列的判断校验等到TransportIndexAction
3、TransportIndexAction中doExecute方法会有一个判断是否自动创建索引,暂时先考虑不自动创建
ClusterState state = clusterService.state();
if (shouldAutoCreate(request, state)) { //是否自动创建索引
...................................................
} else {
innerExecute(task, request, listener);
}
4、主要操作都在TransportReplicationAction类中,ReroutePhase内部类中的doRun方法判断是否本地执行
5、TransportReplicationAction中AsyncPrimaryAction异步执行索引操作
6、ReplicationOperation执行execute方法,primary.perform(request)主分片索引,
public void execute() throws Exception {
final String activeShardCountFailure = checkActiveShardCount();
final ShardRouting primaryRouting = primary.routingEntry();
final ShardId primaryId = primaryRouting.shardId();
if (activeShardCountFailure != null) {
finishAsFailed(new UnavailableShardsException(primaryId,
"{} Timeout: [{}], request: [{}]", activeShardCountFailure, request.timeout(), request));
return;
}
totalShards.incrementAndGet();
pendingActions.incrementAndGet();
primaryResult = primary.perform(request); //主分片索引
final ReplicaRequest replicaRequest = primaryResult.replicaRequest();
assert replicaRequest.primaryTerm() > 0 : "replicaRequest doesn't have a primary term";
if (logger.isTraceEnabled()) {
logger.trace("[{}] op [{}] completed on primary for request [{}]", primaryId, opType, request);
}
// we have to get a new state after successfully indexing into the primary in order to honour recovery semantics.
// we have to make sure that every operation indexed into the primary after recovery start will also be replicated
// to the recovery target. If we use an old cluster state, we may miss a relocation that has started since then.
ClusterState clusterState = clusterStateSupplier.get();
final List<ShardRouting> shards = getShards(primaryId, clusterState);
Set<String> inSyncAllocationIds = getInSyncAllocationIds(primaryId, clusterState);
markUnavailableShardsAsStale(replicaRequest, inSyncAllocationIds, shards); //标记不可用副本分片
performOnReplicas(replicaRequest, shards); //副本 和主分片相同入库到内存并标记Translog
successfulShards.incrementAndGet();
decPendingAndFinishIfNeeded();
}
public static WriteResult<IndexResponse> executeIndexRequestOnPrimary(IndexRequest request, IndexShard indexShard,
MappingUpdatedAction mappingUpdatedAction) throws Exception {
Engine.Index operation = prepareIndexOperationOnPrimary(request, indexShard); //模板合并等操作并封装Engine.Index
Mapping update = operation.parsedDoc().dynamicMappingsUpdate();
final ShardId shardId = indexShard.shardId();
if (update != null) {
mappingUpdatedAction.updateMappingOnMaster(shardId.getIndex(), request.type(), update); //master模板修改
operation = prepareIndexOperationOnPrimary(request, indexShard);
update = operation.parsedDoc().dynamicMappingsUpdate();
if (update != null) {
throw new ReplicationOperation.RetryOnPrimaryException(shardId,
"Dynamic mappings are not available on the node that holds the primary yet");
}
}
indexShard.index(operation); //索引入内存并添加Translog
// update the version on request so it will happen on the replicas
final long version = operation.version();
request.version(version);
request.versionType(request.versionType().versionTypeForReplicationAndRecovery());
assert request.versionType().validateVersionForWrites(request.version());
IndexResponse response = new IndexResponse(shardId, request.type(), request.id(), request.version(), operation.isCreated());
return new WriteResult<>(response, operation.getTranslogLocation());
}