Elasticsearch 四
Elasticsearch优化
硬件选择:
$ vim config/elasticsearch.yml # 本地存储路径相关配置
# path.data: /path/to/data
# path.logs: /path/to/logs
- 优化 I/O方案:
(-) 使用 SSD
(-) 使用 RAID0(又称条带化). RAID会提高磁盘 I/O, 代价是当一块硬盘故障时整个就故障了. 不要使用镜像或奇偶校验 RAID, 因为副本已经提供了这个功能
(-) 另外, 使用多块硬盘, 并允许 ES通过多个 path.data目录配置, 把数据`条带化`分配到它们上面
(-) 不要使用远程挂载的存储, 如 NFS或 SMB/CIFS
分片策略
- 分片(或副本)分配多后产生的问题:
1. 分片(或副本)是可以无限分配的, 而每一个请求都会命中索引中的分片(或副本), 那些分片处在不同的节点(独立的物理机)还好, 但如果单一节点分配了太多的分片(或副本), 会出现严重的资源竞争现象, 因为每个分片(或副本)都会消耗一定文件的句柄, 内存& CPU算力
2. 副本分配多了, 会提升搜索的效率, 而会影响写索引的效率(因为默认写操作, 需要同步到所有副本后才算完成并结束操作)
- 分配时, 需遵循的原则:
(1) 控制每个分片硬盘容量不超过 ES的最大 JVM的堆空间设置(建议设置不超过 32G), 因此, 如果索引的总容量在 500G左右, 那分片大小在 16个左右即可(500/32)& 同时考虑原则(2)
(2) 考虑节点的数量& 每个节点最好是独立的物理机. 当分片数过多& 大大超出了节点的数量时, 可能会导致一个节点上存在多个分片, 此时一旦该节点异常停止工作, 即使它保持了1个以上的副本, 同样也有可能会导致数据丢失, 集群无法恢复. 所以, 建议设置分片数不超过节点数的3倍
(3) 分配主分片, 副本和节点数的, 参考关系: 节点数 <= 主分片数 x (副本数 + 1)
- 推迟分片分配:
> 当节点瞬时中断的时, 默认情况, 集群会等待一分钟来查看节点是否会重新加入, 如果这个节点在此期间重新加入, 重新加入的节点会保持其现有的分片数据, 不触发新的分片分配
通过修改参数 delayed_timeout, 可以延长再均衡的时间, 可以全局设置也可以在索引级别进行修改:
PUT /_all/_settings
{
"settings": {
"index.unassigned.node_left.delayed_timeout": "5m"
}
}
*注: 索引的分片数是创建索引的同时做的, 由于索引的路由机制, 分片数量是无法修改的, 此时只能修改副本数来提升搜索效率
路由选择:
- 锁定分片的计算公式:
shard = hash(routing) % number_of_primary_shards
routing默认是文档的 id, 也可以采用自定义值
- 不带 routing查询: 查询时, 分为2个步骤
(-) 分发: 请求到达协调节点后, 协调节点将查询请求分发到每个分片上
(-) 聚合: 协调节点搜集到每个分片上查询结果, 将结果进行排序, 最后返回给用户
- 带 routing查询:
查询时, 可以直接根据 routing信息定位分片查询, 无需查询所有的分片, 再经过协调节点排序
写入速度优化:
> 相比搜索写入要求较高的场景, 可以考虑以下几个方面
(-) 加大 Translog Flush, 目的是降低 Iops, Writeblock
(-) 增加 Index Refresh间隔, 目的是减少 Segment Merge的次数
(-) 调整 Bulk线程池和队列
(-) 优化节点间的任务分布
(-) 优化 Lucene层的索引建立, 目的是降低 CPU及 IO
- 批量数据提交:
使用 Bulk API进行批量写入. Bulk默认批量提交的数据量不能超过100M. 数据条数一般是根据文档的大小和服务器性能而定
- 优化存储设备:
ES在段合并的时候会频繁操作磁盘, 所以一旦磁盘的性能提高, ES集群的整体性能也会大幅度增加
- 合理使用合并:
Lucene以段的形式存储数据. 当有新的数据写入索引时, Lucene就会自动创建一个新的段
随着数据量的变化, 段的数量会越来越多, 消耗的多文件句柄数及 CPU就越多, 查询效率就会下降
由于 Lucene段合并的计算量庞大, 会消耗大量的 I/O, 所以 ES默认采用较保守的策略, 让后台定期进行段合并
- 减少 Refresh的次数:
Lucene在新增数据时, 采用了延迟写入的策略, 默认情况下索引的 refresh_interval为1秒. Lucene将待写入的数据先写到内存中, 超过1秒(默认)时, 就会触发一次 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堆内存的两个原则:
(-) 不要超过物理内存的50%: Lucene的设计目的是把底层 OS里的数据缓存到内存中. Lucene的段是分别存储到单个文件中的, 这些文件都是不会变化的, 所以很利于缓存, 同时操作系统也会把这些段文件缓存起来, 以便更快的访问. 如果我们设置的堆内存过大, Lucene可用的内存将会减少, 就会严重影响降低 Lucene的全文本查询性能
(-) 堆内存的大小最好不要超过32GB: 在 Java中, 所有对象都分配在堆上, 然后有一个 Klass Pointer指针指向它的类元数据. 这个指针在64位的操作系统上为64位, 64位的操作系统可以使用更多的内存(2^64). 在32位的系统上为32位, 32位的操作系统的最大寻址空间为4GB(2^32). 但是64位的指针意味着更大的浪费, 因为你的指针本身大了, 浪费内存不算, 更糟糕的是, 更大的指针在主内存和缓存器(例如 LLC, L1等)之间移动数据的时候, 会占用更多的带宽
*机器内存为64G时, 可以将31G用于 一个 ES节点; vim config/jvm.option
-Xms 31g
-Xmx 31g
*ES的堆内存默认配置是1GB
重要配置:
如果您觉得有帮助,欢迎点赞哦 ~ 谢谢!!