Elasticsearch重建索引:如何在构建新索引时将其更新?

时间:2013-04-09 19:16:08

标签: elasticsearch tire

我理解使用别名重新编制索引以避免停机,如下所述:Is there a smarter way to reindex elasticsearch?

但仍然存在一个问题:假设重建索引需要一个小时,而原始数据库会不断变化。我需要任何更新才能转到两个索引。

有没有办法做到这一点?

如果没有,我更希望更新是否转到新索引,而查询仍然是从旧索引提供的。但至少在提尔,我还没有看到过使用不同指数进行阅读和写作的方法。可以这样做吗?

2 个答案:

答案 0 :(得分:1)

您无法从Elasticsearch同时更新两个索引。 你可以处理这个问题,并向Elasticsearch提出2个索引请求。

那就是说,你可以使用alias这里虽然我很确定你可以使用Tire搜索多个索引(但我不知道Tire)

你有一个旧的index1

将所有内容推送到index2 在index1,index2

之上添加别名索引

索引完成后,删除index1

答案 1 :(得分:-1)

为了允许零停机时间索引更改,即使使用新的用户生成内容更新搜索系统,您也可以使用以下策略:

为将指向ES索引的读取和写入操作定义别名。更新模型时,查找model_write别名并使用它来写入所有跟踪的索引,这些索引将包括当前活动的索引以及在后台构建的任何索引。

class User < ActiveRecord::Base
  def self.index_for_search(user_id)
    Timeout::timeout(5) do
      user = User.find_by_id(user_id)
      write_alias = Tire::Alias.find("users_write")
      if write_alias
        write_alias.indices.each do |index_name|
          index = Tire::Index.new(index_name)
          if user
            index.store user
          else
            index.remove 'user', user_id
          end
        end
      else
        raise "Cannot index without existence of 'users_write' alias."
      end
    end
  end
end

现在,当您想要进行完整索引重建(或初始索引创建)时,添加新索引,将其添加到别名,并开始构建它,因为知道任何活动用户将同时将其数据添加到两个索引。继续读取旧索引,直到构建新索引,然后切换读取别名。

class SearchHelper
  def self.set_alias_to_index(alias_name, index_name, clear_aliases = true)
    tire_alias = Tire::Alias.find(alias_name)
    if tire_alias
      tire_alias.indices.clear if clear_aliases
      tire_alias.indices.add index_name
    else
      tire_alias = Tire::Alias.new(:name => alias_name)
      tire_alias.index index_name
    end

    tire_alias.save
  end
end

def self.reindex_users_index(options = {})
  finished = false
  read_alias_name = "users"
  write_alias_name = "users_write"
  new_index_name = "#{read_alias_name}_#{Time.now.to_i}"

  # Make new index for re-indexing.
  index = Tire::Index.new(new_index_name)
  index.create :settings => analyzer_configuration,
               :mappings => { :user => user_mapping }
  index.refresh

  # Add the new index to the write alias so that any system changes while we're re-indexing will be reflected.
  SearchHelper.set_alias_to_index(write_alias_name, new_index_name, false)

  # Reindex all users.
  User.find_in_batches do |batch|
    index.import batch.map { |m| m.to_elasticsearch_json }
  end
  index.refresh
  finished = true

  # Update the read and write aliases to only point at the newly re-indexed data.
  SearchHelper.set_alias_to_index read_alias_name, new_index_name
  SearchHelper.set_alias_to_index write_alias_name, new_index_name
ensure
  index.delete if defined?(index) && !finished
end

可以在此处找到描述此策略的帖子:http://www.mavengineering.com/blog/2014/02/12/seamless-elasticsearch-reindexing/