分片策略
分片和副本得设计为ES提供支付分布式和故障转移得特性,但不意味着分片和副本是可以无限分配,
而且索引得分片完成分配后由于索引得路由机制,不能重新修改分片数(副本数可以动态修改)
- 一个分片得底层为一个lucene索引,会消耗一定文件句柄、内存以及CPU运转,当分片数越多资源消耗就会更多
- 每个搜索请求都需要命中索引中得每个分片,如果分片处于不同节点还好,但如果处于相同节点上竞争使用相同资源就导致性能降低
- 控制每个分片占用磁盘容量不超过ES得最大JVM堆空间设置(一般不超过32G),因此如果索引得总容量在500G左右,那么分片大小在16个左右即可
- 考虑node数量,一般一个节点有时就是一台物理机,如果分片数量过多,大大超过节点数,可能会导致一个节点上存在多个分片,一旦该节点故障,即使保持1个以上得副本,同样有可能会导致数据丢失,一般设置分片数不超过节点数得3倍
- 主分片,副本和节点最大数之间数量 节点数<=主分片数*(副本数+1)
推迟分片分配
对于节点瞬时中断得问题,默认情况,集群会等待一分钟来查看节点是否重新加入,如果节点再次期间重新加入,重新加入得节点会保持其现有分片得数据,不会触发新的分片分配,这样就可以减少ES在自动在平衡可用分片所带来的极大开销
通过修改参数delayed_timeout,延长在均衡时间,可全局设置也可以在索引级别修改
PUT /_all/_settings
{
"settings" : {
"index.unassigned.node_left.delayed_timeout" : "5m"
}
}
路由选择
当我们查询文档时,ES是如何知道一个文档应该存放在那个分片中,路由计算
#shard=hash(routing) % number_of_primary_shards
routing默认值是文档 id,也可以采用自定义值,比如用户id
- 不带routing查询
请求到达协调节点上,协调节点查询分发到所有分片上,协调节点搜集每个分片得查询结果,再将查询结果排序聚合,返回结果 - 带routing查询
查询可直接根据routing信息定位到某个分片查询,不需要查询所有分片,经过协调节点排序,比如自定义用户查询,如果routing设置为userid,就可以直接查询出数据,效率提升
写入速度
ES默认配置,综合数据可靠性、写入速度、搜索实时等因素,实际使用我们需要根据项目要求,进行偏向性优化。
针对搜索性能不高,但是写入有要求场景,需要尽可能得选择恰当写优化策略
- 加大Translog Flush,降低磁盘 Iops、Writeblock
- 增加Index Refresh 刷新间隔,减少Segment Merge次数(间隔短意味频繁将内存数据放入文件系统缓存中,文件系统缓存相应写入磁盘中,当磁盘文件数据多就会合并随之影响性能)
- 调整Bulk线程池和队列(批量处理)
- 优化节点间得任务分布
- 优化Lucene层索引建立,降低CPU和IO
优化存储
ES是一种密集使用磁盘得应用,在段合并时候会频繁操作磁盘,所以对磁盘要求较高,当磁盘速度提升,集群整体性能大幅提高(固态硬盘)
减少Refresh次数
#Lucene是一个开源的全文索引与信息检索(IR)库,采用Java实现
Lucene在新增数据时,采用延迟写入策略,默认情况下索引得refresh_interval为1秒
Lucene将代写入得数据先写到内存中,超过默认1秒会触发一次refresh,然后refresh会把内存得数据刷新到操作系统得文件缓存系统中。
- 如果对搜索得实效性不高,可以将refresh周期延长调整30秒等
- 有效减少刷次次数,意味着需要消耗更多得Heap内存
加大Flush设置
#Translog是Elasticsearch的事务日志文件,它记录了所有对索引分片的事务操作(add/update/delete),每个分片对应一个Translog文件。
#Translog是用来恢复数据的。在Elasticsearch中,写入的索引并没有实时落盘到索引文件,而是先双写到内存和Translog文件。如果掉电,Elasticsearch重启后还可以把数据从日志文件中读回来。在flush的时候,Translog文件会被清空
Flush主要目的是把文件缓存系统中得段持久化到磁盘,当Translog得数据量达到512MB或者30分钟,会触发一次Flush
减少副本数量
ES为了保证集群得可用性,提供了Replicas支持,然后每个副本也会执行分析,索引及可能合并得过程,所以Replicas得数量严重影响写索引得效率。
当写索引时,需要把写入数据都同步到副本节点,副本节点越多,写索引得效率就越慢,如果有大批量进行写入操作,可以先禁止Replca副本复制,设置index.number_of_replicas:0关闭副本,再写入完成后,Replca修改回正常状态,提升效率
内存设置
ES在默认安装后设置得内存是1GB,对于任何一个业务来说,这个设置都太小了。config目录文件包含一个jvm.option文件,添加如下命令设置ES堆大小,Xms表示堆初始大小,Xmx表示可分配得最大内存。
一般来说这两数值配置保持相同,目的为了能够在java垃圾回收机制清理完堆分区后不需要重新分割计算堆区得大小而浪费资源,可以减轻伸缩堆大小带来得压力。
- 不要超过物理内存得50%,Lucene设计目的是把底层得OS里得数据缓存到内存中。
Lucene得段分别储存到单个文件中的,这些文件都是不会变化得,所以很利于缓存,同时操作系统也会吧这些文件缓存起来,以便更快得访问
如果我们设置堆内存过大,Lucene可用得内存将减少,会影响降低Lucene得全文本查询性能 - 堆内存大小最好不超过32GB,在java中,所有的对象都分配在堆上,然后有一个Klass pointer指针向它得类元数据
假设有个机器有128GB内存,你可以创建2个节点,每节点内存分配不超过32GB,也就是不超过64GB内存给ES堆内存,剩下超过64GB得内存给Lucene
重要配置
参数 | 参数值 | 说明 |
cluster.name | ES | 配置ES集群名称,默认值是ES,ES会自动发现在同一网段下集群名称相同得节点 |
node.name | node1 | 集群中节点名,在同一集群中不能重复,节点名称一单设置不能在改变 |
node.master | true | 指定该节点是否有资格被选举为Master节点,默认为True,具体能否成为Master节点,需要通过选举产生 |
node.data | true | 执行该节点是否存储索引数据,默认为True,数据的增、删、改、查都是在Data节点完成 |
index.number_of_shards | 1 | 设置索引分片个数,默认是1。可以在创建索引时设置该值,具体设置多少根据数据量大小来定,如果数据量不大,保持默认1时效率最高 |
index.number_of_replicas | 1 | 设置默认索引副本个数,默认为1,副本越多,集群可用性越好,但是写索引时需要同步得数据随之越多 |
transport.tcp.compress | false | 设置在节点间传输时是否压缩,默认为False,不压缩 |
discovery.zen.minimum_master_nodes | 1 | 设置在选举Master节点时需要参与最少候选主节点数,默认1,如果使用默认值,则当网络不稳定时有可能出现脑裂。合理数值为(master_eligible_nodes/2)+1,其中master_eligible_nodes表示集群中候选主节点数 |
descovery.zen.ping.timeout | 3s | 设置在集群中自动发现其他节点时ping连接超时时间,默认为3秒,在较差得网络环境需要设置大一点,防止因误判该节点存活状态而导致分片转移 |