elasticsearch索引index之engine读写控制结构实现
作者:zziawan 发布时间:2021-12-22 00:08:07
engine的实现结构
elasticsearch对于索引中的数据操作如读写get等接口都封装在engine中,同时engine还封装了索引的读写控制,如流量、错误处理等。engine是离lucene最近的一部分。
engine的实现结构如下所示:
engine接口有三个实现类,主要逻辑都在InternalEngine中。
ShadowEngine之实现了engine接口的部分读方法,主要用于对于索引的读操作。
shardFSEngine在InternalEngine的基础上实现了recovery方法,它的功能跟InternalEngine基本相同只是它的recovery过程有区别,不会对Translog和index进行快照存储。
Engine类定义了一些index操作的主要方法和内部类,方法如create,index等。内部类如index,delete等。这些方法的实现是在子类中,这些方法的参数是这些内部类。
Engine类的方法:
public abstract void create(Create create) throws EngineException;
public abstract void index(Index index) throws EngineException;
public abstract void delete(Delete delete) throws EngineException;
public abstract void delete(DeleteByQuery delete) throws EngineException;
这些抽象方法都在子类中实现,它们的参数都是一类,这些都是Engine的内部类,这些内部类类似于实体类,没有相关逻辑只是由很多filed及get方法构成。如Create和Index都继承自IndexOperation,它们所有信息都存储到IndexOperation的相关Field中,IndexOperation如下所示:
public static abstract class IndexingOperation implements Operation {
private final DocumentMapper docMapper;
private final Term uid;
private final ParsedDocument doc;
private long version;
private final VersionType versionType;
private final Origin origin;
private final boolean canHaveDuplicates;
private final long startTime;
private long endTime;
………………
}
无论是Index还是Create,相关数据和配置都在doc中,根据doc和docMapper就能够获取本次操作的所有信息,另外的一些字段如version,uid都是在类初始化时构建。这样传给实际方法的是一个class,在方法内部根据需求获取到相应的数据
如index方法的实现:
private void innerIndex(Index index) throws IOException {
synchronized (dirtyLock(index.uid())) {
final long currentVersion;
VersionValue versionValue = versionMap.getUnderLock(index.uid().bytes());
if (versionValue == null) {
currentVersion = loadCurrentVersionFromIndex(index.uid());
} else {
if (engineConfig.isEnableGcDeletes() && versionValue.delete() && (engineConfig.getThreadPool().estimatedTimeInMillis() - versionValue.time()) > engineConfig.getGcDeletesInMillis()) {
currentVersion = Versions.NOT_FOUND; // deleted, and GC
} else {
currentVersion = versionValue.version();
}
}
long updatedVersion;
long expectedVersion = index.version();
if (index.versionType().isVersionConflictForWrites(currentVersion, expectedVersion)) {
if (index.origin() == Operation.Origin.RECOVERY) {
return;
} else {
throw new VersionConflictEngineException(shardId, index.type(), index.id(), currentVersion, expectedVersion);
}
}
updatedVersion = index.versionType().updateVersion(currentVersion, expectedVersion);
index.updateVersion(updatedVersion);
if (currentVersion == Versions.NOT_FOUND) {
// document does not exists, we can optimize for create
index.created(true);
if (index.docs().size() > 1) {
indexWriter.addDocuments(index.docs(), index.analyzer());
} else {
indexWriter.addDocument(index.docs().get(0), index.analyzer());
}
} else {
if (versionValue != null) {
index.created(versionValue.delete()); // we have a delete which is not GC'ed...
}
if (index.docs().size() > 1) {
indexWriter.updateDocuments(index.uid(), index.docs(), index.analyzer());//获取IndexOperation中doc中字段更新索引
} else {
indexWriter.updateDocument(index.uid(), index.docs().get(0), index.analyzer());
}
}
Translog.Location translogLocation = translog.add(new Translog.Index(index));//写translog
versionMap.putUnderLock(index.uid().bytes(), new VersionValue(updatedVersion, translogLocation));
indexingService.postIndexUnderLock(index);
}
}
这就是Engine中create、index这些方法的实现方式。后面分析索引过程中会有更加详细说明。Engine中还有获取索引状态(元数据)及索引操作的方法如merge。这些方法也是在子类中调用lucene的相关接口,跟create,index,get很类似。因为没有深入Engine的方法实现,因此这里的分析比较简单,后面的分析会涉及这里面很多方法。
来源:https://www.cnblogs.com/zziawanblog/p/6798964.html


猜你喜欢
- 业务背景电商订单项目分正向和逆向两个部分:其中正向数据库记录了订单的基本信息,包括订单基本信息、订单商品信息、优惠卷信息、发票信息、账期信息
- 前言:在java的网络通信中,两个不同节点的主机想要进行通信则可以通过建立Socket对象(相当于客户端主机,向服务端请求发送信息)和Ser
- 1.项目简绍本项目使用SpringBoot开发,jdbc5.1.48 Mybatis 源码可下载其中涉及功能有:Mybatis的使用,Thy
- 书上对 i ++ 和 ++ i 的解释如下:int i = 3,a = 0 ;i ++ : 先赋值再运算;例如:a = i ++
- 一、排序与去重日常工作中,总会有一些场景需要对结果集进行一些过滤。比如,与第三方交互后获取的结果集,需要再次排序去重,此时就会根据某个字段来
- 一:获取根目录的方法取得控制台应用程序的根目录方法方法1、Environment.CurrentDirectory 取得或设置当前工作目录的
- Math.abs()的实现源码通过三目运算符判断a是否小于0来实现/** * Returns the absolute valu
- zuul动态路由网关服务是流量的唯一入口。不能随便停服务。所以动态路由就显得尤为必要。数据库动态路由基于事件刷新机制热修改zuul的路由属性
- 目录微服务微服务架构SpringCould简介环境搭建1. 创建数据库2. 新建一个子模块api3. 新建一个子模块provider作为服务
- 一、引入pom<?xml version="1.0" encoding="UTF-8"?>
- 背景当一个项目分了很多模块,很多个服务的时候,一些公共的配置就需要统一管理了,于是就有了元数据驱动!简介什么是Calcite?是一款开源SQ
- a)原理:每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕。也就是:每一趟在n-i+1(i=1,2,…
- 本文实例讲述了C#获取两个时间的时间差并去除周末的方法。分享给大家供大家参考。具体分析如下:一般来说取时间差的代码很多,但是能够只取工作日的
- 为避免繁琐的注册登陆,很多平台和网站都会实现三方登陆的功能,增强用户的粘性。这篇文章主要介绍了java实现微信扫码登录第三方网站功能(原理和
- 本文实例讲述了Java Web开发之基于Session的购物商店实现方法。分享给大家供大家参考,具体如下:package cn.com.sh
- C#如何安全、高效地玩转任何种类的内存之Span的本质一、what - 痛点是什么?回答这个问题前,先总结一下如何用C#操作任何类型的内存:
- Main方法如下:static void Main(string[] args){ dynamic st
- 单例模式单例模式顾名思义就是单一的实例,涉及到一个单一的类,该类负责创建自己的对象,同时确保只有一个对象被创建,并且提供一种可以访问这个对象
- 一、导入前言:导入必须用post请求具体原因在2中叙述1、Excel导入总结一下目标,就是要将excel中的数据行、逐一提取,最后得到一个l
- SpringCloud简介Spring cloud是一个基于Spring Boot实现的服务治理工具包,在微服务架构中用于管理和协调服务的微