【Elasticsearch】Elasticsearch中FST的Off-Heap优化详解

转自:https://www.easyice.cn/archives/346

前言

一直以来,Elasticsearch(ES)堆内存中占据比重最大的是 FST,即 .tip(terms index)文件。这些文件占据的空间很大,1TB 的索引大约需要 2GB 或更多的内存。为了确保节点稳定运行,业界通常认为一个节点打开的索引不应超过 5TB。

从 ES 7.3 版本开始,.tip 文件被修改为通过 mmap 的方式加载,这使得 FST 占据的内存从堆内转移到了堆外,由操作系统的 page cache 管理。

参考 ES 7.3 的 release notes:

Also mmap terms index (.tip) files for hybridfs #43150 (issue: #42838)

现在,我们来深入探讨其中的一些细节。

hybridfs 的工作原理

hybridfs 是索引默认的 store 类型,它根据操作系统类型自动选择 nio 或者 mmap。那么究竟哪些文件被 mmap 方式打开呢?手册中提到:

Currently only the Lucene term dictionary, norms and doc values files are memory mapped. All other files are opened using Lucene NIOFSDirectory.

对应到文件扩展名,就是 .nvd(norms)、.dvd(doc values)、.tim(term dictionary)、.tip(term index)、.cfs(compound)类型的文件使用 mmap 方式加载,其余使用 nio:

switch(extension) {case "nvd":case "dvd":case "tim":case "tip":case "cfs":return true;default:return false;
}

为什么使用 mmap 实现 Off-Heap

你可能会问,为什么把 .tip 文件通过 mmap 方式读取就实现了 Off-Heap?像 HBase 实现 Off-Heap 需要将数据转移到堆外的数据结构,为什么 ES 不需要?

FST 的查找过程

在堆内存(On-Heap)的情况下,Lucene 将 .tip 文件的数据读进一个数组。在 FST 查找时,seek 到某个位置,读取一些字节,然后再次 seek,再读取,相当于边读取边解析。

private Arc<T> findTargetArc(BytesReader in, ...) {// ...in.setPosition(follow.target);arc.numArcs = in.readVInt();arc.bytesPerArc = in.readVInt();arc.posArcsStart = in.getPosition();arc.nextArc = arc.posArcsStart;// ...
}

在 On-Heap 的情况下,这个 BytesReader 的初始化就是简单地将文件读进数组:

public void init(DataInput in, long numBytes) {bytesArray = new byte[(int) numBytes];in.readBytes(bytesArray, 0, bytesArray.length);
}

因此,在 Off-Heap 的情况下,mmap 像数组一样读取就可以了。

如何查看文件的缓存情况

如果想要查看文件被 page cache 缓存的百分比,可以使用以下工具:

  • vmtouch(推荐)
  • pcstat
  • hcache
  • fincore

要确认某个 .tip 文件是否被 mmap 方式读取的,可以使用 pmap 命令,被 mmap 映射的文件会在这里列出来。

Off-Heap 后的效果

使用 geonames 数据集写入索引 1TB,使用 _cat/segments API 查看 segments.memory 内存占用量,对比 Off-Heap 后的内存占用效果:

store.typesegments.memory
niofs4.7GB
hybridfs1.06GB

JVM 内存占用量降低了约 78%。不同数据样本结果不同,其他的可能会降低更多。

通过 _cat/segments 观测到的 segments.memory 指标,会比实际占用的 JVM 内存少一些,不过相差不大,上述结果可作为参考。

Page Cache 的管理

由于 Off-Heap 后的堆外内存由操作系统的 page cache 管理,什么时候被驱逐出去由操作系统决定,进程无法控制。如果 .tip 文件的内容被驱逐出 page cache,对 FST 的查找会涉及到磁盘 IO,对查询延迟有比较大的影响。

Page Cache 的回收策略

Linux 系统的 page cache 回收有两种情况:

  1. 系统内存不足时的自动回收:当系统可用内存不足时,系统会自动回收 page cache 缓存的数据,其中可能包括 mmap 映射的 .tip 文件。
  2. 手工回收:通过改写 /proc/sys/vm/drop_caches 或 posix_fadvise 调用来手工回收。

当索引处于打开(open)状态时,由 mmap 映射到 page cache 的 .tip 数据并不会被回收;而如果索引处于关闭(close)状态,则会被完全回收。

Page Cache 的回收算法

在 Linux 2.6.34 的内核中,对 page cache 的回收策略使用双链策略,参考《Linux 内核设计与实现(第三版)》。算法描述大致如下:

  • 引入两个链表:active list 和 inactive list。
  • 两个链表都是从尾部加入,头部移出。
  • 页面换出操作只在 inactive list 执行。
  • 对于文件缓存,当第一次访问的时候加入到 inactive list,再次访问的时候把它提升到 active list。
  • 当 active list 大小大于 inactive list,就将 active list 头部的页面降级到 inactive list。

更多 page cache 的信息可以参考 Linux MM Page Replacement Design。

mmap 的原理

依据 mmap 的原理,文件描述符(fd)被映射为指针(或者说字节数组)供进程直接访问,仅在进程访问到相应位置的时候才去读取磁盘,是根据内容按需读取磁盘。

你可能会想,既然如此,_open 索引是不是变快了?原来 nio 需要把整个文件读进堆内存,现在 mmap 一下就结束了,那么等索引首次被查询的时候才会加载到 page cache?实际上,_open 索引并没变快,因为在 _open 索引的过程中,Lucene 会检查文件的校验和,把整个文件读取一遍:

// BlockTreeTermsReader constructor
CodecUtil.checksumEntireFile(indexIn);
ChecksumIndexInput in = new BufferedChecksumIndexInput(clone);
// 读取文件到目标位置,并更新校验和
in.seek(in.length() - footerLength());
return checkFooter(in);

关于 _id 字段的 Off-Heap 问题

Lucene 支持字段级的 Off-Heap 设置。ES 7.3 中将 .tip Off-Heap 时并不包含 _id 字段,#52518 中提到,这是因为担心降低写入速度。不过在经历了一些测试之后发现影响并不大。

一般来说,只有在使用显式 IDs 时,索引速率才会受到影响,因为否则 Elasticsearch 几乎不会在索引过程中查找 terms dictionary。因此,强制将 _id 字段的 terms index 保持在堆内存中,对于那些具有仅追加工作负载的用户来说是相当浪费的。此外,我使用 http_logs 数据集在索引时进行了基准测试,结果表明,即使在使用显式 IDs 的情况下,速度下降也足够小,可能不值得强制将 terms index 保持在堆内存中。

题外话:这段内容提到,使用外部 doc id 方式入库时需要从 term dictionary 中查询,这是因为使用外部 ID 写入时,ES 需要判断该 ID 是否存在,以便执行更新(update)或追加(append)操作。因此在分片中对 _id 字段执行 Lucene 的 seekExact 查询来判断此 ID 是否存在,所以使用外部 ID 入库时写入速度会降低一些(约 20%)。这也是 _id 字段需要写入 FST 的一个原因。

在将 _id 字段 Off-Heap 之后,使用 http_logs 数据集和外部 ID 的方式执行写入测试,写入速度降低了 1.8%,JVM 内存降低了 100 倍。

因此,在 ES 7.7 版本中,会将 _id 字段也放到堆外。

结语

把 FST 放到堆外可以让节点能够持有更多的数据,这对 ES 集群能处理的数据规模有重大提升,意义重大。但是 .tip 文件需要加载到内存的意义比 .tim 等文件要重要得多,page cache 总会有需要回收的时候,谁能保证 .tip 不被回收呢?所以总体来说,可能会让查询延迟增加不确定性,且不便重现和诊断。不过也不用太担心,这种情况一般很少发生。

参考资料

  • Elasticsearch Issue #38390
  • Elasticsearch Pull Request #42838
  • Elasticsearch Pull Request #43150
  • Elasticsearch Pull Request #52518
  • Elasticsearch 7.3.0 Release Notes
  • Linux MM Page Replacement Design

转自:https://www.easyice.cn/archives/346

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/news/883642.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis-14.XML映射文件

一.XML映射文件 除了使用注解的方式完成mybatis基础的增删改查操作以外&#xff0c;还可以使用基于XML文件配置SQL语句。 二.配置XML映射文件 首先在resources中新建文件夹com/域名/mapper用来和java源代码中的包名保持一致&#xff0c;这是同包。 然后在mapper文件夹中新建x…

uni-app之旅-day08-购物车-收货地址

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 9.2 收货地址区域9.2.1 创建收货地址组件9.2.2 实现收货地址区域的按需展示9.2.3 实现选择收货地址的功能9.2.4 将 address 信息存储到 vuex 中9.2.5 将 Store 中的…

详解Pectra升级:如何影响以太坊价值及利益相关者

Pectra很可能是最后几个会直接影响用户和ETH持有者的升级之一。 原文&#xff1a;Galaxy Research&#xff1b;编译&#xff1a;Golem&#xff1b;编辑&#xff1a;郝方舟 出品 | Odaily星球日报&#xff08;ID&#xff1a;o-daily&#xff09; 编者按&#xff1a;以太坊 Pectr…

【开源项目】libfaketime安装、使用——小白教程

项目 Github&#xff1a;GitHub - wolfcw/libfaketime: libfaketime modifies the system time for a single application libfaketime安装 01.切换路径&#xff0c;目标路径&#xff1a;/usr/local &#xff08;在/usr/local路径下git clone 开源项目) 切换路径指令: cd …

「C/C++」C++17 之 std::variant 安全的联合体(变体)

#1024程序员节&#xff5c;征文# ✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计…

windows 训练yolov8官方数据集

第一步&#xff1a;安装Anaconda3-2024.06-1-Windows-x86_64.exe 下载地址&#xff1a;https://repo.anaconda.com/archive/ 第二步&#xff1a;创建环境 打开Anaconda Prompt 输入 conda info -e 打印&#xff1a; 已经安装了一些环境&#xff0c;然后我们创建新的环境&a…

Linux(kali)换源操作

apt换源 &#xff08;切换到国内源&#xff09; 阿里云Kali镜像源 deb http://mirrors.aliyun.com/kali kali-rolling main non-free non-free-firmware contrib deb-src http://mirrors.aliyun.com/kali kali-rolling main non-free non-free-firmware contrib 1.切换为root用…

springboot095学生宿舍信息的系统--论文pf(论文+源码)_kaic

学生宿舍信息管理系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了学生宿舍信息管理系统的开发全过程。通过分析学生宿舍信息管理系统管理的不足&#xff0c;创建了一个计算机管理学生宿舍信息管理系统的方…

lstio微服务治理-概述

一、Service Mesh介绍 Service Mesh 的中文译为&#xff1a;服务网格&#xff0c;是一个用于处理服务和服务之间通信的基础设施层。它负责为构建复杂的云原生应用传递可靠的网络请求&#xff0c;并为服务通信实现了微服务所需要的基本组件功能&#xff0c;如&#xff1a;服务发…

新网虚拟主机wordpress伪静态规则

先在WordPress安装目录下的创建.htaccess 文件&#xff0c;并在该文件中添加以下规则&#xff1a; BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index.php$ [L] RewriteCond %{REQUEST_FILENAME} !f RewriteCond %{REQUEST_…

哈尔滨银行难以摆脱低估值,不良贷款突破100亿元,何时回A?

撰稿 | 芋圆 来源 | 贝多财经 在经济缓慢恢复的步调中&#xff0c;多数理财者倾向于选择更为保守的资产分配策略&#xff0c;但部分银行在竞争加剧&#xff0c;净息差持续收窄的压力下&#xff0c;却将业务转型的矛头对准了风险更高的金融投资领域&#xff0c;哈尔滨银行就是…

400行程序写一个实时操作系统(十七):调度算法的实现

前言 在上一篇博客笔者介绍了操作系统中的调度算法&#xff0c;调度算法的本质就是选择下一个任务。 如果读者认真看了上一篇文章的内容&#xff0c;那么接下来讲解的Sparrow的算法应该是非常清晰易懂的。 在实时操作系统Sparrow RTOS中&#xff0c;我们引入了优先级的概念&…

基础知识-因果分析-daythree-独立性检验

我们经常需要观察一个事件的发生对另一个事件的发生是否有影响。有时候&#xff0c;我们可以观察到一个事件的发生对另一个事件发生的概率有影响。比如&#xff0c;你驾车超速这个事件的发生会增加你发生交通事故的概率。但是&#xff0c;有时候我们也可以观察到&#xff0c;一…

SpringMVC6-SpringMVC的视图

目录 ThymeleafView 转发视图 重定向视图 视图控制器view-controller SpringMVC中的视图是View接口&#xff0c;视图的作用&#xff1a;渲染数据&#xff0c;将模型Model中的数据展示给用户 SpringMVC视图的种类很多&#xff0c;默认有转发视图InternalResourceView 和重定…

【再谈设计模式】单例模式~唯一性的守护者

一、引言 在软件工程中&#xff0c;软件开发&#xff0c;设计模式是提高代码复用性和可维护性的有效工具。单例模式&#xff08;Singleton Pattern&#xff09;作为一种创建型设计模式&#xff0c;旨在确保一个类只有一个实例&#xff0c;并提供对该实例的全局访问。这一模式在…

Spring Boot 实现文件上传下载功能

文章目录 一、原理分析1.1 请求类型1.2 服务器解析 二、功能实现2.1 创建项目并导入依赖2.2 文件上传功能实现2.2.1 文件上传 Service2.2.2 文件上传 Controller 2.3 文件下载功能实现2.3.1 文件下载 Service2.3.2 文件下载 Controller 2.4 文件上传前端代码(可选)2.4.1 上传文…

HarmonyOS Next API12最新版 端云一体化开发-云函数篇

一、新建一个端云一体化项目 见文章&#xff1a; HarmonyOS NEXT API12最新版 端云一体化开发-创建端云一体化项目流程_鸿蒙appapi-CSDN博客 二、官方文档 使用限制-云函数 - 华为HarmonyOS开发者 (huawei.com) Cloud Foundation Kit简介-Cloud Foundation Kit&#xff0…

深度学习:SGD的缺点

首先看下述函数&#xff1a; 最小值为x0&#xff0c;y0处 先了解下它的梯度特征。了理解其梯度特征&#xff0c;我们需要计算其梯度向量。 梯度向量 ∇f 是函数 f 在每个变量方向上的偏导数组成的向量。具体来说&#xff1a; ∇f(∂f/∂x,∂f∂/y) 首先&#xff0c;我们计算 f …

【北京迅为】《STM32MP157开发板嵌入式开发指南》-第六十七章 Trusted Firmware-A 移植

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

C++游戏开发详解

C 是一种广泛使用的编程语言&#xff0c;尤其在游戏开发领域有着不可替代的地位。它提供了对底层硬件的直接访问能力&#xff0c;允许开发者优化性能&#xff0c;这对于追求高帧率和低延迟的游戏来说至关重要。本文将详细介绍使用 C 进行游戏开发的基础知识和技术要点&#xff…