Elasticsearch杂记

分片

  • 主分片,用以解决数据水平扩展的问题。通过主分片,可以将数据分布到集群内的所有节点之上。

    • 一个分片是一个运行的Lucene的实例
    • 主分片数在索引创建时指定,后续不允许修改,除非Reindex
  • 副本,用以解决数据高可用的问题。分片是主分片的拷贝

    • 副本分片数,可以动态调整
    • 增加副本数,还可以在一定程度上提高服务的可用性(读取的吞吐)

如何设计分片数

  • 当分片数 > 节点数时

    • 一旦集群中有新的数据节点加入,分片就可以自动进行分配
    • 分片在重新分配时,系统不会有downtime
  • 多分片的好处:一个索引如果分布在不同节点,多个节点可以并行执行

    • 查询可以并行执行
    • 数据写入可以分散到多个机器

分片过所带来的副作用

  • Shard是ElasticSearch实现集群水平扩展的最小单位

  • 过多设置分片数会带来一些潜在的问题

    • 每个分片是一个Lucene的索引,会使用机器的资源。过多的分片会导致额外的性能开销

      • Lucene Indices / File descriptors / RAM / CPU
      • 每次搜索的请求,需要从每个分片上获取数据
      • 分片的Meta信息由Master节点维护。过多,会增加管理的负担。经验值,控制分片总数在10W以内

分片的设定

  • 对于生产环境中分片的设定,需要提前做好容量规划

    • 分片数设置过小

      • 导致后续无法增加节点实现水平扩展
      • 单个分片的数据量太大,导致重新分配耗时
    • 分片数设置过大,7.0开始,默认主分片设置成1,解决了over-sharding的问题

      • 影响搜索结果的相关性打分,影响统计结果的准确性
      • 单个节点上过多的分片,会导致资源浪费,同时也会影响性能

如何确定主分片数

  • 从存储的物理角度看

    • 日志类应用,单个分片不要大于50GB
    • 搜索类应用,单个分片不要超过20GB
  • 为什么要控制分片存储大小

    • 提高Update的性能
    • Merge时,减少所需的资源
    • 丢失节点后,具备更快的恢复速度 / 便于分片在集群内Rebalancing

如何确定副本分片数

  • 副本是主分片的拷贝

    • 提高系统可用性:相应查询请求,防止数据丢失
    • 需要占用和主分片一样的资源
  • 对性能的影响

    • 副本会降低数据的索引速度:有几份副本就会有几倍的CPU资源消耗在索引上

    • 会减缓对主分片的查询压力,但是会消耗同样的内存资源

      • 如果机器资源充分,提高副本数,可以提高整体的查询QPS

倒排索引不可变性

  • 倒排索引采用Immutable Design,一旦生成,不可更改

  • 不可变性,带来了的好处如下:

    • 无需考虑并发写文件的问题,避免了锁机制带来的性能问题
    • 一旦读入内核的文件系统缓存,便留在那里。只要文件系统存有足够的空间,大部分请求就会直接请求内存,不会命中磁盘,提升了很大的性能
    • 缓存容易生成和维护/数据可以被压缩
  • 不可变性,带来了的挑战:如果需要让一个新的文档可以被搜索,需要重建整个索引。

刷新的本质:写入数据由内存 buffer 写入到内存段中,以保证搜索可见

将文档插入 Elasticsearch 时,它们会被写入缓冲区中,然后在刷新时定期从该缓冲区刷新到段中。刷新频率由 refresh_interval 参数控制,默认每1秒发生一次。也就是说,新插入的文档在刷新到段(内存中)之前,是不能被搜索到的。

关于是否需要实时刷新

  • 如果新插入的数据需要近乎实时的搜索功能,则需要频繁刷新
  • 如果对最新数据的检索没有实时性要求,则应增加刷新间隔,以提高数据写入的效率,从而应释放资源辅助提高查询性能

关于刷新频率对查询性能的影响

  • 由于每刷新一次都会生成一个Lucene段,刷新频率越小就意味着同样时间间隔,生成的段越多
  • 每个段都要消耗句柄和内存
  • 每次查询请求都需要轮询每个段,轮询完毕后再对结果进行合并
  • 也就意味着:refresh_interval越小,产生的段越多,搜索反而会越慢;反过来说,加大refresh_interval,会相对提升索引性能

什么是段

  • 一个集群包含1个或多个节点
  • 一个节点包含1个或多个索引
  • 一个索引:类似MySQL中的数据库
  • 每个索引都是一个Lucene索引实例,可以将其视作一个独立的搜索引擎,它能够对Elasticsearch集群中的数据子集进行索引并处理相关查询
  • 每个分片包含多个segment(段),每一个segment都是一个倒排索引

在查询的时候,会把所有的segment查询结果汇总归并为最终的分片查询结果返回

为什么段是不可变的?

  • 在lucene中,为了实现高索引速度,故使用了segment分段架构存储
  • 一批写入数据保存在一个段中,其中每个段是磁盘中的单个文件
  • 由于两次写入之间的文件操作非常繁重,因此将一个段设为不可变的,以便所有后续写入都转到New段

什么是段合并?

由于自动刷新流程每秒会创建一个新的段(由动态配置参数:refresh_interval决定),这样会导致短时间内的段数量暴增。
而段数据太多会带来较大的麻烦

  • 消耗资源:每一个段都会消耗文件句柄、内存和CPU运行周期
  • 搜索变慢:每个搜索请求都必须轮流检查每个段;所以段越多,搜索也就越慢

Elasticsearch通过在后台进行段合并来解决这个问题:小的段被合并到大的段,然后这些大的段再被合并到更大的段。

段合并做了什么?

段合并的时候会将那些旧的已删除文档从文件系统中消除,
被删除的文档(或被更新文档的旧版本)不会被拷贝到新的大段中,
启动段合并不需要你做任何事,进行索引和搜索时会自动进行。

为什么要进行段合并?

  • 索引段的个数越多,搜索性能越低并且消耗更多的内存
  • 索引段是不可变的,你不能物理上从中删除信息

可以物理上删除document,但只是做了删除标记,物理上并没有删除

  • 当段合并的时候,这些被标记位删除的文档并没有被拷贝至新的索引段中,这样减少了最终的索引段中的document数目。

段合并的好处是什么?

  • 减少索引段的数量并提高检索速度
  • 减少索引的容量(文档数)

原因:段合并会移除被标记为已删除的那些文档

段合并可能带来的问题

  • 磁盘IO操作的代价
  • 速度慢的系统中,段合并会显著影响性能

重建索引

使用场景

  • 一般在以下几种情况时,我们需要重建索引

    • 索引的Mappings发生变更:字段类型更改,分词器及字典更新
    • 索引的Settings发生变更:索引的主分片数发生改变
    • 集群内,集群间需要做数据迁移
  • Elasticsearch的内置提供的API

    • Update By Query:在现有索引重建
    • Reindex:在其他索引上重建索引

性能优化

https://elastic.blog.csdn.net/article/details/97695931

分片大小

  • 如果分片给索引的分片太多,则Lucene分段会很小,从而导致开销增加。当同时进行多个查询,许多小分片也会降低查询吞吐量
  • 分片太大会导致搜索性能下降和故障恢复时间更长

数据动态持续写入场景

Index Sorting

注意:索引排序机制是6.X版本才有的特性
在Elasticsearch中创建索引时,可以配置每个分片中的分段的排序方式。默认情况下,Lucene不会应用任何排序。index.sort.*定义应使用哪些字段对每个Segment内的文档进行排序

面试题

一旦创建索引后,为什么无法更改索引的主分片数量?

如果我们要更改分片的数量,那么对于文档,运行路由公式的结果将发生变化。

假设:设置有 5 个分片时文档已存储在分片 A 上,因为那是当时路由公式的结果。

后面我们将主分片更改为7个,如果再尝试通过ID查找文档,则路由公式的结果可能会有所不同。

现在,即使文档实际上存储在Shard A上,该公式也可能会路由到ShardB。这意味着永远不会找到该文档。

以此可以得出:主分片创建后不能更改的结论。

原文地址:https://www.cnblogs.com/deepSleeping/p/14473401.html