ElasticSearch性能优化

硬件选择

Elasticsearch 的基础是 Lucene,所有的索引和文档数据是存储在本地的磁盘中,具体的 路径可在 ES 的配置文件../config/elasticsearch.yml 中配置。磁盘在现代服务器上通常都是瓶颈。Elasticsearch 重度使用磁盘,你的磁盘能处理的吞吐量 越大,你的节点就越稳定。

1、使用 SSD。就像其他地方提过的, 他们比机械磁盘优秀多了。

2、使用 RAID 0。条带化 RAID 会提高磁盘 I/O,代价显然就是当一块硬盘故障时整个就故障了。不要 使用镜像或者奇偶校验 RAID 因为副本已经提供了这个功能。

3、另外,使用多块硬盘,并允许 Elasticsearch 通过多个 path.data 目录配置把数据条带化分配到它们上 面。

4、不要使用远程挂载的存储,比如 NFS 或者 SMB/CIFS。这个引入的延迟对性能来说完全是背道而驰 的。

分片策略

一、合理设置分片数

1、控制每个分片占用的硬盘容量不超过 ES 的最大 JVM 的堆空间设置(一般设置不超过 32G),因此,如果索引的总容量在 500G 左右,那分片大小在 16 个左右即可;当然, 最好同时考虑原则 2。

2、考虑一下 node 数量,一般一个节点有时候就是一台物理机,如果分片数过多,大大超过了节点数, 很可能会导致一个节点上存在多个分片,一旦该节点故障,即使保持了 1 个以上的副本,同样有可能 会导致数据丢失,集群无法恢复。所以, 一般都设置分片数不超过节点数的 3 倍。

3、主分片,副本和节点最大数之间数量,我们分配的时候可以参考以下关系:节点数<=主分片数*(副本数+1)

二、推迟分片分配

        对于节点瞬时中断的问题,默认情况,集群会等待一分钟来查看节点是否会重新加入, 如果这个节点在此期间重新加入,重新加入的节点会保持其现有的分片数据,不会触发新的 分片分配。这样就可以减少 ES 在自动再平衡可用分片时所带来的极大开销。

        通过修改参数 delayed_timeout ,可以延长再均衡的时间,可以全局设置也可以在索引 级别进行修改:

PUT /_all/_settings 
{
 "settings": {
 "index.unassigned.node_left.delayed_timeout": "5m" 
 }
}

路由选择

        通过下面这个公式来计算文档应该存放到哪个分片中:

shard = hash(routing) % number_of_primary_shards

        查询的时候,可以直接根据 routing 信息定位到某个分配查询,不需要查询所有的分配,经 过协调节点排序。

        向上面自定义的用户查询,如果 routing 设置为 userid 的话,就可以直接查询出数据来, 效率提升很多。

写入速度优化

一、批量数据提交

        ES 提供了 Bulk API 支持批量操作,当我们有大量的写任务时,可以使用 Bulk 来进 行批量写入。

        通用的策略如下:Bulk 默认设置批量提交的数据量不能超过 100M。数据条数一般是 根据文档的大小和服务器性能而定的,但是单次批处理的数据大小应从 5MB~15MB 逐渐 增加,当性能没有提升时,把这个数据量作为最大值。

二、优化存储设备

        ES 是一种密集使用磁盘的应用,在段合并的时候会频繁操作磁盘,所以对磁盘要求较 高,当磁盘速度提升之后,集群的整体性能会大幅度提高。

三、合理使用合并

        Lucene 以段的形式存储数据。当有新的数据写入索引时,Lucene 就会自动创建一个新 的段。

        随着数据量的变化,段的数量会越来越多,消耗的多文件句柄数及 CPU 就越多,查询 效率就会下降。

        由于 Lucene 段合并的计算量庞大,会消耗大量的 I/O,所以 ES 默认采用较保守的策 略,让后台定期进行段合并。

四、减少 Refresh 的次数

        Lucene 在新增数据时,采用了延迟写入的策略,默认情况下索引的 refresh_interval 为 1 秒。

        Lucene 将待写入的数据先写到内存中,超过 1 秒(默认)时就会触发一次 Refresh, 然后 Refresh 会把内存中的的数据刷新到操作系统的文件缓存系统中。

        如果我们对搜索的实效性要求不高,可以将 Refresh 周期延长,例如 30 秒。

        这样还可以有效地减少段刷新次数,但这同时意味着需要消耗更多的 Heap 内存。

五、加大 Flush 设置

        Flush 的主要目的是把文件缓存系统中的段持久化到硬盘,当 Translog 的数据量达到 512MB 或者 30 分钟时,会触发一次 Flush。

        index.translog.flush_threshold_size 参数的默认值是 512MB,我们进行修改。

        增加参数值意味着文件缓存系统中可能需要存储更多的数据,所以我们需要为操作系统 的文件缓存系统留下足够的空间。

六、减少副本的数量

        ES 为了保证集群的可用性,提供了 Replicas(副本)支持,然而每个副本也会执行分 析、索引及可能的合并过程,所以 Replicas 的数量会严重影响写索引的效率。

        当写索引时,需要把写入的数据都同步到副本节点,副本节点越多,写索引的效率就越 慢。

        如 果 我 们 需 要 大 批 量 进 行 写 入 操 作 , 可 以 先 禁 止 Replica 复 制 , 设 置 index.number_of_replicas: 0 关闭副本。在写入完成后,Replica 修改回正常的状态。

内存设置

        ES 默认安装后设置的内存是 1GB,对于任何一个现实业务来说,这个设置都太小了。可在jvm.option 文件设置ES 的堆大小,Xms 表示堆的初始大小,Xmx 表示可分配的最大内存。

        确保 Xmx 和 Xms 的大小是相同的,其目的是为了能够在 Java 垃圾回收机制清理完 堆区后不需要重新分隔计算堆区的大小而浪费资源,可以减轻伸缩堆大小带来的压力。

        因为 ES 堆内存的分配需要满足以下两个原则:

* 不要超过物理内存的 50%:Lucene 的设计目的是把底层 OS 里的数据缓存到内存中。

* 堆内存的大小最好不要超过 32GB:在 Java 中,所有对象都分配在堆上,然后有一个 Klass Pointer 指 针指向它的类元数据。

        假设你有个机器有 128 GB 的内存,你可以创建两个节点,每个节点内存分配不超过 32 GB。 也就是说 不超过 64 GB 内存给 ES 的堆内存,剩下的超过 64 GB 的内存给 Lucene

重要配置

参数名 参数值 说明
cluster.name elasticsearch 配置 ES 的集群名称,默认值是 ES,建议改成与所存数据相关的名称,ES 会自动发现在同一网段下的 集群名称相同的节点
node.name node-1 集群中的节点名,在同一个集群中不能重复。节点 的名称一旦设置,就不能再改变了。当然,也可以 设 置 成 服 务 器 的 主 机 名 称 , 例 如 node.name:${HOSTNAME}。
node.master true 指定该节点是否有资格被选举成为 Master 节点,默 认是 True,如果被设置为 True,则只是有资格成为 Master 节点,具体能否成为 Master 节点,需要通 过选举产生。
node.data true 指定该节点是否存储索引数据,默认为 True。数据 的增、删、改、查都是在 Data 节点完成的。
index.number_of_shards 1 设置都索引分片个数,默认是 1 片。也可以在创建 索引时设置该值,具体设置为多大都值要根据数据 量的大小来定。如果数据量不大,则设置成 1 时效 率最高
index.number_of_replicas 1 设置默认的索引副本个数,默认为 1 个。副本数越 多,集群的可用性越好,但是写索引时需要同步的 数据越多。
transport.tcp.compress true 设置在节点间传输数据时是否压缩,默认为 False, 不压缩
discovery.zen.minimum_master_nodes 1 设置在选举 Master 节点时需要参与的最少的候选 主节点数,默认为 1。如果使用默认值,则当网络 不稳定时有可能会出现脑裂。 合理的数值为 (master_eligible_nodes/2)+1 ,其中 master_eligible_nodes 表示集群中的候选主节点数
discovery.zen.ping.timeout 3s 设置在集群中自动发现其他节点时 Ping 连接的超 时时间,默认为 3 秒。 在较差的网络环境下需要设置得大一点,防止因误 判该节点的存活状态而导致分片的转移

你可能感兴趣的:(数据库与缓存,开源框架项目,检索搜索,Elasticsearch,性能优化)