三十五、ElasticsearchI基于snapshot+ Hadoop hdfs进行数据备份和恢复

三十五、ElasticsearchI基于snapshot+ Hadoop hdfs进行数据备份和恢复,第1张

一、es生产集群备份恢复之基于snapshot+hdfs进行数据备份

1、es集群数据备份

任何一个存储数据的软件,都需要定期的备份数据。es replica提供了运行时的高可用保障机制,可以容忍少数节点的故障和部分数据的丢失,但是整体上却不会丢失任何数据,而且不会影响集群运行。但是replica没法进行灾难性的数据保护,比如说机房彻底停电,所有机器全部宕机,等等情况。对于这种灾难性的故障,我们就需要对集群中的数据进行备份了,集群中数据的完整备份。

要备份集群数据,就要使用snapshot api。这个api会将集群当前的状态和数据全部存储到一个外部的共享目录中去,比如NAS,或者hdfs。而且备份过程是非常智能的,第一次会备份全量的数据,但是接下来的snapshot就是备份两次snapshot之间的增量数据了。数据是增量进入es集群或者从es中删除的,那么每次做snapshot备份的时候,也会自动在snapshot备份中增量增加数据或者删除部分数据。因此这就意味着每次增量备份的速度都是非常快的。

如果要使用这个功能,我们需要有一个预先准备好的独立于es之外的共享目录,用来保存我们的snapshot备份数据。es支持多种不同的目录类型:shared filesystem,比如NAS;Amazon S3;hdfs;Azure Cloud。不过对于国内的情况而言,其实NAS应该很少用,一般来说,就用hdfs会比较多一些,跟hadoop这种离线大数据技术栈整合起来使用。

2、创建备份仓库

(1)创建和查询仓库的命令

这里用了shared filesystem作为仓库类型,包括了仓库名称以及仓库类型是fs,还有仓库的地址。这个里面就包含了仓库的一些必要的元数据了。可能还有其他的一些参数可以配置,主要是基于我们的node和网络的性能来配置。max_snapshot_bytes_per_sec,这个参数用于指定数据从es灌入仓库的时候,进行限流,默认是20mb/s。max_restore_bytes_per_sec,这个参数用于指定数据从仓库中恢复到es的时候,进行限流,默认也是20mb/s。假如说网络是非常快速的,那么可以提高这两个参数的值,可以加快每次备份和恢复的速度,比如下面:

创建一个仓库之后,就可以查看这个仓库的信息了:GET /_snapshot/my_backup,或者是查看所有的仓库,GET /_snapshot/_all。可能返回如下的信息:

(2)基于hdfs创建仓库

首先先要在es插件目录安装repository-hdfs的插件:bin/elasticsearch-plugin install repository-hdfs,必须在每个节点上都安装,然后重启整个集群。

在3个hdfs node上,都加入hdfs-site.xml,禁止权限检查,如果要修改这个配置文件,要先在/usr/local/hadoop/sbin,运行./stop-dfs.sh,停止整个hdfs集群,然后在3个node上,都修改hdfs-site.xml,加入下面的配置,禁止权限的检查

hdfs snapshot/restore plugin是跟最新的hadoop 2.x整合起来使用的,目前是hadoop 2.7.1。所以如果我们使用的hadoop版本跟这个es hdfs plugin的版本不兼容,那么考虑在hdfs plugin的文件夹里,将hadoop相关jar包都替换成我们自己的hadoop版本对应的jar包。即使hadoop已经在es所在机器上也安装了,但是为了安全考虑,还是应该将hadoop jar包放在hdfs plugin的目录中。

安装好了hdfs plugin之后,就可以创建hdfs仓库了,用如下的命令即可:

(3)验证仓库

在课程演示中,最好都是用root用户去演示,一般来说就够了,因为在不同的公司里,你可能linux用户管理,权限,都不太一样

专门去建一套用户和授权去演示,不太合适

如果一个仓库被创建好之后,我们可以立即去验证一下这个仓库是否可以在所有节点上正常使用。verify参数都可以用来做这个事情,比如下面的命令。这个命令会返回一个node列表,证明那些node都验证过了这个仓库是ok的,可以使用的

先停止整个es集群,然后在3个节点上,都加入下面的配置,然后用elasticsearch账号重启整个es集群

3、对索引进行snapshotting备份

(1)对所有open的索引进行snapshotting备份

一个仓库可以包含多分snapshot,每个snapshot是一部分索引的备份数据,创建一份snapshot备份时,我们要指定要备份的索引。比如下面这行命令:PUT _snapshot/my_hdfs_repository/snapshot_1,这行命令就会将所有open的索引都放入一个叫做snapshot_1的备份,并且放入my_backup仓库中。这个命令会立即返回,然后备份 *** 作会被后台继续进行。如果我们不希望备份 *** 作以后台方式运行,而是希望在前台发送请求时等待备份 *** 作执行完成,那么可以加一个参数即可,比如下面这样:PUT _snapshot/my_backup/snapshot_1?wait_for_completion=true。

另一种方式

curl -XPUT ' http://elasticsearch02:9200/_snapshot/my_hdfs_repository/snapshot_1'

(2)对指定的索引进行snapshotting备份

默认的备份是会备份所有的索引,但是有的时候,可能我们不希望备份所有的索引,有些可能是不重要的数据,而且量很大,没有必要占用我们的hdfs磁盘资源,那么可以指定备份少数重要的数据即可。此时可以使用下面的命令去备份指定的索引:

ignore_unavailable如果设置为true的话,那么那些不存在的index就会被忽略掉,不会进行备份过程中。默认情况下,这个参数是不设置的,那么此时如果某个index丢失了,会导致备份过程失败。设置include_global_state为false,可以阻止cluster的全局state也作为snapshot的一部分被备份。默认情况下,如果某个索引的部分primary shard不可用,那么会导致备份过程失败,那么此时可以将partial设置为true。

而且snapshotting的过程是增量进行的,每次执行snapshotting的时候,es会分析已经存在于仓库中的snapshot对应的index file,然后仅仅备份那些自从上次snapshot之后新创建的或者有过修改的index files。这就允许多个snapshot在仓库中可以用一种紧凑的模式来存储。而且snapshotting过程是不会阻塞所有的es读写 *** 作的,然而,在snapshotting开始之后,写入index中的数据,是不会反应到这次snapshot中的。每次snapshot除了创建一份index的副本之外,还可以保存全局的cluster元数据,里面包含了全局的cluster设置和template。

每次只能执行一次snapshot *** 作,如果某个shard正在被snapshot备份,那么这个shard此时就不能被移动到其他node上去,这会影响shard rebalance的 *** 作。只有在snapshot结束之后,这个shard才能够被移动到其他的node上去。

4、查看snapshot备份列表

一旦我们在仓库中备份了一些snapshot之后,就可以查看这些snapshot相关的详细信息了,使用这行命令就可以查看指定的snapshot的详细信息:GET _snapshot/my_backup/snapshot_2,结果大致如下所示。当然也可以查看所有的snapshot列表,GET _snapshot/my_backup/_all。

5、删除snapshot备份

如果要删除过于陈旧的snapshot备份快照,那么使用下面这行命令即可:DELETE _snapshot/my_backup/snapshot_2。记住,一定要用api去删除snapshot,不要自己手动跑到hdfs里删除这个数据。因为snapshot是增量的,有可能很多snapshot依赖于底层的某一个公共的旧的snapshot segment。但是delete api是理解数据如何增量存储和互相依赖的,所以可以正确的删除那些不用的数据。如果我们自己手工进行hdfs文件删除,可能导致我们的backup数据破损掉,就无法使用了。

6、监控snapshotting的进度

使用wait_for_completion可以在前台等待备份完成,但是实际上也没什么必要,因为可能要备份的数据量特别大,难道还等待1个小时??看着是不太现实的,所以一般还是在后台运行备份过程,然后使用另外一个监控api来查看备份的进度,首先可以获取一个snapshot ID:GET _snapshot/my_backup/snapshot_3。如果这个snapshot还在备份过程中,此时我们就可以看到一些信息,比如什么时候开始备份的,已经运行了多长时间,等等。然而,这个api用了跟snapshot一样的线程池去执行,如果我们在备份非常大的shard,进度的更新可能会非常之慢。一个更好的选择是用_status API,GET _snapshot/my_backup/snapshot_3/_status,这个api立即返回最详细的数据。这里我们可以看到总共有几个shard在备份,已经完成了几个,还剩下几个,包括每个索引的shard的备份进度:

7、取消snapshotting备份过程

如果我们想要取消一个正在执行的snapshotting备份过程,比如我们发现备份时间过于长,希望先取消然后在晚上再运行,或者是因为不小心误 *** 作发起了一次备份 *** 作,这个时候就可以运行下面这条命令:DELETE _snapshot/my_backup/snapshot_3。也就是立即删除这个snapshot,这个命令会去取消snapshot的过程,同时将备份了一半的仓库中的数据给删除掉。

curl -XDELETE ' http://elasticsearch02:9200/_snapshot/my_hdfs_repository/snapshot_1'

9、es生产集群备份恢复之基于snapshot+hdfs+restore进行数据恢复

1、基于snapshot的数据恢复

正经备份,一般来说,是在一个shell脚本里,你用crontab做一个定时去做增量备份。

那么在es集群故障,导致数据丢失的时候,就可以用_restore api进行数据恢复了。比如下面这行命令:

POST _snapshot/my_hdfs_repository/snapshot_1/_restore。

文件中所有索引都全恢复。在某些场景下,我们想恢复一些数据但是不要覆盖现有数据,用下面的命令即可恢复数据,并且进行重命名 *** 作:

这个restore过程也是在后台运行的,如果要在前台等待它运行完,那么可以加上wait_for_completion flag:POST

_snapshot/my_backup/snapshot_1/_restore?wait_for_completion=true。

?wait_for_completion=true,等待它备份完成了以后,才会去执行下一条命令

restore过程只能针对已经close掉的index来执行,而且这个index的shard还必须跟snapshot中的index的shard数量是一致的。restore *** 作会自动在恢复好一个index之后open这个index,或者如果这些index不存在,那么就会自动创建这些index。如果通过include_global_state存储了集群的state,还会同时恢复一些template。

默认情况下,如果某个索引在恢复的时候,没有在snapshot中拥有所有的shard的备份,那么恢复 *** 作就会失败,比如某个shard恢复失败了。但是如果将partial设置为true,那么在上述情况下,就还是可以进行恢复 *** 作得。不过在恢复之后,会自动重新创建足够数量的replica shard。

此外,还可以在恢复的过程中,修改index的一些设置,比如下面的命令:

2、监控restore的进度

从一个仓库中恢复数据,其实内部机制跟从其他的node上恢复一个shard是一样的。如果要监控这个恢复的过程,可以用recovery api,比如:

GET restored_index_3/_recovery。

如果要看所有索引的恢复进度:GET /_recovery/。可以看到恢复进度的大致的百分比。

3、取消恢复过程

如果要取消一个恢复过程,那么需要删除已经被恢复到es中的数据。因为一个恢复过程就只是一个shard恢复,发送一个delete *** 作删除那个索引即可,如果那个索引正在被恢复,那么这个delete命令就会停止恢复过程,然后删除已经恢复的 所有数据。

    副本是昂贵的--在HDFS中默认的3副本机制有200%的存储空间和其它的资源(比如:网络带宽)开销。然而,相对于低 I/O 活动的暖数据集和冷数据集,在正常的 *** 作期间对其额外的副本很少访问,但是仍然消耗与第一副本相同数量的资源。

    因此,一个自然的改进是使用纠删码(Erasure Coding)替代副本机制,它使用更少的存储空间提供相同的容错级别,一个典型的纠删码设置,会使得存储空间的开销不超过50%一个EC文件的副本因子是无意义的,它一直保持为1,并且不能通过命令 -setrep修改EC的副本因子的值。

    磁盘阵列(RAID)是在存储系统中,使用EC最出名的。RAID使用条 带的方式实现的EC,它提供逻辑上序列的数据(比如文件)到更小的单元(比如比特、字节、或块),并存储连续的单元到不同的磁盘上。在本指南的其余部分,这种条带分布单元被称为条带单元(或者单元),对于每一个条带原始数据单元,计算并存储一定数量的奇偶校验单元,这个过程叫做编码。通过对剩余的数据和奇偶校验单元解码计算,可以恢复任意条带单元的错误。

    将EC和HDFS集成可以提高存储效率,然而同样提供传统的基于副本机制的HDFS持久化部署,例如:3副本的文件有6个块,将会消耗 6*3 = 18个块的磁盘空间,但是使用EC(6个数据,3个校验)部署,他将只消耗9个块的磁盘空间。

    在EC的环境中,条带有若干主要的优点,首先,它能在线EC(使用EC的格式直接写数据),避免转换阶段,直接节省存储空间。在线EC通过并行利用多磁盘主轴增强I/O性能;这在高性能的网络的集群中尤其需要。其次,它自然的分发小文件到多个DataNodes,消除了将多个文件绑定到一个编码组的需要,这会很大的简化文件的 *** 作,比如删除、配额汇报和在联邦集群中不同的Namespace之间迁移数据等。在典型的HDFS集群中,小文件占总存储空间3/4以上的消耗,为了更好的支持小文件,在第一阶段工作中,HDFS支持条带的EC。在未来,HDFS也会支持连续的EC布局,查看设计文档,更多的信息在issue HDFS-7285 中讨论。

     条带的HDFS文件是由逻辑上的块组构成,每个块组包含一定数量的内部块,为了减少额外的块对NameNode内存消耗,提出了新的分层块命名协议,块组的ID可以从它的内部块的任意 ID 中推断出来,这允许块组级别的管理,而不是块级别的。

     客户端读写路径被增强,可以并行处理一个块组的多个内部块;在输出/写入路径, DFSStripedOutputStream 用于管理一组数据流,每个数据流对应一个DataNode,该DataNode在当前块组中存储一个内部块,这些数据流大多是异步工作;协调器负责 *** 作整个块组,包括结束当前的块组、分配新的块组等等。在输入 / 读路径, DFSStripedInputStream 将请求的逻辑字节范围的数据转换为存储在DataNodes上的内部块的范围,然后并行的发布读请求,在出现故障时,它发出额外的读请求用于解码。

     DataNode会运行一个额外的 ErasureCodingWorker (ECWorker) 任务用于后台恢复失败的EC块,当NameNode检测到一个失败的EC块,它会选择一个DataNode去做恢复的工作,恢复任务通过心跳响应传递至DataNode,这个过程类似于副本块重新复制失败的数据块,重建失败的块有3个主要的任务:

     使用专用的线程池并行的读取输入数据,基于EC策略,它将所有的读请求调度到所有的源节点,并且只读取最小数据量的输入块数用于重构。

     从输入数据中解码出新的数据块和奇偶校验块,所有丢失的数据块和校验块一起解码。

     解码完成后,恢复的数据块被传输到目标DataNode节点。

     为了使纠删码策略适合异构的工作方式,我们允许HDFS集群上的文件和目录具有不同的副本和纠删码策略,纠删码策略封装了如何编码/解码文件,每一个策略由以下信息部分定义:

     这个包括在EC组(比如:6+3)中数据块和校验块的数量,以及编解码器算法(比如: Reed-Solomon, XOR )

    这决定了条带读写的粒度,包括缓冲区大小和编码工作。

    策略被命名为数据块数量-校验块数量-块单元的大小,当前支持6种内置策略:RS-3-2-1024k, RS-6-3-1024k, RS-10-4-1024k, RS-LEGACY-6-3-1024k, XOR-2-1-1024k 和REPLICATION。

    REPLICATION是一种特殊的策略,它只能被设置在目录上,强制目录采用3副本策略,而不是继承它的祖先的纠删码策略,该策略使3副本目录与纠删码目录交叉成为可能。

    REPLICATION 策略是一直启用的,而其它的内置策略在默认的情况下是禁用的。

    类似于HDFS存储策略,纠删码策略是设置在目录上的,当一个文件被创建,它继承离它最近的祖先目录的EC策略。

    目录级别的EC策略只影响在该目录下创建的新文件,一旦一个文件已经被创建,它的纠删码策略可以被查询,但是不能改变,如果一个纠删码文件被重命名到一个不同的EC策略的目录中,该文件会保留它之前存在的EC策略,转换一个文件到不同的EC策略需要重写它的数据,重写数据是通过拷贝文件(比如:通过distcp)而不是重命名文件。

    我们允许用户通过XML文件的方式去定义它们自己的EC策略,该XML文件必须要有下面的3部分:

        1) layoutversion:  表示EC策略文件格式的版本。

        2) schemas: 这个包括所有用户定义的EC约束

        3) policies:  这个包括所有用户定义的EC策略,每个策略由schema id和条带单元的大小(cellsize)构成,

    在hadoop conf目录中有一个名称叫 user_ec_policies.xml.template的样本EC策略的XML文件。

     因特尔 ISA-L 代表因特尔智能存储加速库, ISA-L 是为存储应用程序优化的底层函数开源的集合,它包括在 AVX 和 AVX2 指令集上快速的块  Reed-Solomon 类型的纠删码优化,HDFS纠删码可以利用ISA-L去加速编解码计算,ISA-L支持大多数开源的 *** 作系统,包括linux和windows,ISA-L默认是不启动的,有关如何启动ISA-L,请看下面的说明。

    纠删码在集群的CPU和网络方面提出了额外的要求。

    编码和解码工作会消耗HDFS客户端和DataNodes上额外的CPU。

    纠删码文件也分布在机架之间,用于机架容错,这意味着当读取和写入条带文件,大多数 *** 作是在机架外的,因此,网络对分带宽非常重要的。

    对于机架容错来说,至少拥有与配置的EC条带宽度相同的机架数量也是很重要的,对于EC策略RS (6,3),这意味着至少要有9个机架,理想的情况下要有10或者11个机架用于处理计划内和计划外的停机。对于机架数量少于条带宽度的集群,HDFS不能维护机架容错,但是仍然会分散条带文件到多个节点为了节点级别的容错。

    默认情况下,所有内置的纠删码策略是被禁用的,但是定义在参数dfs.namenode.ec.system.default.policy中的除外,该策略在默认情况下是启用的。集群管理员可以根据集群的大小和希望的容错属性使用命令hdfs ec [-enablePolicy -policy <policyName>]启用一组策略;例如,对于一个拥有9个机架的集群,类似RS-10-4-1024k 这样的策略不能达到机架级别的容错,而策略RS-6-3-1024k 或者RS-3-2-1024k更适合。如果管理员只关心节点级别的容错,在至少有14个DataNodes的集群中策略RS-10-4-1024k也是适合的。

    系统默认的EC策略可以通过参数‘dfs.namenode.ec.system.default.policy’ 来配置,在这种配置下,当命令 ‘-setPolicy’没有指定策略名称的参数时,默认的策略将会被使用。

    默认情况下,参数 ‘dfs.namenode.ec.system.default.policy’ 的值为“RS-6-3-1024k”,使用Reed-Solomon和XOR实现的编解码器可以使用客户端和DataNode节点指定如下的关键字配置:io.erasurecode.codec.rs.rawcoders用来指定默认的RS编解码器,io.erasurecode.codec.rs-legacy.rawcoders用于指定legacy RS编解码器,io.erasurecode.codec.xor.rawcoders用于指定XOR编解码器;用户也可以使用类似关键字io.erasurecode.codec.self-defined-codec.rawcoders来配置自定义的编解码器。这些关键字的值是带有回退机制的编码器名称的列表。这些编解码器工厂以指定的配置的值有序的被加载,直到一个编解码器被成功的加载,默认的RS和XOR编解码器配置更喜欢本地实现,而不是纯java实现;RS-LEGACY没有本地编解码器实现,因此默认的只能是纯java的实现;所有这些编解码器都有纯java的实现;对于默认的RS编解码器,它也有一个本地实现,利用英特尔 ISA-L库提高编解码器性能;对于XOR编解码器,也支持利用英特尔 ISA-L库提升编解码的性能的本地实现;请参阅“Enable Intel ISA-L”获取更详细的信息。默认的RSLegacy的实现是纯java的,默认的RS和XOR是使用了因特尔ISA-L库本地实现的,在DataNodes上的纠删码后台恢复工作也可以使用下面的参数被调优:

     1) dfs.datanode.ec.reconstruction.stripedread.timeout.millis --条带读取超时时间,默认值 5000 ms

     2) dfs.datanode.ec.reconstruction.stripedread.buffer.size --读取服务的缓存大小,默认值 64K

     3) dfs.datanode.ec.reconstruction.threads -- DataNode用于后台重构工作的线程数量,默认值 8 个线程

     4) dfs.datanode.ec.reconstruction.xmits.weight -- 与副本块恢复 相比,EC后台恢复任务使用的xmits 的相对权重,默认值0.5,设置它的值为0去禁用计算EC恢复任务的权重,也就是说,EC任务总是1 xmits。通过计算出读数据流的数量和写数据流的数量的最大值来计算出纠删码恢复任务的xmits。例如,如果一个EC恢复任务需要从6个节点读取数据,往2个节点写入数据,它拥有的 xmits 是max(6, 2) * 0.5 = 3,复制文件的恢复任务总是计算为1xmit,NameNode利用dfs.namenode.replication.max-streams减去DataNode上总的xmitsInProgress(合并来自副本文件和EC文件的xmits) ,以便调度恢复任务到这个DataNode。

    HDFS利用因特尔ISA-L库去提高默认的RS本地实现的编解码器的编解码计算速度,开启并使用英特尔ISA-L库,需要3步:

        1)构建ISA-L库,请参阅官方的网站 “ https://github.com/01org/isa-l/ ” 获取详情信息。

        2)构建带有ISA-L支持的Hadoop,请参阅源码中BUILDING.txt文件中的 “Build instructions for Hadoop”中的“Intel ISA-L build options”部分。

        3)使用-Dbundle.isal拷贝 isal.lib 目录中的内容到最终的tar文件中。

    使用该tar文件部署Hadoop,确保ISA-L是在HDFS客户端和DataNodes端是可用的。为了验证ISA-L能够被Hadoop正确的检测到,运行命令  hadoop checknative来验证。

    HDFS提供了EC的子命令用于执行纠删码相关的管理命令。

    hdfs ec [generic options] [-setPolicy -path <path>[-policy <policyName>] [-replicate]] [-getPolicy -path <path>] [-unsetPolicy -path <path>] [-listPolicies] [-addPolicies -policyFile <file>] [-listCodecs] [-enablePolicy -policy <policyName>] [-disablePolicy -policy <policyName>] [-help [cmd ...]]

    下面是关于每个命令的详情:

    [-setPolicy -path <path>[-policy <policyName>] [-replicate]]

    在指定的目录的路径上设置纠删码策略。

    path:HDFS中的目录,这是一个强制的参数,设置一个策略只影响新创建的文件,不影响已经存在的文件。

    policyName:在这个目录下的文件上使用的纠删码策略,如果配置了参数‘dfs.namenode.ec.system.default.policy’,这个参数可以被省略,这时路径的EC策略将会被设置成配置文件中的默认值。

    -replicate:在目录上应用指定的REPLICATION策略,强制目录采用3副本复制方案。

    -replicate 和-policy <policyName>是可选的参数,它们不能同时被指定。

    [-getPolicy -path <path>]

    获取在指定路径上目录或者文件的纠删码策略的详情。

    [-unsetPolicy -path <path>]

    取消之前使用setPolicy 在目录上设置的纠删码策略。如果目录是从祖先中继承的纠删码策略,unsetPolicy 是一个空 *** 作,即在没有明确设置策略的目录上取消策略将不会返回错误。

    [-listPolicies ]

    列出所有在HDFS中注册的纠删码策略,只有启用的策略才能使用setPolicy 命令。

    [-addPolicies -policyFile <file>]

    添加一个纠删码策略的列表,请参阅模板策略文件etc/hadoop/user_ec_policies.xml.template,最大的条带单元大小被定义在属性 ‘dfs.namenode.ec.policies.max.cellsize’ 中,默认值是4MB,当前的HDFS中总共允许用户添加64个策略,被添加的策略ID的范围是64~127,如果已经有64个策略被添加,再添加策略将会失败。

    [-listCodecs]

    获取系统中支持的纠删码编解码器和coder列表。一个coder是一个编解码器的实现,一个编解码器可以有不同的实现,因此会有不同的coder,编解码器的coders采用后备的顺序被列出。

    [-removePolicy -policy <policyName>]

    移除一个纠删码策略。

    [-enablePolicy -policy <policyName>]

    启用一个纠删码策略

    [-disablePolicy -policy <policyName>]

    禁用一个纠删码策略。

    由于大量的技术挑战,在纠删码文件上不支持某些HDFS的写 *** 作,比如hflush, hsync 和append *** 作。

    在纠删码文件上使用append()将会抛出IOException。

    在DFSStripedOutputStream 上执行hflush() 和hsync()是空 *** 作,因此,在纠删码文件上调用hflush() 或者hsync()不能保证数据被持久化。

    客户端可以使用 StreamCapabilities  提供的API去查询一个OutputStream 是否支持hflush() 和hsync(),如果客户端渴望数据通过hflush() 和hsync()持久化,当前的补救措施是在非纠删码目录中创建3副本文件,或则使用FSDataOutputStreamBuilder#replicate()提供的API在纠删码目录中创建3副本文件。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11729444.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-18
下一篇 2023-05-18

发表评论

登录后才能评论

评论列表(0条)

保存