Elasticsearch 在 db_ranking 的排名又(双叒叕)上升了一位,如图 1-1 所示;由此可见 es 在存储领域已经蔚然成风且占有非常重要的地位。
随着 Elasticsearch 越来越受欢迎,企业花费在 ES 建设上的成本自然也不少。那如何减少 ES 的成本呢?今天我们就特地来聊聊 ES 降本增效的常见方法:
图 1-1 Elasticsearch db_ranking
所谓弹性伸缩翻译成大白话就是随时快速瘦身与增肥,并且是头痛医头,按需动态调整资源。当计算能力不足的时候我们可以快速扩充出计算资源,业届比较有代表性的两个 ES 相关产品阿里云 Indexing Service 和 滴滴的 ES-Fastloader;
当存储资源不足时,能够快速扩容磁盘,业届比较代表性 es 产品:阿里云的 ES 日志增强版。
ES 使用计算存储分离架构之后,解决了资源预留而造成资源浪费的问题。在早期大家认为的计算存储分离的实现方式为:使用云盘代替本地盘,这种实现方式可以提高数据的可靠性、可以快速弹扩磁盘资源和计算资源,但是 es 自身弹性需求是无法解决,即秒级 shard 搬迁和 replica 扩容。
那么如何解决 es 自身的弹性呢?本文该部分将给出答案。
本文该部分将介绍我们京东云 - 中间件搜索团队,研发的共享存储版本 ES;计算存储分离架构如图 1-2 所示
图 1-2 计算存储分离架构 (共享)
如图 1-2 所示,我们只存储一份数据,primary shard 负责读写,replica 只负责读;当我们需要扩容 replica 的时候无需进行数据搬迁,直接跳过原生 es 的 peer recover 两阶段,秒级完成 replica 的弹扩。
当主分片发生 relocating 时,可以直接跳过原生 es 的 peer recover 第一阶段 (该阶段最为耗时),同时也不需要原生 es 的第二阶段发送 translog。
共享版本的计算存储分离 ES,相对于原生的 ES 和普通版本的计算存储分离,具有如下突出的优势:
表 1-1 副本性能测试对比
我们的初步性能测试结果如表 1-1 所示;副本数越多,共享版本的 es 越具有优势;
从表 1-1 所示我们可以看出性能似乎提升的不是特别理想,目前我们正从两个方面进行优化提升:
在研发 es 计算存储分离的过程中,我们攻克了很多的问题,后续将输出更加详细的文章进行介绍,比如:主写副只读的具体实现,replica 的访问近实时问题,ES 的主分片切换脏写问题等等。目前共享版本的 ES 正在内部进行公测,欢迎在云搜平台进行试用。
对于有大量写入的场景,通常不会持续的高流量写入,而只有 1-2 个小时写入流量洪峰;在写入过程中最耗费时间的过程并不是写磁盘而是构建 segment,既然构建 segment 如此耗时,那么我们是否可以将该部分功能单独出来,形成一个可快速扩展的资源(避免去直接改动 es 源码而引入其他问题)。
目前业界已经有比较好的案例如阿里云的 Indexing Service 和滴滴开源的 ES-Fastloader 外部构建 Segment,相对于共享存储版的 es 实现起来更简单;它的核心解决方案使用了 spark 或者 map reduce 这种批处理引擎进行批量计算处理,然后将构建好的 segment 搬运到对应的索引 shard 即可。它的详细实现,我这里就不做搬运工了,大家感兴趣可以参考滴滴发布的文章《滴滴离线索引快速构建 FastIndex 架构实践》
外部构建 segment 的功能也在我们的规划中。
ES 实现降本增效的另外一个方向:分级存储,该解决方案主要是针对数据量大查询少且对查询耗时不太敏感的业务。分级存储,比较成熟的解决方案有 es 冷热架构和可搜索快照。
冷热架构适用场景:时序型数据或者同一集群中同时存在这两个索引(一个热数据,另外一个冷数据)
es 冷热架构架构,该功能已经在京东云上线有一段时间了,欢迎大家根据自己的业务形态进行试用,冷数据节点开启如图 2-1 所示
图 2-1 冷数据节点开启
建议如果索引表是按天/小时,这种周期存储的数据,且数据查询具有冷热性,建议开启冷节点;开启冷节点后你可能会获得如下的收益:
冷热架构的核心技术为
shard-allocation-filtering;
冷热架构实现原理:
es 的 hot 节点增加如下配置
node.attr.box_type: hot
es 的 warm 节点增加如下配置
node.attr.box_type: warm
热数据索引 setting 增加如下配置,即可限制 shard 分配在 hot 节点
"index.routing.allocation.require.box_type": "hot"
当数据查询减弱,我们通过如下配置,即可使数据由 hot 节点迁移到 warm 节点
"index.routing.allocation.require.box_type": "warm"
可搜索快照是在冷热架构的基础上更进一步的分级存储,在之前我们将数据快照之后是无法对快照的数据进行搜索,如果要对快照的数据进行搜索,则需将快照数据先 restore(restore 的过程可能会比较长)之后才能被搜索。
在引入可搜索快照之后,我们可以直接搜索快照中的数据,大大降低了没必要的资源使用.
除了从资源的角度进行降低存储成本之外,基于数据自身的特性,使用优秀的压缩算法也是一种必不可少的搜索;针对时序数据 facebook 开源了一个非常优秀的压缩算法 zstd,
目前已经在业界被大量使用,国内的两大云友商已经在 es 进行了实现,腾讯云针对 zstd 的测试结果如表 3-1 所示;阿里云在 TimeStream 功能中使用了 zstd。
表 3-1 三种压缩算法的对比测试结果
目前在 lucene 的代码库中也有开源爱好者提交了 custom codec providing Zstandard compression/decompression(zstd pr)
es 单个节点存储数据量受到 jvm 堆内存的限制,为了使单个节点能够存储更多的数据,因此我们需要减少堆内存中的数据。
ES 堆中常驻内存中占据比重最大是 FST,即 tip(terms index) 文件占据的空间,1TB 索引大约占用 2GB 或者更多的内存,因此为了节点稳定运行,业界通常认为一个节点 open 的索引不超过 5TB。现在,从 ES 7.3 版本开始,将 tip 文件修改为通过 mmap 的方式加载,这使 FST 占据的内存从堆内转移到了堆外 (即 off Heap 技术 ) 由操作系统的 pagecache 管理 [6]。
使用 esrally 官方数据集 geonames 写入索引 1TB,使用 _cat/segments API 查看 segments.memory 内存占用量,对比 offheap 后的内存占用效果,如表 3-2 所示;JVM 内存占用量降低了 78% 左右
表 3-2 segments.memory 内存占用量
[1] Indexing Service
[2] ES-Fastloader
[3] 大规模测试新的 Elasticsearch 冷层可搜索快照
[4] Introducing Elasticsearch searchable snapshots
[5] 7.7 版本中的新改进:显著降低 Elasticsearch 堆内存使用量
[6] Elasticsearch 7.3 的 offheap 原理