【问题标题】:Blocking an index for readonly operations, makes elasticsearch left in an inconsistent state为只读操作阻塞索引,使 elasticsearch 处于不一致状态
【发布时间】:2015-05-14 04:52:11
【问题描述】:

如果我必须对该索引进行重新索引处理,我想阻止该索引的写入操作。
这两个帖子(elasticsearch migrations with c and nestNEST Elasticsearch Reindex examples)都非常有帮助,但正如this third one 所建议的,您可能会在此过程中丢失更新和删除。
我曾尝试使用 elasticsearch 中的设置阻止索引写入操作,但我在尝试此操作时发现了一些问题。
我使用 Nest 的UpdateSettings api 更改设置blocks.read_onlyblocks.metadatablocks.readblocks.write

var client = CreateElasticClient(); // A wrapper method of ElasticClient()
var response = client.UpdateSettings(r => r
                    .Index(IndexName)
                    .BlockReadonly()
                    .BlocksMetadata()
                    .BlocksRead()
                    .BlocksWrite()
                    );

如果我将设置blocks.read_onlyblocks.metadatablocks.read 设置为 true(默认设置的值),那么索引将不接受写入操作,而且读取操作也不允许,准确地说,我今天不得不重新安装elasticsearch 3次,因为更改这些设置后我无法用它做任何其他事情。
blocks.write设置为true不会有任何效果,我可以读取索引,也可以编写它。
QUESTION
所以,我的问题是,我应该怎么做(在重新索引时阻止索引写入操作)?

【问题讨论】:

  • 只需将此 UpdateSettingsDescriptor 与 .BlocksWrite() 一起保留。为我工作。当您仅使用 .BlockWrite() 时,可能会收到错误响应。想分享吗?
  • 嗨@Rob 我在UpdateSettingDescriptor 中使用了两种组合,最后一种只使用了BlocksWrite(),但即便如此我也能够在索引中写入。
  • 您确定 UpdateSettings 请求没有返回错误吗?我能够通过在 UpdateSettings 请求上调用 .BlockWrite() 来阻止对索引的写入,它就像一个魅力。能否分享更多细节:ES、NEST 版本、如何创建 ElasticClient 等?
  • @Rob 我使用的是 ES 1.5.1,也是 Nest 的最后一个版本。 UpdateSetting 响应成功。即使我检查索引设置,block.write 也设置为 true。所以我就不贴更多细节了,因为一切都是手工制作的,修改设置是成功的。

标签: elasticsearch nest


【解决方案1】:

我准备了简单的例子。也许它会让你的问题有所了解。

internal class Program
{
    private static void Main(string[] args)
    {
        var indexName = "indexname";
        var indexName2 = "indexname2";

        var uri = new Uri("http://localhost:9200");
        var settings = new ConnectionSettings(uri).SetDefaultIndex(indexName).EnableTrace();
        var client = new ElasticClient(settings);

        var indicesResponse = client.DeleteIndex(descriptor => descriptor.Index(indexName));
        var indicesResponse2 = client.DeleteIndex(descriptor => descriptor.Index(indexName2));

        client.CreateIndex(descriptor => descriptor.Index(indexName).AddMapping<Document>(m => m.MapFromAttributes()));

        client.Index(new Document {Id = 1});

        client.Refresh();

        var acknowledgedResponse = client.UpdateSettings(descriptor => descriptor.Index(indexName).BlocksWrite());

        var observable = client.Reindex<Document>(descriptor => descriptor.FromIndex(indexName).ToIndex(indexName2));
        observable.Subscribe(new ReindexObserver<Document>(response => Console.WriteLine(response.IsValid),
            Console.WriteLine, () => Console.WriteLine("Done")));

        var documentToAdd = new Document { Id = 2, Name = "new" };

        var indexResponse = client.Index(documentToAdd);

        //indexResponse -> can't index new document with message: blocked by: [FORBIDDEN/8/index write (api)];

        var getResponse = client.Get<Document>(descriptor => descriptor.Id(1));

        //getResponse -> still can read from index

        var acknowledgedResponse2 = client.UpdateSettings(descriptor => descriptor.Index(indexName).BlocksWrite(false));

        var indexResponse2 = client.Index(documentToAdd);

        //indexResponse2 -> now I can add new document to my index

        Console.ReadKey();
    }
}

public class Document
{
    public int Id { get; set; }
    public string Name { get; set; }
}

【讨论】:

  • 这个解决方案完全有效,与我的代码的唯一区别是我尝试从不同的线程插入文档,并且它没有失败。我检查了索引设置,并且 block.write 设置为 true,就像我运行您的解决方案时一样。我将此标记为已接受的答案,因为它有效,但我需要对此进行更多研究。
【解决方案2】:

随着数据的增长,重新索引可能会成为一个耗时的过程。即使有办法阻止写入,您打算如何重新应用丢失的写入? (如果它们是重新索引未捕获的新文档)

Elasticsearch 支持可用于此目的的别名。见Aliases。当您重建索引时,您仍然可以捕获所有写入并仍然支持使用这些的读取操作。这是一个有用的链接,其中详细介绍了一些方法。 Reindex options

【讨论】:

  • 嗨@jrao77,感谢您的回答。关于它,我在问题中提到的第三篇文章与您建议的重新索引选项的链接相匹配。它非常有用,但没有显示任何明确的解决方案。
猜你喜欢
  • 2019-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 2016-12-22
  • 1970-01-01
相关资源
最近更新 更多