本套技术专栏是作者(秦凯新)平时工作的总结和升华,并深度整理大量网上资源和专业书籍。通过从真实商业环境抽取案例进行总结和分享,并给出商业应用的调优建议和集群环境容量规划等内容,请持续关注本套博客。QQ邮箱地址:1120746959@qq.com,如有任何学术交流,可随时联系。
1 ES Filesystem Cache 优化
es的搜索引擎严重依赖于底层的filesystem cache,你如果给filesystem cache更多的内存,尽量让内存可以容纳所有的indx segment file索引数据文件,那么你搜索的时候就基本都是走内存的,性能会非常高。
实际生产测试:如果走磁盘一般肯定上秒,搜索性能绝对是秒级别的,1秒,5秒,10秒。但是如果是走filesystem cache,是走纯内存的,那么一般来说性能比走磁盘要高一个数量级,基本上就是毫秒级的,从几毫秒到几百毫秒不等。
1.1 石杉笔记经典案例
-
比如说,es节点有3台机器,每台机器,看起来内存很多,64G,总内存,64 * 3 = 192g,然后给每台机器给es jvm heap是32G,那么剩下来留给filesystem cache的就是每台机器才32g,总共集群里给filesystem cache的就是32 * 3 = 96g内存
-
假设公司的磁盘上索引数据文件,在3台机器上,一共占用了1T的磁盘容量,你的es数据量是1t,每台机器的数据量是300g。
-
因为filesystem cache的内存才100g,而系统数据总共具有300G数据,那么只有十分之一的数据可以放内存,其他的都只能在磁盘,然后你执行搜索操作,大部分操作都是走磁盘,性能肯定差。
-
解决思路:一共要在es中存储1T的数据,那么多台机器留个filesystem cache的内存加起来综合,至少要到512G,至少半数的情况下,搜索是走内存的,性能一般可以到几秒钟,2秒,3秒,5秒。
2 ES 索引字段+HBase联合优化
-
比如说现在有一行数据,id name age ....30个字段,但是系统需求上,只需要根据id name age三个字段来搜索,如果往es里写入一行数据所有的字段,就会导致说70%的数据是不用来搜索的,结果硬是占据了es机器上的filesystem cache的空间,单挑数据的数据量越大,就会导致filesystem cahce能缓存的数据就越少。
-
若仅仅只是写入es中要用来检索的少数几个字段就可以了,比如说,就写入es id name age三个字段就可以了,然后你可以把其他的字段数据存在mysql里面,我们一般是建议用es + hbase的这么一个架构。
elastcisearch减少数据量仅仅放要用于搜索的几个关键字段即可,尽量写入es的数据量 跟es机器的filesystem cache是差不多的就可以了;其他不用来检索的数据放hbase里,或者mysql。
3 ES 数据预热
如果按照上述的方案去做了,es集群中每个机器写入的数据量还是超过了filesystem cache一倍,比如说你写入一台机器60g数据,结果filesystem cache就30g,还是有30g数据留在了磁盘上。此时最好做一个专门的缓存预热子系统,就是对热数据,每隔一段时间,你就提前访问一下,让数据进入filesystem cache里面去。这样期待下次别人访问的时候,一定性能会好一些。
4 ES 冷热分离
es可以做类似于mysql的水平拆分,就是说将大量的访问很少,频率很低的数据,单独写一个索引,然后将访问很频繁的热数据单独写一个索引。
- 假设有6台机器,2个索引,一个放冷数据,一个放热数据,每个索引3个shard,3台机器放热数据index;另外3台机器放冷数据index。这样的话,大量的时间是在访问热数据index,热数据可能就占总数据量的10%,此时数据量很少,几乎全都保留在filesystem cache里面了,就可以确保热数据的访问性能是很高的。
5 ES Document模型设计
5.1 石杉笔记经典案例
-
Mysql 数据模型
订单表:id order_code total_price 订单条目表:id order_id goods_id purchase_count price 在mysql里,都是select * from order join order_item on order.id=order_item.order_id where order.id=1 1 测试订单 5000 1 1 1 2 2000 1 测试订单 5000 2 1 2 5 200 -
es里的数据模型
document模型设计是非常重要的,很多操作,不要在搜索的时候才想去执行各种复杂的乱七八糟的操作。es能支持的操作就是那么多,不要考虑用es做一些它不好操作的事情。如果真的有那种操作,尽量在document模型设计的时候,写入的时候就完成。另外对于一些太复杂的操作,比如join,nested,parent-child搜索都要尽量避免,性能都很差的。
写入es的时候,搞成两个索引,order索引,orderItem索引 order索引,里面就包含id order_code total_price orderItem索引,里面写入进去的时候,先完成join操作后再写入ES,如下设计: id order_code total_price id order_id goods_id purchase_count price
6 ES 分页性能优化
-
es的分页是较坑的,假如每页是10条数据,你现在要查询第100页,如果你有个5个shard,实际上是会把每个shard上存储的前1000条数据都查到仅有的一个协调节点上,那么就有5000条数据,接着协调节点对这5000条数据进行一些合并、处理,再获取到最终第100页的10条数据。
翻页的时候,翻的越深,每个shard返回的数据就越多,而且协调节点处理的时间越长。非常坑。所以用es做分页的时候,你会发现越翻到后面,就越是慢。 -
不允许深度分页/默认深度分页性能很惨
-
使用ES scroll api, 一次性给你生成所有数据的一个快照,然后每次翻页就是通过游标移动,获取下一页下一页这样子,性能会比上面说的那种分页性能也高很多很多.
(1)这个适合于那种类似微博下拉翻页的,不能随意跳到任何一页的场景。 同时这个scroll是要保留一段时间内的数据快照的,你需要确保用户不会持续不断翻页翻几个小时。 (2)因为scroll api是只能一页一页往后翻的,是不能说,先进入第10页,然后去120页,回到58页,不能随意乱跳页。 所以现在很多产品,都是不允许你随意翻页的,app,也有一些网站,做的就是你只能往下拉,一页一页的翻
7 总结
结合大数据在我们工业大数据平台的实践,总结成一篇实践指南,方便以后查阅反思,后续我会根据本篇博客进行代码技术实践实现。
秦凯新 于郑州 201903032330