ES学习笔记之--delete api的实现流程

ES的delete api使用很是简单。node

curl -XDELETE 'http://localhost:9200/index/type/doc_id'

前面学习了get api的主要流程,这里探索一下delete api的实现原理。 优先选择delete api而非index api, 主要是以为删除貌似更容易, 选择delete api学习曲线应该比较平缓。api

ES相关功能Action的命名很统一, 好比get api, 对应实现类的名称为TransportGetAction, delete api对应实现类的名称也是依样画葫芦: TransportDeleteActioncurl

可是学习TransportDeleteAction, 其核心流程在其父类: TransportReplicationAction。 我的以为这个名字起得很差,让人觉得是只会在副本上执行相关功能的意思。ide

了解TransportReplicationAction以前,先说一下delete api的执行流程,就是剧透结果,再解析剧情。学习

从ES中删除一个文档的过程以下: 先从主分片中执行删除操做,再在全部的副本分片上执行删除操做。 因此核心流程分三步:

s1: 从请求节点路由到主分片节点。

s2: 在主分片节点执行删除操做。

s3: 在全部的副本分片上执行删除操做。

按如上所述, 在TransportReplicationAction类中,对应着三个子类:this

class name 功能
ReroutePhase 将请求路由到primary 分片所在的节点
PrimaryPhase 在主分片执行任务
ReplicationPhase 在全部的replica分片上执行任务

这个结构是通用的,就像模板同样。 这个类有个注释,解释了类的运行流程:url

/**
 * Base class for requests that should be executed on a primary copy followed by replica copies.
 * Subclasses can resolve the target shard and provide implementation for primary and replica operations.
 *
 * The action samples cluster state on the receiving node to reroute to node with primary copy and on the
 * primary node to validate request before primary operation followed by sampling state again for resolving
 * nodes with replica copies to perform replication.
 */

解释起来有以下的关键几点:插件

1. 基于该类的请求先会在primary shard执行,而后在replica shard执行。
2. 具体执行的操做由子类实现,好比`TransportDeleteAction`就实现了删除的操做。
3. 每一个节点在执行相关的操做前须要基于cluster state对请求参数进行验证。这个验证对应的方法就是`resolveRequest`

基于这个流程,能够看出,删除操做仍是比较重量级的, 副本越多,删除的代价就越大。 code

因为ES每一个节点代码都是同样的,因此默认状况下每一个节点的可扮演的角色是自由切换的。 这里主要是在研读transportService.sendRequest()方法时的一个小窍门。 好比代码:orm

void performOnReplica(final ShardRouting shard) {
            // if we don't have that node, it means that it might have failed and will be created again, in
            // this case, we don't have to do the operation, and just let it failover
            final String nodeId = shard.currentNodeId();

            ...

            final DiscoveryNode node = nodes.get(nodeId);
            transportService.sendRequest(node, transportReplicaAction, ... ){
                ...
            }
        }

这里transportService.sendRequest()后,接受的逻辑在哪里呢?

transportService.registerRequestHandler(actionName, request, ThreadPool.Names.SAME, new OperationTransportHandler());
  transportService.registerRequestHandler(transportPrimaryAction, request, executor, new PrimaryOperationTransportHandler());
 // we must never reject on because of thread pool capacity on replicas
  transportService.registerRequestHandler(transportReplicaAction, replicaRequest, executor, true, true, new ReplicaOperationTransportHandler());

也就是说transportService.sendRequest()的第二个参数actiontransportService.registerRequestHandler()的第一个参数action是一一对应的。
遇到transportService.sendRequest()直接经过action参数找到对应的Handler便可。好比PrimaryOperationTransportHandler就是用于接收ReroutePhase().run()方法中发送出去的请求。

回到TransportDeleteAction, 来理解ES删除的逻辑,整个类就只须要理解2个方法:

# 在primary shard执行的删除逻辑
shardOperationOnPrimary()

# 在replica shard执行的删除逻辑
executeDeleteRequestOnReplica()

这里面就是删除的具体逻辑,Engine相关的内容后续再深刻。

关于删除,ES提供的是delete by id的思路。 早期ES是支持经过query批量删除的,后来以为这个功能太过危险,就将delete by query作成了Plugin, 由用户自行安装插件后才能使用。 关于ES批量删除的思路,能够参考delete by query插件的源码,大致思路是经过scroll query 按条件查询出doc id, 而后使用client.bulk()进行删除。

最后,因为TransportReplicationAction是个比较通用的模式,因此ES其余的功能也是基于这个模式的, 好比: TransportIndexAction

相关文章
相关标签/搜索