百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

Elasticsearch与文件描述符的恩恩怨怨

sinye56 2025-01-24 13:52 20 浏览 0 评论

提到Elasticsearch,让笔者最恶心的倒不是它的反人类的DSL设计,而是每次安装都需要修改进程的最大文件描述符。那ES与文件描述符有啥恩怨呢,下面就来唠叨唠叨。首先说说文件描述符、在说说ES为什么要这么多文件描述符。

一、文件描述符

1、什么是文件描述符

文件描述符(File descriptor)是操作系统为了高效管理文件所创建的一种索引,用于指向被打开的文件,所有I/O操作都是通过文件描述符来实现。有的地方也会说成是文件句柄,他俩有些区别,这里为了方便理解,暂且认为一样。

如果以文件句柄(File Handle)来理解的话,也很形象。Handle是门把手的意思,我们用门把手操作门,类似的,进程用文件句柄操作底层操作系统的资源。

在Linux中,遵循一切皆是文件的原则,磁盘文件、目录、设备、网络套接字、硬件等都是文件。当进程读写文件,在打开时,文件和进程就建立了连接,文件描述符就是这个连接。

文件描述符实际上就是对内核层的一个硬件资源实例的指针的引用。当然啦,它和指针也是有区别的,指针是栈上的变量,用来操作堆内存里的对象。

文件描述符在系统里的位置见下图:

2、为什么需要文件描述符

这里还用门把手举例。一扇门如果有多个把手,被不同的人操作,那门往哪儿走就不确定了,很容易出现争论。为了避免这种情况,门只有一个把手。

为了解决系统资源浪费和资源冲突的问题,操作系统不会让每个用户层的进程都在内核层创建一个硬件资源实例。在操作同一个系统硬件资源时,用户层可能有多个进程,但是都对应到内核层的一个进程。

3、文件描述符数量限制

操作系统会为进程设置一个默认的可以操作的文件描述符数量,进程打开的文件数量或者需要的文件数量超过这个数字时就会抛出异常。

通过ulimit -a命令可以查看可操作的文件描述符数量。通过vim /etc/security/limits.con可以修改进程可操作性的文件描述符数量。

二、ES为什么要这么多文件描述符

在说ES为什么要这么多文件描述符之前,先简单说说ES写入数据的过程。

1、ES写入数据的过程

1.1、写入的主要流程

假设有3个节点:node1、node2、node3,其中node2是主节点,写入数据的主要流程如下:

  1. 客户端的请求携带数据,到达node1,node1找到主分片所在的node2。
  2. node1将数据转发到主分片所在node2,node2将数据写入主分片。
  3. 主分片写入成功后,node2将数据转发到node1和node3,node1和node3将数据写入副本分片。
  4. 所有副本分片都写入成功后,node2向 客户端所请求的节点node1 返回写入成功的消息。
  5. 客户端所请求的节点node1向客户端返回成功。

1.2、写入的细节流程

ES写入数据的细节流程分为4步:Refresh操作、写Transaction Log、Flush操作***、Merge***操作

  • Refresh操作:在文档写入ES时首先会写到Index Buffer里,然后每隔一秒执行一次Refresh操作,把Index Buffer里的数据写入磁盘缓存里,但不会调用fsync刷到硬盘。因为数据被Refresh 后才能被检索出来,所以ES是近实时的搜索引擎。
  • 写Transaction Log:文档写入到Index Buffer后,数据是没有刷到硬盘的,存在数据丢失的风险。为了保证数据不丢失,在写完 Index Buffer 后,系统还要写Transaction Log,写Transaction Log默认是调用 fsync 进行刷盘的。ES重启时会从Transaction Log中恢复数据,防止数据丢失。
  • Flush操作:Flush操作会将磁盘缓存持久化到磁盘中,默认30分钟 或 在Transaction Log写满时触发。Flush将磁盘缓存 持久化到磁盘后,会清空Transaction Log。
  • Merge操作:在每次Refresh 后都会创建一个新的Segment文件,随着时间推移和索引越来越多,Segment文件会暴增,这时会带来许多问题,比如消耗过多的文件描述符、内存、CPU时间周期等,而且每次搜索都要检查每个Segment然后再合并结果,所以Segment越多、搜索也就越慢,因此需要合并Segment。ES会自动执行Merge操作,然后物理删除过多的Segment文件。

2、为什么要这么多文件描述符

通过以上ES写数据的流程可以知道,ES在每次Refresh时都会创建新的Segment,创建索引的过程中会创建大量的Segment。Segment内部一般包含着:词项、词频、文档之间的关系。每个Segment都是一个文件,ES使用了大量的文件。每一个Segment都会消耗文件描述符、内存和CPU运行周期。同时,ES 在节点之间进行通信和数据拷贝、ES在和客户端之间进行通信等,也使用了大量的网络资源。

基于以上原因,ES需要大量的文件描述符。Linux 系统为进程准备了一个默认的文件描述符数量,但是这对ES节点来说有点低了,所以要调大文件描述符数量。

3、Linux命令lsof

lsof命令是Linux系统管理工具,人如其名,“列出打开文件(lists openfiles)”。

lsof -p pid命令:显示系统中某个进程当前已打开的所有文件列表。

执行lsof -p 29624时,可以看到大量的文件,索引越多,写入的数据越多,文件描述符数量越多。

执行lsof -p 29624|wc -l,可以查看进程打开文件的总数。

4、其余的文件描述符不够用的情况

1、大量新的数据源源不断的快速写入到ES,造成临时的Segment文件越来越多,ES无法快速合并成一个大的Segment。在查询时,如果查询的数据对应到多个Segment,那么打开的文件描述符就很多了。

2、机器内存过小,资源紧张时内存不够,会触发OOM-Killer将ES进程杀死,其实是一种假死的,因为进程被Kill掉之后,保活进程又会将ES重启,而每次重启后都会产生新的translog文件,并且没有把之前旧的日志文件删除,最终把系统的文件描述符耗尽。

3、如果还有其余场景的话,欢迎朋友们在留言区补充。

三、总结

本文主要说了 文件描述符ES为什么要这么多文件描述符,希望对你有帮助,核心概念如下:

  • 文件描述符:用户层的进程 对 内核层一个 硬件资源实例 的指针 的引用。
  • ES写入流程:Refresh操作、写Transaction Log、Flush操作、Merge操作。
  • 为什么要这么多:ES在每次Refresh时都会创建新的Segment,随着时间的推移和索引的增多,会导致短时间内的Segment数量暴增。ES 在节点之间进行通信和数据拷贝、ES在和客户端之间进行通信等原因,所以需要大量的文件描述符。

本篇完结!感谢你的阅读,欢迎点赞 关注 收藏 私信!!!

原文链接:Elasticsearch与文件描述符的恩恩怨怨

相关推荐

程序员:JDK的安装与配置(完整版)_jdk的安装方法

对于Java程序员来说,jdk是必不陌生的一个词。但怎么安装配置jdk,对新手来说确实头疼的一件事情。我这里以jdk10为例,详细的说明讲解了jdk的安装和配置,如果有不明白的小伙伴可以评论区留言哦下...

Linux中安装jdk并配置环境变量_linux jdk安装教程及环境变量配置

一、通过连接工具登录到Linux(我这里使用的Centos7.6版本)服务器连接工具有很多我就不一一介绍了今天使用比较常用的XShell工具登录成功如下:二、上传jdk安装包到Linux服务器jdk...

麒麟系统安装JAVA JDK教程_麒麟系统配置jdk

检查检查系统是否自带java在麒麟系统桌面空白处,右键“在终端打开”,打开shell对话框输入:java–version查看是否自带java及版本如图所示,系统自带OpenJDK,要先卸载自带JDK...

学习笔记-Linux JDK - 安装&配置

前提条件#检查是否存在JDKrpm-qa|grepjava#删除现存JDKyum-yremovejava*安装OracleJDK不分系统#进入安装文件目...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

测试员必备:Linux下安装JDK 1.8你必须知道的那些事

1.简介在Oracle收购Sun后,Java的一系列产品就被整合到Oracle官网中,打开官网乍眼一看也不知道去哪里下载,还得一个一个的摸索尝试,而且网上大多数都是一些Oracle收购Sun前,或者就...

Linux 下安装JDK17_linux 安装jdk1.8 yum

一、安装环境操作系统:JDK版本:17二、安装步骤第一步:下载安装包下载Linux环境下的jdk1.8,请去官网(https://www.oracle.com/java/technologies/do...

在Ubuntu系统中安装JDK 17并配置环境变量教程

在Ubuntu系统上安装JDK17并配置环境变量是Java开发环境搭建的重要步骤。JDK17是Oracle提供的长期支持版本,广泛用于开发Java应用程序。以下是详细的步骤,帮助你在Ubuntu系...

如何在 Linux 上安装 Java_linux安装java的步骤

在桌面上拥抱Java应用程序,然后在所有桌面上运行它们。--SethKenlon(作者)无论你运行的是哪种操作系统,通常都有几种安装应用程序的方法。有时你可能会在应用程序商店中找到一个应用程序...

Windows和Linux环境下的JDK安装教程

JavaDevelopmentKit(简称JDK),是Java开发的核心工具包,提供了Java应用程序的编译、运行和开发所需的各类工具和类库。它包括了JRE(JavaRuntimeEnviro...

linux安装jdk_linux安装jdk软连接

JDK是啥就不用多介绍了哈,外行的人也不会进来看我的博文。依然记得读大学那会,第一次实验课就是在机房安装jdk,编写HelloWorld程序。时光飞逝啊,一下过了十多年了,挣了不少钱,买了跑车,娶了富...

linux安装jdk,全局配置,不同用户不同jdk

jdk1.8安装包链接:https://pan.baidu.com/s/14qBrh6ZpLK04QS8ogCepwg提取码:09zs上传文件解压tar-zxvfjdk-8u152-linux-...

运维大神教你在linux下安装jdk8_linux安装jdk1.7

1.到官网下载适合自己机器的版本。楼主下载的是jdk-8u66-linux-i586.tar.gzhttp://www.oracle.com/technetwork/java/javase/downl...

window和linux安装JDK1.8_linux 安装jdk1.8.tar

Windows安装JDK1.8的步骤:步骤1:下载JDK打开浏览器,找到JDK下载页面https://d.injdk.cn/download/oraclejdk/8在页面中找到并点击“下载...

最全的linux下安装JavaJDK的教程(图文详解)不会安装你来打我?

默认已经有了linux服务器,且有root账号首先检查一下是否已经安装过java的jdk任意位置输入命令:whichjava像我这个已经安装过了,就会提示在哪个位置,你的肯定是找不到。一般我们在...

取消回复欢迎 发表评论: