Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >ElasticSearch Recovery 分析

ElasticSearch Recovery 分析

作者头像
用户2936994
发布于 2018-08-27 02:37:04
发布于 2018-08-27 02:37:04
1.5K00
代码可运行
举报
文章被收录于专栏:祝威廉祝威廉
运行总次数:0
代码可运行

上周出现了一次故障,recovery的过程比较慢,然后发现Shard 在做恢复的过程一般都是卡在TRANSLOG阶段,所以好奇这块是怎么完成的,于是有了这篇文章

这是一篇源码分析类的文章,大家需要先建立一个整体的概念,建议参看这篇文章

另外你可能还需要了解下 Recovery 阶段迁移过程:

INIT -> INDEX -> VERIFY_INDEX -> TRANSLOG -> FINALIZE -> DONE

概览

Recovery 其实有两种:

  1. Primary的迁移/Replication的生成和迁移
  2. Primary的恢复

org.elasticsearch.indices.cluster.IndicesClusterStateService.clusterChanged 被触发后,会触发applyNewOrUpdatedShards 函数的调用,这里是我们整个分析的起点。大家可以跑进去看看,然后跟着文章打开对应的源码浏览。

阅读完这篇文章,我们能够得到:

  1. 熟悉整个recovery 流程
  2. 了解translog机制
  3. 掌握对应的代码体系结构

Primary的恢复

这个是一般出现故障集群重启的时候可能遇到的。首先需要从Store里进行恢复。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (isPeerRecovery(shardRouting)) {
   ......
}
else {
  //走的这个分支
  indexService.shard(shardId).recoverFromStore(shardRouting, 
  new StoreRecoveryService.RecoveryListener() {
}

Primary 进行自我恢复,所以并不需要其他节点的支持。所以判定的函数叫做isPeerRecovery 其实还是挺合适的。

indexService.shard(shardId).recoverFromStore 调用的是 org.elasticsearch.index.shard.IndexShard的方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  public void recoverFromStore(ShardRouting shard, StoreRecoveryService.RecoveryListener recoveryListener) {
    ......
    final boolean shouldExist = shard.allocatedPostIndexCreate();
    storeRecoveryService.recover(this, shouldExist, recoveryListener);
    }

逻辑还是很清晰的,判断分片必须存在,接着将任务委托给 org.elasticsearch.index.shard.StoreRecoveryService.recover 方法,该方法有个细节需要了解下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 if (indexShard.routingEntry().restoreSource() != null) {
       indexShard.recovering("from snapshot", 
           RecoveryState.Type.SNAPSHOT, 
           indexShard.routingEntry().restoreSource());
            } else {
       indexShard.recovering("from store", 
           RecoveryState.Type.STORE, 
           clusterService.localNode());
            }

ES会根据restoreSource 决定是从SNAPSHOT或者从Store里进行恢复。这里的indexShard.recovering并没有执行真正的recovering 操作,而是返回了一个recover的信息对象,里面包含了譬如节点之类的信息。

之后就将其作为一个任务提交出去了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
threadPool.generic().execute(new Runnable() {
            @Override
  public void run() {
  try {
  final RecoveryState recoveryState = indexShard.recoveryState();
  if (indexShard.routingEntry().restoreSource() != null) {
     restore(indexShard, recoveryState);
     } else {              
     recoverFromStore(indexShard, indexShouldExists, recoveryState);
    }

这里我们只走一条线,也就是进入 recoverFromStore 方法,该方法会执行索引文件的恢复动作,本质上是进入了INDEX Stage.

接着进行TranslogRecovery了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
typesToUpdate = indexShard.performTranslogRecovery(indexShouldExists);
indexShard.finalizeRecovery();

继续进入 indexShard.performTranslogRecovery 方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  public Map<String, Mapping> performTranslogRecovery(boolean indexExists) {
        if (indexExists == false) {            
            final RecoveryState.Translog translogStats = recoveryState().getTranslog();
            translogStats.totalOperations(0);
            translogStats.totalOperationsOnStart(0);
        }
        final Map<String, Mapping> recoveredTypes = internalPerformTranslogRecovery(false, indexExists);     
        return recoveredTypes;
    }

这个方法里面,最核心的是 internalPerformTranslogRecovery方法,进入该方法后先进入 VERIFY_INDEX Stage,进行索引的校验,校验如果没有问题,就会进入我们期待的TRANSLOG 状态了。

进入TRANSLOG 后,先进行一些设置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
engineConfig.setEnableGcDeletes(false);
engineConfig.setCreate(indexExists == false);

这里的GC 指的是tranlog日志的删除问题,也就是不允许删除translog,接着会创建一个新的InternalEngine了,然后返回调用org.elasticsearch.index.shard.TranslogRecoveryPerformer.getRecoveredTypes

不过你看这个代码会比较疑惑,其实我一开始看也觉得纳闷:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  if (skipTranslogRecovery == false) {            
       markLastWrite();
        }
 createNewEngine(skipTranslogRecovery, engineConfig);
 return  engineConfig.getTranslogRecoveryPerformer().
                                  getRecoveredTypes();

我们并没有看到做translog replay的地方,而从上层的调用方来看:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
typesToUpdate = indexShard.performTranslogRecovery(indexShouldExists);
indexShard.finalizeRecovery();

performTranslogRecovery 返回后,就立马进入扫尾(finalizeRecovery)阶段。 里面唯一的动作是createNewEngine,并且传递了skipTranslogRecovery 参数。 也就说,真正的translog replay动作是在createNewEngine里完成,我们经过探索,发现是在InternalEngine 的初始化过程完成的,具体代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try {
      if (skipInitialTranslogRecovery) {
          commitIndexWriter(writer,
                                       translog, 
                                       lastCommittedSegmentInfos.
                                       getUserData().
                                       get(SYNC_COMMIT_ID));
                } else {
                    recoverFromTranslog(engineConfig, translogGeneration);
                }
            } catch (IOException | EngineException ex) {
              .......
            }

里面有个recoverFromTranslog,我们进去瞅瞅:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   final TranslogRecoveryPerformer handler = engineConfig.getTranslogRecoveryPerformer();
        try (Translog.Snapshot snapshot = translog.newSnapshot()) {
            opsRecovered = handler.recoveryFromSnapshot(this, snapshot);
        } catch (Throwable e) {
            throw new EngineException(shardId, "failed to recover from translog", e);
        }

目前来看,所有的Translog recovery 动作其实都是由 TranslogRecoveryPerformer 来完成的。当然这个名字也比较好,翻译过来就是 TranslogRecovery 执行者。先对translog 做一个snapshot,然后根据这个snapshot开始进行恢复,进入 recoveryFromSnapshot 方法我们查看细节,然后会引导你进入

下面的方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 public void performRecoveryOperation(Engine engine, Translog.Operation operation, boolean allowMappingUpdates) {
        try {
            switch (operation.opType()) {
                case CREATE:
                    Translog.Create create = (Translog.Create) operation;
                    Engine.Create engineCreate = IndexShard.prepareCreate(docMapper(create.type()),
                            source(create.source()).index(shardId.getIndex()).type(create.type()).id(create.id())
                                    .routing(create.routing()).parent(create.parent()).timestamp(create.timestamp()).ttl(create.ttl()),
                            create.version(), create.versionType().versionTypeForReplicationAndRecovery(), Engine.Operation.Origin.RECOVERY, true, false);
                    maybeAddMappingUpdate(engineCreate.type(), engineCreate.parsedDoc().dynamicMappingsUpdate(), engineCreate.id(), allowMappingUpdates);
                    if (logger.isTraceEnabled()) {
                        logger.trace("[translog] recover [create] op of [{}][{}]", create.type(), create.id());
                    }
                    engine.create(engineCreate);
                    break;

终于看到了实际的translog replay 逻辑了。这里调用了标准的InternalEngine.create 等方法进行日志的恢复。其实比较有意思的是,我们在日志回放的过程中,依然会继续写translog。这里就会导致一个问题,如果我在做日志回放的过程中,服务器由当掉了(或者ES instance 重启了),那么就会导致translog 变多了。这个地方是否可以再优化下?

假设我们完成了Translog 回放后,如果确实有重放,那么就行flush动作,删除translog,否则就commit Index。具体逻辑由如下的代码来完成:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (opsRecovered > 0) {
     opsRecovered, translogGeneration == null ? null : translogGeneration.translogFileGeneration, translog
                            .currentFileGeneration());
            flush(true, true);
        } else if (translog.isCurrent(translogGeneration) == false) {
            commitIndexWriter(indexWriter, translog, lastCommittedSegmentInfos.getUserData().get(Engine.SYNC_COMMIT_ID));
        }

接着就进入了finalizeRecovery,然后,就没然后了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 indexShard.finalizeRecovery();
            String indexName = indexShard.shardId().index().name();
            for (Map.Entry<String, Mapping> entry : typesToUpdate.entrySet()) {
                validateMappingUpdate(indexName, entry.getKey(), entry.getValue());
            }
            indexShard.postRecovery("post recovery from shard_store");

Primary的迁移/Replication的生成和迁移

一般这种recovery其实就是发生relocation或者调整副本的时候发生的。所以集群是在正常状态,一定有健康的primary shard存在,所以我们也把这种recovery叫做Peer Recovery。 入口和前面的Primary恢复是一样的,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (isPeerRecovery(shardRouting)) {
 //走的这个分支
.....
RecoveryState.Type type = shardRouting.primary() ? RecoveryState.Type.RELOCATION : RecoveryState.Type.REPLICA;
                recoveryTarget.startRecovery(indexShard, type, sourceNode, new PeerRecoveryListener(shardRouting, indexService, indexMetaData));
......           
}
else {
 ......
}

核心代码自然是 recoveryTarget.startRecovery。这里的recoveryTarget的类型是: org.elasticsearch.indices.recovery.RecoveryTarget

startRecovery方法的核心代码是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
threadPool.generic().execute(new RecoveryRunner(recoveryId));

也是启动一个县城异步执行的。RecoveryRunner调用的是RecoveryTarget的 doRecovery方法,在该方法里,会发出一个RPC请求:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
final StartRecoveryRequest request = new StartRecoveryRequest(recoveryStatus.shardId(), recoveryStatus.sourceNode(), clusterService.localNode(),        false, metadataSnapshot, recoveryStatus.state().getType(), recoveryStatus.recoveryId());

recoveryStatus.indexShard().prepareForIndexRecovery();
            recoveryStatus.CancellableThreads().execute(new CancellableThreads.Interruptable() {
                @Override
                public void run() throws InterruptedException {
                    responseHolder.set(transportService.submitRequest(request.sourceNode(), RecoverySource.Actions.START_RECOVERY, request, new FutureTransportResponseHandler<RecoveryResponse>() {
                        @Override
                        public RecoveryResponse newInstance() {
                            return new RecoveryResponse();
                        }
                    }).txGet());
                }
            });

这个时候进入 INDEX Stage。 那谁接受处理的呢? 我们先看看现在的类名叫啥? RecoveryTarget。 我们想当然的想,是不是有RecoverySource呢? 发现确实有,而且该类确实也有一个处理类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 class StartRecoveryTransportRequestHandler extends TransportRequestHandler<StartRecoveryRequest> {
        @Override
        public void messageReceived(final StartRecoveryRequest request, final TransportChannel channel) throws Exception {
            RecoveryResponse response = recover(request);
            channel.sendResponse(response);
        }
    }

ES里这种通过Netty进行交互的方式,大家可以看看我之前写文章ElasticSearch Rest/RPC 接口解析

这里我们进入RecoverSource对象的recover方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 private RecoveryResponse recover(final StartRecoveryRequest request) {
      .....
      if (IndexMetaData.isOnSharedFilesystem(shard.indexSettings())) {
            handler = new SharedFSRecoverySourceHandler(shard, request, recoverySettings, transportService, logger);
        } else {
            handler = new RecoverySourceHandler(shard, request, recoverySettings, transportService, logger);
        }
        ongoingRecoveries.add(shard, handler);
        try {
            return handler.recoverToTarget();
        } finally {
            ongoingRecoveries.remove(shard, handler);
        }
 }

我们看到具体负责处理的类是RecoverySourceHandler,之后调用该类的recoverToTarget方法。我对下面的代码做了精简,方便大家看清楚。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public RecoveryResponse recoverToTarget() {
        final Engine engine = shard.engine();
        assert engine.getTranslog() != null : "translog must not be null";
        try (Translog.View translogView = engine.getTranslog().newView()) {
     
            final SnapshotIndexCommit phase1Snapshot;
            phase1Snapshot = shard.snapshotIndex(false);
            phase1(phase1Snapshot, translogView);
                      
            try (Translog.Snapshot phase2Snapshot = translogView.snapshot()) {
                phase2(phase2Snapshot);
            } catch (Throwable e) {
                throw new RecoveryEngineException(shard.shardId(), 2, "phase2 failed", e);
            }

            finalizeRecovery();
        }
        return response;
    }

首先创建一个Translog的视图(创建视图的细节我现在也还没研究),接着的话对当前的索引进行snapshot。 然后进入phase1阶段,该阶段是把索引文件和请求的进行对比,然后得出有差异的部分,主动将数据推送给请求方。之后进入文件清理阶段,然后就进入translog 阶段:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected void prepareTargetForTranslog(final Translog.View translogView) {

接着进入第二阶段:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try (Translog.Snapshot phase2Snapshot = translogView.snapshot()) {
                phase2(phase2Snapshot);           
            }

对当前的translogView 进行一次snapshot,然后进行translog发送:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int totalOperations = sendSnapshot(snapshot);

具体的发送逻辑如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 cancellableThreads.execute(new Interruptable() {
                    @Override
                    public void run() throws InterruptedException {
                        final RecoveryTranslogOperationsRequest translogOperationsRequest = new RecoveryTranslogOperationsRequest(
                                request.recoveryId(), request.shardId(), operations, snapshot.estimatedTotalOperations());
                        transportService.submitRequest(request.targetNode(), RecoveryTarget.Actions.TRANSLOG_OPS, translogOperationsRequest,
                                recoveryOptions, EmptyTransportResponseHandler.INSTANCE_SAME).txGet();
                    }
                });

这里发的请求,都是被 RecoveryTarget的TranslogOperationsRequestHandler 处理器来完成的,具体代码是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 @Override
        public void messageReceived(final RecoveryTranslogOperationsRequest request, final TransportChannel channel) throws Exception {
            try (RecoveriesCollection.StatusRef statusRef = onGoingRecoveries.getStatusSafe(request.recoveryId(), request.shardId())) {
                final ClusterStateObserver observer = new ClusterStateObserver(clusterService, null, logger);
                final RecoveryStatus recoveryStatus = statusRef.status();
                final RecoveryState.Translog translog = recoveryStatus.state().getTranslog();
                translog.totalOperations(request.totalTranslogOps());
                assert recoveryStatus.indexShard().recoveryState() == recoveryStatus.state();
                try {
                    recoveryStatus.indexShard().performBatchRecovery(request.operations());

这里调用IndexShard.performBatchRecovery进行translog 的回放。

最后发送一个finalizeRecovery给target 节点,完成recovering操作。

关于Recovery translog 配置相关

在如下的类里有:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//org.elasticsearch.index.translog.TranslogService
INDEX_TRANSLOG_FLUSH_INTERVAL = "index.translog.interval";
INDEX_TRANSLOG_FLUSH_THRESHOLD_OPS = "index.translog.flush_threshold_ops";
INDEX_TRANSLOG_FLUSH_THRESHOLD_SIZE = "index.translog.flush_threshold_size";
INDEX_TRANSLOG_FLUSH_THRESHOLD_PERIOD = "index.translog.flush_threshold_period";
INDEX_TRANSLOG_DISABLE_FLUSH = "index.translog.disable_flush";

当服务器恢复时发现有存在的translog日志,就会进入TRANSLOG 阶段进行replay。translog 的recovery 是走的标准的InternalEngine.create/update等方法,并且还会再写translog,同时还有一个影响性能的地方是很多数据可能已经存在,会走update操作,所以性能还是非常差的。这个目前能够想到的解决办法是调整flush日志的频率,保证存在的translog 尽量的少。 上面的话可以看出有三个控制选项:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//每隔interval的时间,就去检查下面三个条件决定是不是要进行flush,
//默认5s。时间过长,会超出下面阈值比较大。
index.translog.interval 

//超过多少条日志后需要flush,默认Int的最大值
index.translog.flush_threshold_ops 

//定时flush,默认30m 可动态设置
index.translog.flush_threshold_period

//translog 大小超过多少后flush,默认512m  
index.translog.flush_threshold_size

本质上translog的恢复速度和条数的影响关系更大些,所以建议大家设置下 index.translog.flush_threshold_ops,比如多少条就一定要flush,否则积累的太多,

出现故障,恢复就慢了。这些参数都可以动态设置,但建议放到配置文件。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016.07.01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
《Elasticsearch 源码解析与优化实战》第10章:索引恢复流程分析
索引恢复(index.recovery)是ES数据恢复过程。待恢复的数据是客户端写入成功,但未执行刷盘(flush)的Lucene分段。例如,当节点异常重启时,写入磁盘的数据先到文件系统的缓冲,未必来得及刷盘,如果不通过某种方式将未刷盘的数据找回来,则会丢失一些数据,这是保持数据完整性的体现;另一方面,由于写入操作在多个分片副本上没有来得及全部执行,副分片需要同步成和主分片完全一致,这是数据副本一致性的体现。
HLee
2021/05/27
2.5K0
《Elasticsearch 源码解析与优化实战》第10章:索引恢复流程分析
Elasticsearch 底层系列之分片恢复解析
我们是基础架构部,腾讯云 CES/CTSDB 产品后台服务的支持团队,我们拥有专业的ES开发运维能力,为大家提供稳定、高性能的服务,欢迎有需求的童鞋接入,同时也欢迎各位交流 Elasticsearch、Lucene 相关的技术!
luckiexie
2018/12/10
3.8K5
ElasticSearch Bulk 源码解析
读这篇文章前,建议先看看ElasticSearch Rest/RPC 接口解析,有利于你把握ElasticSearch接受处理请求的脉络。对于RPC类的调用,我会在后文简单提及,只是endpoint不一样,内部处理逻辑还是一样的。这篇只会讲IndexRequest,其他如DeleteRequest,UpdateRequest之类的,我们暂时不涉及。
用户2936994
2018/08/27
8900
Elasticsearch索引分片损坏该怎么办?(二)
本文描述问题及解决方法同样适用于 腾讯云 Elasticsearch Service(ES)。
岳涛
2021/10/08
3.2K3
Elasticsearch索引分片损坏该怎么办?(二)
Elasticsearch快照(snapshot)备份原理及分析
Snapshot是Elasticsearch提供的一种将集群数据备份至远程存储库的功能。例如将数据备份至S3,HDFS,共享文件系统等。
空洞的盒子
2024/08/02
2K3
如何提高ElasticSearch 索引速度
这篇文章会讲述上面几个参数的原理,以及一些其他的思路。这些参数大体上是朝着两个方向优化的:
用户2936994
2018/08/27
1.7K0
《Elasticsearch 源码解析与优化实战》第7章:写流程
本章分析ES写入单个和批量文档写请求的处理流程,仅限于ES内部实现,并不涉及Lucene内部处理。在ES中,写入单个文档的请求称为Index请求,批量写入的请求称为Bulk请求。写单个和多个文档使用相同的处理逻辑,请求被统一封装为BulkRequest。
HLee
2021/05/25
2.4K0
《Elasticsearch 源码解析与优化实战》第7章:写流程
《Elasticsearch 源码解析与优化实战》第12章:allocation模型分析
本文主要分析allocation 模块的结构和原理,然后以集群启动过程为例分析 allocation 模块的工作过程
HLee
2021/05/27
1.1K1
《Elasticsearch 源码解析与优化实战》第12章:allocation模型分析
ES系列(五):获取单条数据get处理过程实现
前面讲的都是些比较大的东西,即框架层面的东西。今天咱们来个轻松点的,只讲一个点:如题,get单条记录的es查询实现。
烂猪皮
2021/06/10
1.3K0
ES系列(五):获取单条数据get处理过程实现
Elasticsearch索引分片损坏该怎么办?
那么这种情况发生的原因是什么呢?我们要知道,索引分片是不可能无故发生损坏的,分片所在的节点一定发生过异常。
周银辉
2024/08/27
4070
Elasticsearch源码分析-写入解析
Elasticsearch(ES)是一个基于Lucene的近实时分布式存储及搜索分析系统,其应用场景广泛,可应用于日志分析、全文检索、结构化数据分析等多种场景,既可作为NoSQL数据库,也可作为搜索引擎。由于ES具备如此强悍的能力,因此吸引了很多公司争相使用,如维基百科、GitHub、Stack Overflow等。
技术姐
2018/11/07
6K0
Elasticsearch7.0.0~7.6.2版本bug:大量文档update之后refresh慢
一次日常运营时,用户反馈ES无法写入数据,且出现写拒绝和写入队列堆积,集群健康状态为red。依据这些现象,查看了如下指标:
杨松柏
2022/06/05
1.5K0
Elasticsearch7.0.0~7.6.2版本bug:大量文档update之后refresh慢
《Elasticsearch 源码解析与优化实战》第8章:GET流程
ES的读取分为Get和Search两种操作,这两种读取操作有较大的差异,GET/MGET必须指定三元组:index、_type、_id。 也就是说,根据文档id从正排索引中获取内容。而Search不指定_id,根据关键词从倒排索引中获取内容。本章分析GET/MGET过程,下一章分析Search过程。
HLee
2021/06/11
9860
《Elasticsearch 源码解析与优化实战》第8章:GET流程
一次系统扩容引起的elasticsearch故障及恢复
由于m21p22服务器配置比较老旧,而且上面还有其他人部署的其他应用。硬盘写入性能比较差,因此考虑吧elasticsearch部署在另外两台配置高的服务器,而将kibana、redis等与硬盘关系不大的软件部署在m21p22服务器。考虑到部署的复杂性以及服务器的实际情况,选择了redis接收beats的日志数据,再通过logstash实现负载均衡。这是之前elk集群的配置情况。 随着业务的深入,上述集群已经越来越难以满足业务的需要,日志量大会在redis中出现堆积,另外服务器查询量大之后,节点的cpu和load会触发告警。因此,与运维部门商议,又申请了2台服务器,作为elasticsearch的扩展节点,以降低原有服务器的负载。 如下是增加服务器之后的配置信息:
冬天里的懒猫
2020/08/03
1.9K0
Elasticsearch源码分析六之AllocationDeciders
上面的图为类继承关系图的一部分,下面针对具体的配置进行分析。本文及本系列源码都是针对es的7.5.1版本。Shard Allocation,Shard Move,Shard Rebalance会利用这些Decider,再决定是否进行分片分配,分片迁移,分片均衡等操作。
山行AI
2020/03/10
1.6K0
ES5.6 Bulk源码解析
Bulk注册 在启动类BootStrap的start()方法中,启动了node.start()方法。在Node初始化的过程中,加载了一系列的模块和插件,其中包含ActionModel。 ActionModule actionModule = new ActionModule(false, settings, clusterModule.getIndexNameExpressionResolver(), settingsModule.getIndexScopedSetting
YG
2018/05/23
9921
Elasticsearch索引分片损坏该怎么办?(一)
本文描述问题及解决方法同样适用于 腾讯云 Elasticsearch Service(ES)。
岳涛
2021/09/30
5.1K2
Elasticsearch索引分片损坏该怎么办?(一)
《Elasticsearch 源码解析与优化实战》第17章:Shrink原理分析
官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-shrink-index.html
HLee
2021/08/16
1.1K0
《Elasticsearch 源码解析与优化实战》第17章:Shrink原理分析
【ES三周年】深入理解 Elasticsearch 集群数据快照
之前我们生产 ES 集群因为数据分片过大,导致集群重启无法选举,具体可以看这篇文章。当系统分片数据量越来越大,给生产集群造成一定压力,同时也会影响数据检索和查询效率。为了减轻集群压力,缩小集群分片数,减少集群故障,需要考虑数据归档方案,将查询频率低的数据从集群中归档到一个集中区域。
leon 橙
2022/12/21
5.2K2
《Elasticsearch 源码解析与优化实战》第13章:Snapshot 模块分析
快照模块是ES备份、迁移数据的重要手段。它支持增量备份,支持多种类型的仓库存储。本章我们先来看看如何使用快照,以及它的一些细节特性,然后分析创建、删除及取消快照的实现原理。
HLee
2021/06/17
1.9K1
《Elasticsearch 源码解析与优化实战》第13章:Snapshot 模块分析
推荐阅读
相关推荐
《Elasticsearch 源码解析与优化实战》第10章:索引恢复流程分析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验