ES在建立索引的时候和Lucene是有一定区别的,因为它对Lucene进行了一定的优化,内部还牵涉到分布式索引的分发,下面就详细的分析一下写入原理思想以及流程和对应节点的处理
一:写入原理以及特性
1 写入索引的时候,首先先写入到lucene,然后再写入到translog,主要原因如下
.Lucene的内存写入会有很复杂的逻辑,很容易失败
.避免TransLog中有大量无效记录,减少recover的复杂度和提高速度
2 写入索引需要考虑到下面各个维度
可靠性:或者是持久性,数据写入系统成功后,数据不会被回滚或丢失
一致性:数据写入成功后,再次查询时必须能保证读取到最新版本的数据,不能读取到旧数据
原子性:一个写入或者更新操作,要么完全成功,要么完全失败,不允许出现中间状态
隔离性:多个写入操作相互不影响
实时性:写入后是否可以立即被查询到
性能:写入性能,吞吐量
二:写入流程
索引的写入过程是比较复杂的,集群中的各个节点都需要承担一部分工作,下面把常规节点在写入索引过程中具体是干什么的,分析一下
1 ClientNode:客户端节点
> Ingest Pipeline
对原始文档做一些处理,比如HTML解析,自定义的处理,具体处理逻辑可以通过插件来实现
> Auto Create Index
判断当前Index是否存在,如果不存在,则需要自动创建Index,这里需要和Master交互
> Set Routing
如果Request中指定了路由条件,则直接使用Request中的Routing,否则使用Mapping中配置的,如果Mapping中无配置,则使用默认的_id字段值。
> Construct BulkShardRequest
同一个Shard中的请求聚集在一起,构建BulkShardRequest,每个BulkShardRequest对应一个Shard
> Send Request To Primary
将每一个BulkShardRequest请求发送给相应Shard的Primary Node
2 PrimaryNode:主节点
> Index or Update or Delete
循环执行每个Single Write Request,对于每个Request选择不同的逻辑来处理
> Translate Update To Index or Delete
Update操作的特有步骤:
会通过GetRequest查询到已经存在的同_id Doc
(如果有)的完整字段和值(依赖_source字段),然后和请求中的Doc合并
获取到读到的Doc版本号,记做V1。
> Parse Doc
这里会解析Doc中各个字段。生成ParsedDocument对象,同时会生成uid Term
> Update Mapping
有个自动更新Mapping的功能,就在这一步生效
> Get Sequence Id and Version
。则会从SequenceNumber Service获取一个sequenceID和Version
。SequenceID在Shard级别每次递增1,SequenceID在写入Doc成功后,会用来初始化LocalCheckpoint
> Add Doc To Lucene
索引写入LUCENE,此时索引文件是保存在内存中,对查询不可见
> Write Translog
。索引写入LUCENE,此时索引文件是保存在内存中,对查询不可见
。写完Lucene的Segment后,会以keyvalue的形式写TransLog,Key是_id,Value是Doc内容
。当查询的时候,如果请求是GetDocByID,则可以直接根据_id从TransLog中读取到,满足NoSQL场景下的实时性要去
> Renew Bulk Request
。这里会重新构造Bulk Request,原因是前面已经将UpdateRequest翻译成了Index或Delete请求
。不需要再执行Update逻辑,一是保证Replica中逻辑更简单,性能更好,二是保证同一个请求在Primary和Replica中的执行结果一样
> Flush Translog
这里会根据TransLog的策略,选择不同的执行方式,要么是立即Flush到磁盘,要么是等到以后再Flush
Flush的频率越高,可靠性越高,对写入性能影响越大
> Send Requests To Replicas
将刚才构造的新的Bulk Request并行发送给多个Replica,然后等待Replica的返回,等待多个Replica成功返回后,Primary Node才会返回用户
具体需要多少Replica Node返回,可以通过配置或者请求参数设置
> Receive Response From Replicas
Replica中请求都处理完后,且满足最小Replica返回数后,会更新Primary Node的LocalCheckPoint
3 ReplicaNode:副本节点
Replica中请求都处理完后,且满足最小Replica返回数后,会更新Primary Node的LocalCheckPoint
三:牵涉源码类
TransportShardBulkAction:批量传输主节点Request
TransportReplicationAction:批量传输副本节点Request
PrimaryOperationTransportHandler:处理主节点
ReplicaOperationTransportHandler:处理副本节点之间的数据
对于索引的写入,如果数据量很大的话,索引也是需要进行一定的优化,这个后面会有专门的章节来讲述的.