使用elasticsearch遇到的一些问题以及解决方法

1.由gc引起节点脱离集群

因为gc时会使jvm停止工作,如果某个节点gc时间过长,masterping3次(zendiscovery默认ping失败重试3次)不通后就会把该节点剔除出集群,从而导致索引进行重新分配。

解决方法:

(1)优化gc,减少gc时间。(2)调大zendiscovery的重试次数(es参数:ping_retries)和超时时间(es参数:ping_timeout)。后来发现根本原因是有个节点的系统所在硬盘满了。导致系统性能下降。

2.outofmemory错误

因为默认情况下es对字段数据缓存(FieldDataCache)大小是无限制的,查询时会把字段值放到内存,特别是facet查询,对内存要求非常高,它会把结果都放在内存,然后进行排序等操作,一直使用内存,直到内存用完,当内存不够用时就有可能出现outofmemory错误。

解决方法:

(1)设置es的缓存类型为SoftReference,它的主要特点是据有较强的引用功能。只有当内存不够的时候,才进行回收这类内存,因此在内存足够的时候,它们通常不被回收。另外,这些引用对象还能保证在Java抛出OutOfMemory异常之前,被设置为null。它可以用于实现一些常用图片的缓存,实现Cache的功能,保证最大限度的使用内存而不引起OutOfMemory。在es的配置文件加上index.cache.field.type:soft即可。

(2)设置es最大缓存数据条数和缓存失效时间,通过设置index.cache.field.max_size:50000来把缓存field的最大值设置为50000,设置index.cache.field.expire:10m把过期时间设置成10分钟。

3.无法创建本地线程问题

es恢复时报错:RecoverFilesRecoveryException[[index][3]Failedtotransfer[215]fileswithtotalsizeof[9.4gb]];nested:OutOfMemoryError[unabletocreatenewnativethread];]]

刚开始以为是文件句柄数限制,但想到之前报的是toomanyopenfile这个错误,并且也把数据改大了。查资料得知一个进程的jvm进程的最大线程数为:虚拟内存/(堆栈大小*1024*1024),也就是说虚拟内存越大或堆栈越小,能创建的线程越多。重新设置后还是会报那这错,按理说可创建线程数完全够用了的,就想是不是系统的一些限制。后来在网上找到说是maxuserprocesses的问题,这个值默认是1024,这个参数单看名字是用户最大打开的进程数,但看官方说明,就是用户最多可创建线程数,因为一个进程最少有一个线程,所以间接影响到最大进程数。调大这个参数后就没有报这个错了。

解决方法:

(1)增大jvm的heap内存或降低xss堆栈大小(默认的是512K)。

(2)打开/etc/security/limits.conf,把softnproc1024这行的1024改大就行了。

4.集群状态为黄色时并发插入数据报错

[7]:index[index],type[index],id[1569133],message[UnavailableShardsException[[index][1][4]shardIt,[2]active:Timeoutwaitingfor[1m],request:org.elasticsearch.action.bulk.BulkShardRequest@5989fa07]]

这是错误信息,当时集群状态为黄色,即副本没有分配。当时副本设置为2,只有一个节点,当你设置的副本大于可分配的机器时,此时如果你插入数据就有可能报上面的错,因为es的写一致性默认是使用quorum,即quorum值必须大于(副本数/2+1),我这里2/2+1=2也就是说要要至少插入到两份索引中,由于只有一个节点,quorum等于1,所以只插入到主索引,副本找不到从而报上面那个错。

解决方法:(1)去掉没分配的副本。(2)把写一致性改成one,即只写入一份索引就行。

5.设置jvm锁住内存时启动警告

当设置bootstrap.mlockall:true时,启动es报警告Unknownmlockallerror0,因为linux系统默认能让进程锁住的内存为45k。

解决方法:设置为无限制,linux命令:ulimit-lunlimited

6.错误使用api导致集群卡死

其实这个是很低级的错误。功能就是更新一些数据,可能会对一些数据进行删除,但删除时同事使用了deleteByQuery这个接口,通过构造BoolQuery把要删除数据的id传进去,查出这些数据删除。但问题是BoolQuery最多只支持1024个条件,100个条件都已经很多了,所以这样的查询一下子就把es集群卡死了。

解决方法:用bulkRequest进行批量删除操作。