上篇我们说到通过引入索引模板可以有效的应对各种新增需求,降低存储成本,提升检索效率,但是呀随着时间的推移,集群承载的数据量越来越大,导致检索越来越慢,今天我们就一起看下这种情况下如何处理。
我们通过es官方文档可以知道从7.x以后number_of_shards(primary shard)为1个,replica shard也是1个,如果你有200G的数据等于全在一个分片上。这搜索起来肯定慢啊。
es官方建议每个shard数据不要超过50G,所以我们的数据都在一个shard上肯定不行啊。于是我们需要定制索引的settings.得到了第一版:
"settings" : {
"index" : {
"number_of_shards" : "3",
"number_of_replicas" : "2"
}
}
这个可以根据自己索引的数据量预估下,不一定shard越多就越好。replica也是根据数据的安全性以及查询性能、存储成本、写入性能等各种维度平衡评估一下。
虽然replica shard会提高检索效率,但是也大大降低了写入的性能。他的关系就好比mysql的主从一样,我向来提倡不要试图通过增加mysql的从节点来提高检索效率(会带来各种问题,首先同步延时就是大问题,即便是半同步模式遇到高并发更新的时候也会有一定的同步延时),通过引入缓存,合理使用索引,分库分表等来解决这个问题,从节点只用来保证高可用。
es也是一样的道理,所以我们这里设置2分replica shard保证没一份数据有2分冗余,down2个也可以保证数据不丢失,也符合分布式环境中最少三节点。
设置完settings后确实检索性能有提高,但是过不了多久发现又慢了,这是为啥呢?原来啊es默认支持近实时查询,这样每一秒就会刷盘,就会产生一个segment file,每个segment就对应一个lucene,这玩意就好比我们有10个鸡蛋放在10个篮子里,需要查询的时候我们要遍历10个篮子才知道最后结果。如果10个鸡蛋都在一个篮子里那么只需要查询一个篮子即可。
所以我们的第二版settings优化来了:
"settings" : {
"index" : {
"refresh_interval" : "10s",
???????????????"number_of_shards"?:?"3",???????????
???????????????"number_of_replicas"?:?"2"
}
}
告诉es这个索引每个10秒再执行一次refresh操作(根据业务容忍度合理设置时间,设置10秒后写入的数据10以后才可以查询到),这样我们的segment就大大减少了,但是之前已经生成的怎么办呢?而且即便是10秒仍然会有很多segment,所以我们还需要定时进行merger操作,这个应该好理解,就好比我们提交代码的时候需要执行merger一样。
写个crontabl表达式,通过linux定时强制执行,一定要在在业务低峰期进行改操作哦,因为会造成磁盘大量的数据移动。
POST /index-name/_optimize?max_count_segments=1
并且我们可以动态设置merger的并行度,index.merge.scheduler.max_thread_count合理的发挥磁盘最大性能。
PUT /index_name/_settings
{ "index.merge.scheduler.max_thread_count": 10}
除了这些还有一些优化点,比如translog的优化,es中的translog就好比mysql的中的binlog、redolog的意思。异常down重启后通过translog来恢复数据,那么它呢其实也是先写的内存,在定时flush到磁盘,我们也可以对此进行优化,比如达到一定大小才执行flush操作。最中我们的settings设置如下:
"settings" : {
"index" : {
"refresh_interval" : "10s",
"number_of_shards" : "3",
"translog" : {
"flush_threshold_size" : "500m",
"sync_interval" : "5s",
"durability" : "async"
},
"number_of_replicas" : "2"
}
}
经过上述一些优化后我们的性能大有提升啊。Ok今天就先到这里,欢迎关注个人微信公众号: