悟空,拿我的打狗棒来

get 方法的realtime参数的疑惑

Elasticsearch | 作者 code4j | 发布于2019年02月26日 | 阅读数:4587

今天看了下get的实现原理,对其中realtime这个参数的使用不解
 
@Override
protected GetResponse shardOperation(GetRequest request, ShardId shardId) {
IndexService indexService = indicesService.indexServiceSafe(shardId.getIndex());
IndexShard indexShard = indexService.getShard(shardId.id());

if (request.refresh() && !request.realtime()) {
indexShard.refresh("refresh_flag_get");
}

GetResult result = indexShard.getService().get(request.type(), request.id(), request.storedFields(),
request.realtime(), request.version(), request.versionType(), request.fetchSourceContext());
return new GetResponse(result);
}
这块是其中的一个实现。
从  request.refresh() && !request.realtime() 这个逻辑可以得出,只有设置了refresh并且realtime是关闭的情况下,才会在此处主动触发一次refresh。
 
然后有关realtime的逻辑还在IntrenalGet中出现过一次:
if (get.realtime()) {
VersionValue versionValue = versionMap.getUnderLock(get.uid().bytes());
if (versionValue != null) {
if (versionValue.isDelete()) {
return GetResult.NOT_EXISTS;
}
if (get.versionType().isVersionConflictForReads(versionValue.getVersion(), get.version())) {
throw new VersionConflictEngineException(shardId, get.type(), get.id(),
get.versionType().explainConflictForReads(versionValue.getVersion(), get.version()));
}
refresh("realtime_get");
}
}
在这里如果开启了realtime且能够起到刷新的作用。
 
 
那问题就是,第一个逻辑干嘛还要有一个realtime的判断。而且默认realtime 从controller来的时候是true,那么在上文!request.realtime() 就是false,也就是默认情况下,这里面的refresh是不会执行的(等于refresh在这一步被架空了)。所以这块是做什么用的呢?感觉意义不明确
已邀请:

rochy - rochy_he

赞同来自:

Indicates that a request can execute in realtime (reads from the translog).
 
简单来说就是 realtime = true 的时候,Get 会直接从 translog 读取内容

hapjin

赞同来自:

1,GET 操作不受 refresh 发生频率的影响。


 the get API is realtime, and is not affected by the refresh rate of the index (when data will become visible for search).​


2,GET API 会触发 refresh 操作。参考:docs-get


 If a document has been updated but is not yet refreshed, the get API will issue a refresh call in-place to make the document visible


3,看ES6.3.2源码注释的话,普通 GET 操作应该是不会从translog读数据的。结合上面第2条和下面的源码注释,如果UPDATE了一个文档且尚未refreshed,那么GET 就会触发refresh。
 
(org.elasticsearch.index.engine.InternalEngine#get)
                    if (get.isReadFromTranslog()) {
// [b]this is only used for updates - API _GET calls will always read form a reader for consistency
[/b] // the update call doesn't need the consistency since it's source only + _parent but parent can go away in 7.0
4,调用了org.elasticsearch.index.engine.InternalEngine#refresh(java.lang.String, org.elasticsearch.index.engine.Engine.SearcherScope)方法,并不一定会真正的发生refresh动作,参考:org.apache.lucene.search.ReferenceManager#doMaybeRefresh方法的实现。
 5,很好奇 GET 操作会触发refresh吗?或者说:GET操作在什么情况下会触发refresh。
 
6,除了这条语句:request.refresh() && !request.realtime() 外,还有个地方会调用refresh()方法:
if (get.realtime()) {
VersionValue versionValue = null;
try (Releasable ignore = versionMap.acquireLock(get.uid().bytes())) {
// we need to lock here to access the version map to do this truly in RT
versionValue = getVersionFromMap(get.uid().bytes());
}
if (versionValue != null) {
if (versionValue.isDelete()) {
return GetResult.NOT_EXISTS;
}
if (get.versionType().isVersionConflictForReads(versionValue.version, get.version())) {
throw new VersionConflictEngineException(shardId, get.type(), get.id(),
get.versionType().explainConflictForReads(versionValue.version, get.version()));
}
if (get.isReadFromTranslog()) {
// this is only used for updates - API _GET calls will always read form a reader for consistency
// the update call doesn't need the consistency since it's source only + _parent but parent can go away in 7.0
if (versionValue.getLocation() != null) {
try {
Translog.Operation operation = translog.readOperation(versionValue.getLocation());
if (operation != null) {
// in the case of a already pruned translog generation we might get null here - yet very unlikely
TranslogLeafReader reader = new TranslogLeafReader((Translog.Index) operation, engineConfig
.getIndexSettings().getIndexVersionCreated());
return new GetResult(new Searcher("realtime_get", new IndexSearcher(reader)),
new VersionsAndSeqNoResolver.DocIdAndVersion(0, ((Translog.Index) operation).version(), reader, 0));
}
} catch (IOException e) {
maybeFailEngine("realtime_get", e); // lets check if the translog has failed with a tragic event
throw new EngineException(shardId, "failed to read operation from translog", e);
}
} else {
trackTranslogLocation.set(true);
}
}

refresh("realtime_get", SearcherScope.INTERNAL);
}
scope = SearcherScope.INTERNAL;
}else{
//...
}
 
org.elasticsearch.index.get.ShardGetService#innerGet方法的 readFromTranslog参数是false

get_result.png

 

xieqiao

赞同来自:

7.x 的源码,初始化Engine.Get的readFromTranslog一并使用realtime参数,realtime参数为true时,将从translog中获取

2.png


1.png

 

要回复问题请先登录注册