大数据分析工程师入门7--HDFS&YARN基础

640?wx_fmt=png



导语



HDFS和YARN是大数据生态的基础组件,不过,因为其处于数据分析架构体系的底层,通常我们很少能感受到它们的存在。


但是我们必须要了解它们,因为在某些场景下,我们依然会接触到它们。了解他们并熟悉怎么使用,是大数据分析师必备的技能之一。


首先,还是让我们来回答经典的三个问题:


  • 为什么要讲HDFS和YARN?

  • 本节课程的目标是什么?

  • 本文的讲解思路是?



为什么要讲HDFS和YARN?



作为大数据生态的基石,HDFS和YARN支撑着所有上层的组件,其重要性不言而喻。HDFS作为分布式存储的基础解决方案,为所有的其他组件提供高可用、稳定而高效的数据存储服务。


而YARN作为资源的管理与调度框架,负责整个分布式集群资源的分配、动态调整、资源调度等,从而实现资源的高利用率。


鉴于这两大组件如此重要,我们必须要了解其基本原理和概念,一方面可以对工作中排查问题有比较大的帮助,另一方面方便我们与他人沟通交流。


 

本节课程目标是什么?



本文主要会从实用的角度出发,结合实际的工作经验,讲解工作中经常提及的HDFS和YARN的核心概念和常用操作。


本文不会去深入剖析讲解其内部的工作原理,更多地是教大家一些工作中实用的技巧。



本文的讲解思路是?




第1部分,HDFS核心概念,讲解必须了解的HDFS各组成部分及作用,方便与他人沟通交流。


第2部分,HDFS常用命令,讲解工作中常用的HDFS命令。


第3部分,HDFS WebUI使用,将教大家怎么使用HDFS的Web页面。


第4部分,YARN核心概念,讲解YARN的基本结构和各组件作用。


第5部分,YARN常用命令,讲解YARN常用操作指令。


第6部分,YARN Web界面使用,讲解如何杀死一个作业、如何查看执行日志等。




0 1

HDFS核心概念


1.1 HDFS


HDFS(Hadoop Distributed File System),是Hadoop的开源分布式文件系统,其设计思想源于谷歌的GFS(Google File System)论文,是GFS的开源实现。HDFS具有非常多的优势,使其成为大数据生态最重要的基础分布式存储组件。


其优势如下:


a.容量大,可扩展性强。由于节点众多,HDFS可以存储大量的数据,并且可以通过增加子节点的方式,增加HDFS的容量,从而存储更多的数据。


b.高容错性。数据自动保存多个副本,某个副本丢失后,集群会自动恢复,自动补上丢失的副本。HDFS还提供了回收站功能,可以有效避免误删。


c.高可用性。HDFS拥有两个主节点,一个active节点,一个standby节点。当active节点异常关闭后,standby节点可以迅速切换为active,继续提供服务。


d.高稳定性。HDFS非常的稳定,长时间运行依然如此,单个从节点宕机,不会对HDFS造成任何影响。


e.低成本。HDFS可以构建在廉价的主机上,和商用的存储方案相比,成本非常低廉。


当然,HDFS也有一些自己的劣势:


a.不适合存储小文件。较多地存储小文件(低于block大小的文件),会消耗NameNode比较多的内存。另外,分布式存储的特性,也会导致小文件的读取效率不高。


b.不适合低延时访问。HDFS是为大数据量读写的场景设计的,牺牲低延时换来高吞吐率,因此比较适合读写吞吐率高的场景,不适合要求快速响应的场景。


c.不支持并发写入,对修改不友好。并发写入在分布式场景下实现比较困难,会使整个模型变得非常复杂,因此HDFS放弃了这一特性。另外,HDFS只允许追加和覆盖文件,不允许修改已有文件。

 

1.2 NameNode


HDFS的主节点,负责维护文件系统树,管理文件、目录、块等信息以及HDFS命名空间,协调并管理所有从节点,负责处理和调度客户端的读写请求。


在HDFS2.0中,可以同时存在两个NameNode,其中一个是active状态,负责上述所提到的功能,另一个是standby状态,只负责同步active节点的数据,并在active节点宕掉时,切换为active状态并继续提供服务。


1.3 DataNode


HDFS的从节点,负责具体数据的存储,处理与客户端的交互,进行具体数据的读写操作。


因此,要额外关注DataNode的磁盘使用情况和损坏情况,出现故障要及时修复,否则可能会导致数据的意外丢失。另外,由于会进行大量读写操作,因此建议DataNode节点主机,采用多磁盘单盘挂载的方式,可以提高数据的读写能力。


1.4 Block


Block(块)是HDFS的最基本存储单位,块是被切分出来的。对于一个大文件而言,为了提升其存储和读取的效率,会将其切分成N个小块,分别存储在不同机器上,这样读取时便可以从多台机器同时读取数据,极大地提高效率。


当然,这样做有利有弊,优势是效率提升了,劣势是增大了文件损坏的风险,丢失任意一个块,文件就会损坏。不过,这个可以通过下一节要讲的副本机制来保证其安全性。


HDFS默认的块大小为128M(2.7.3之前的版本默认值为64M),可以根据自己的应用情况来进行修改。


不过,如果设置过小会导致占用很多NameNode的内存。但是也不能过大,因为很多分布式计算框架,如MapReduce、Spark等,都是基于读取数据所包含的块的数量来设置partition或task的数量的。


块大小设置过大,那么块数量就会相应减少,task数量就会减少,单个task处理的数据就会变多,这样没有充分发挥分布式计算的并行优势。


1.5 Replication


副本(Replication)是HDFS提供的容错机制。


HDFS默认的副本数为3。副本机制的其中一个作用,就是解决上节中提到的文件损坏风险的问题。多个副本,保证了数据的安全性,丢失一个副本,文件也不会损坏。多个副本会存储在不同的机架上,进一步保证数据的安全性。


另外,多个副本也可以有效分摊读取压力,避免DataNode节点热点问题。


1.6 JournalNode


JournalNode的主要作用是负责两个NameNode之间的状态同步。前面讲到在正常运行的HDFS集群中,会有两个NameNode,一个是Active节点,另一个是Standby节点。


Active节点负责处理所有客户端的请求,维护文件系统树。而Standby负责和Active节点保持数据上的同步状态,以便Active节点挂掉后,可以迅速切换为Active并继续提供服务。


那么如何做到这一点呢?


这就不得不借助于JournalNode了。Active节点会把命名空间的每个改变,封装成一个record,写入JournalNode主节点。而Standby节点,会实时从JournalNode获取最新的改变,并将改变应用到自己的命名空间中。


这样,当Active节点意外挂掉后,Standby节点和挂掉前的Active节点的状态一致,便可以快速切换为Active状态,并继续提供服务。至于切换过程是怎么完成的,下小节讲到ZKFC时,会详细解释。


JournalNode集群,要求至少是3个节点,这样可以容忍1个节点失败。其节点数可以更多,但是最好是单数,方便快速选举出主节点。


1.7 ZKFC


ZKFC(ZKFailoverController),主要作用是监控NameNode的健康状况,并实现Active状态的自动转移。


ZKFC进程通常和NameNode进程运行在同一台主机上,方便监控同一主机上的NameNode的健康状况。那么,ZKFC是如何完成Active状态的自动转移呢?


这和它的功能有很大关系,ZKFC有三个核心功能:


1) 健康监控。ZKFC会定期对本地的NameNode发起health-check的请求,如果NameNode及时正确响应,那么ZKFC就认为节点是健康的。否则,将其标记为不健康。


2) ZooKeeper会话管理。当本地NameNode是健康状态时,ZKFC在ZooKeeper中持有一个session。 如果本地NameNode又正好处于Active状态,那么ZKFC还会持有一个"ephemeral"的节点作为锁,一旦本地NameNode不再健康,那么会话失效,这个锁节点也会被自动删除。


3) 基于ZooKeeper的选举。如果本地NameNode是健康的,并且ZKFC发现没有其他节点持有那个独占锁,它将自己尝试获取锁。 如果成功,那么它“赢得了选举”,并负责运行Failover以使其本地NameNode处于Active状态。 Failover的过程是:首先,必要时对先前的Active NameNode进行隔离,然后本地NameNode转换为Active状态。


所以,通过这3个功能,便可以实现Active状态的自动转移。


有一点需要注意的是,配置失败自动转移,需要关闭集群,所以在一开始启动集群前就要设置并测试好,否则关停服务中的HDFS集群,代价是比较大的。具体设置方法详见官方文档,这里就不展开讲了。


1.8 HA


HA(High Availability),即高可用。


讲完上述几个部分后,相信你对HDFS的高可用原理已经比较熟悉了。通过NameNode、JournalNode、ZooKeeper、ZKFC四个进程的配合,实现了HDFS集群的高可用性。关于HA,有几点需要特别说明下:


a.高可用性必须事先检测。在集群搭建时,必须检测极端情况下的高可用性,避免由于配置失误或其他原因,导致高可用性失效。


b.针对NameNode、JournalNode、ZooKeeper、ZKFC四个进程,需要进行监控,并且由监控进程将失败进程自动拉起。虽然这些服务,都能容忍部分进程挂掉,但是如果长时间不拉起,一旦再有进程失败,可能就会导致服务异常。


c.不要过分依赖HA。定期备份NameNode数据还是很有必要的,以应对突发的极端异常情况。


1.9 Trash


Trash是HDFS的回收站,HDFS会为每一个用户创建一个回收站目录:

/user/用户名/.Trash/。


当用户删除文件或目录时,并不是直接删除而是移动到了对应用户的回收站目录下。该目录下的文件会保留一段时间,之后自动删除。保留时间长短可以配置,单位是分钟,如果设置为0,表示不开启回收站功能,具体配置内容如下所示:


 
 
//修改core-site.xml	
<property>	
    <name>fs.trash.interval</name>	
    <value>1440</value>	
</property>


这个功能务必要打开,因为它可以有效避免误删数据,避免错误操作带来的严重后果。我们在删除数据时,也最好不要跳过回收站,这样即使出现失误,也还有挽救的可能,不然数据是无法找回的。



0 2

HDFS常用命令


HDFS提供了非常丰富的shell命令,拥有强大而细致的功能。但是,对于初级大数据分析师来说,平时工作很少会接触到HDFS,下面我们只挑工作中使用频率最高的几个命令来讲一下。


2.1 ls


该命令主要用于查看文件夹下的文件列表及文件的各种属性,如访问权限、所属用户及组、最后修改时间等,是使用频率非常高的命令之一。通常ls命令会配合选项使用,常用选项为-h和-R,其中-h表示以方便人类理解的形式显示文件大小,-R表示递归遍历下面的子目录。


具体示例如下所示:

 
 
# 命令使用	
hdfs dfs -ls [-h] [-R] <path>	
# 示例	
~$ hdfs dfs -ls -h -R /test/temp	
-rw-r--r--   3 hadoop supergroup     6.7 K 2019-06-05 21:07 /test/temp/a.csv	
-rw-r--r--   3 hadoop supergroup     9.9 M 2019-06-05 21:07 /test/temp/b.txt	
drwxrwxr-x+  - hadoop supergroup         0 2019-06-05 21:08 /test/temp/cc	
-rw-r--r--   3 hadoop supergroup       635 2019-06-05 21:08 /test/temp/cc/d.sql	
-rw-r--r--   3 hadoop supergroup    27.8 M 2019-06-05 21:08 /test/temp/cc/e.log


返回结果的第一列,表示是文件或目录及其访问权限,具体含义和linux的ls -l命令设计一致,不了解的同学可以自行百度一下,这里就不再赘述了。不过,细心的同学可能已经发现了,返回结果的第三行,第一列的结尾有个加号("+"),这是表示这个目录被赋予了额外的ACL权限,ACL不属于基础课程的内容,想了解的同学可以自己看下官方文档,这里就不细讲了,只需知道加号的含义即可。


返回结果的第2列到第8列的含义,依次为文件的副本数、所属用户、所属用户组、文件的大小、最后修改日期、最后修改时间、文件或目录名。


2.2 du


该命令通常用于查看文件或目录的汇总大小,工作中常用它来估算输入数据量的大小。它有两个选项,-h和-s,-h表示以方便人类理解的方式展示,-s表示对目标目录下面的所有文件和子目录进行汇总,而不是逐个显示其大小。具体示例如下:


 
 
# 命令使用	
hdfs dfs -du [-s] [-h] <path>	
# 示例	
~$ hdfs dfs -du -s -h /test/temp	
37.7 M  /test/temp	
	
~$ hdfs dfs -du -h /test/temp	
6.7 K   /test/temp/a.csv	
9.9 M   /test/temp/b.txt	
27.8 M  /test/temp/cc


可以看出,加上-s后,只显示目标目录的汇总大小。


2.3 get


该命令通常用于将HDFS的文件或目录下载到本地,工作中常用来导出HDFS上的数据。


具体示例如下:

 
 
# 命令使用	
hdfs dfs -get <hdfs_path> <local_path>	
# 示例	
~$ hdfs dfs -get /test/temp/a.csv .


需要注意的是,本地目录必须存在,并且执行该命令的用户必须对其有写权限。示例命令中的"."表示执行命令时的当前目录。


2.4 put


该命令常用于将本地文件或目录上传至HDFS,这是把本地文件上传到HDFS上最简便的途径。如果要上传的文件在HDFS上已经存在同名文件则会报错,这时你可以加上-f选项,会直接覆盖目标文件。


但是覆盖发生后将无法撤销,因此,请谨慎使用此选项。


 
 
# 命令使用	
hdfs dfs -put [-f] <local_path> <hdfs_path>	
# 示例	
~$ hdfs dfs -put /data/f.json /test/temp



2.5 rm


该命令用于删除文件或目录,工作中常用来删除中间结果、临时文件、没用的文件和目录。它可以搭配选项-r、-f、-skipTrash来使用,-r表示递归删除,-f表示忽略警告或错误强制删除,-skipTrash表示跳过回收站,直接彻底删除。使用-skipTrash时一定要谨慎,因为一旦误删,无法挽回。


使用rm命令时有以下三点建议:


1.在删除之前最好先用ls看下要删除的内容,尤其是使用-r时,一定要看下子目录的内容是否也是要删除的,确认无误后再删除。


2.如果使用-f参数,就不要使用-skipTrash。因为两个参数一起使用,一旦操作失误,一点后悔的余地都没有了。


3.尽量不要使用-skipTrash,除非你的删除操作是为了释放出足够的存储空间。


 
 
# 命令使用	
hdfs dfs -rm [-f] [-r] [-skipTrash]	
# 示例	
~$ hdfs dfs -rm -f /test/temp/f.json



2.6 cat/tail


cat命令通常用于查看文件内容,一般会配合linux管道和head命令使用,查看文件开头的内容。与之相对应的是tail命令,可以查看文件末尾的1KB内容。

 
 
# 命令使用	
hdfs dfs -cat <file_path> | head 	
hdfs dfs -tail <file_path>	
# 示例	
~$ hdfs dfs -cat /test/temp/a.csv | head -n 20 //查看文件前20行	
~$ hdfs dfs -tail /test/temp/a.csv



2.7 help


该命令用于返回其他命令的使用说明。这个命令非常好用,当你忘记某个命令的选项有哪些,分别是什么含义,是大写还是小写时,使用这个命令,可以快速获得相关信息。

 
 
# 命令使用	
hdfs dfs -help <cmd>	
# 示例	
~$ hdfs dfs -help put	
-put [-f] [-p] [-l] <localsrc> ...<dst> :	
  Copy files from the local file system intofs. Copying fails if the file already	
  exists, unless the -f flag is given.	
  Flags:	
 	
  -p  Preserves access and modificationtimes, ownership and the mode.	
  -f  Overwrites the destination if italready exists.	
  -l  Allow DataNode to lazily persistthe file to disk. Forces	
         replicationfactor of 1. This flag will result in reduced	
         durability. Usewith care.	




0 3

HDFS WebUI


3.1 主界面各部分介绍


640?wx_fmt=png


上图是Active NameNode的Web主界面,图中标记1表示总览页,点击标记2位置可以查看从节点的状态,点击标记3位置可以查看启动进度,标记4是工具页面(在下面3.3会详细讲),通过标记5的位置可以看出当前主机是否为活跃的NameNode,标记6可以看出HDFS的版本号,标记7可以查看HDFS的总容量、已使用容量和剩余容量等。


下图为Standby NameNode的Web主界面,除了红框位置信息不同外,其余信息是一致的,但是值得注意的是Standby NameNode的Web页面是不能浏览文件系统的,在3.3我们会解释下具体原因。


640?wx_fmt=png


3.2  查看DataNode节点状态


在3.1我们提到,点击页面上的Datanodes可以看到如下界面:


640?wx_fmt=png


通常我们会用这个页面查看节点的健康状况、容量信息等。如下图为某个节点挂掉时的情况。


640?wx_fmt=png


所以,如果你的分析程序发生异常,你怀疑和DataNode的健康状况有关,你可以来这个界面检查下所有DataNode的健康情况。


3.3 浏览文件系统或查看日志


你可以通过点击Utilities,展开工具选项,标记1点击后会跳到浏览文件系统的页面,标记2可以查看HDFS相关进程的日志。


640?wx_fmt=png


这里要说明一点的是,只能在Active NameNode的Web界面上浏览文件系统,而不能在Standby NameNode的Web界面上浏览。


这是因为Standby节点是同步Active节点的文件系统信息,这样就可能存在一定的延迟,也就是说Standby节点上看到的文件系统内容可能不是最新的,所以是不能开放浏览的,如果你尝试在Standby NameNode的Web界面上浏览文件系统会看到以下提示。


640?wx_fmt=png



0 4

YARN核心概念



YARN是Yet Another ResourceNegotiator的缩写。


YARN是一个通用的资源管理系统与调度平台,它将CPU、内存、磁盘、网络等资源进行统一管理与拆分,以容器的形式,为上层应用提供统一的资源服务。其主要包含四大组件,分别为ResourceManager、NodeManager、ApplicationMaster、Container。


它们的关系如下图所示,接下来我们会做详细讲解。


640?wx_fmt=png

(图片来自Hadoop官网)


4.1 ResourceManager


ResourceManager是YARN集群的Master进程,主要负责整个集群资源的统一管理和分配,当我们提交一个作业给YARN,实际上就是提交给了ResourceManager,并由它协调分配相应的资源,这样程序才能得以运行。


所以,ResourceManager是比较核心的进程,NodeManager和ApplicationMaster都要通过与之交互,完成资源的申请、分配和使用。鉴于其核心地位,与NameNode类似,ResourceManager也是有HA的,以保障它不会出现单点故障,可以长时间稳定运行,在4.3我们会再详细讲解。


4.2 NodeManager


NodeManager是YARN集群的Slave进程,主要负责所在节点的资源和任务管理,它是每台机器的框架代理,管理着容器的生命周期,监视其资源使用情况(CPU,内存,磁盘,网络)并将其报告给ResourceManager。


ResourceManager和NodeManager共同构成了数据计算框架,使YARN具备了资源管理和协调能力。


4.3 HA


ResourceManager的HA(HighAvailability)实现,要比NameNode简单得多,与其相比有两点重要的不同:


1) 依赖比较少。ResourceManager的HA只依赖ZooKeeper集群,而NameNodeHA还依赖JournalNode和ZKFC。


2) 可以有多个Standby节点。NameNode只能有一个Standby节点,而ResourceManager可以有多个。


其实现原理大致为:


通常情况下,会有一个Active节点和多个Standby节点同时运行,Active节点在运行期间,会将应用提交相关数据持久化到ZooKeeper中,当Active节点挂掉后,会由嵌入在ResourceManager进程内的基于ZooKeeper的ActiveStandbyElector从正常运行的多个Standby节点中选举出下一个Active节点,然后读取ZooKeeper中的应用提交信息,并接收NodeManager的汇报信息,重建上个Active节点挂掉前的运行状态。


下图为Hadoop官网给出的HA架构图。


640?wx_fmt=png

(图片来自Hadoop官网)


4.4ApplicationMaster&Container


ApplicationMaster实际上是特定计算框架的一个实例,每种计算框架都有自己的ApplicationMaster实现,负责与ResourceManager协商资源,并和NodeManager协同来执行和监控Container。


Container是一个动态资源分配单位,它将内存、CPU、磁盘、网络等资源封装在一起,从而限定每个任务使用的资源量。ApplicationMaster和Container组成了分布式计算的框架基础,分布式计算的代码就是在这二者进程内执行。


4.5 Queue


Queue,是队列的意思。YARN接管了计算集群的所有资源,汇聚成一个巨大的计算资源池,统一进行管理和调度,但是这样颗粒度就会比较粗,所以队列的作用就是将这些资源划分为不同大小的多个资源池,以方便进行更加细粒度的管控和资源隔离。


通过队列,我们可以控制可使用的最大资源、并行的应用数等,并实现不同类别应用的隔离,如短时作业和常驻作业,确保资源有较高的利用率和隔离性。



0 5

YARN常用命令


5.1 list


该指令常用于查看作业列表,通常会配合-appStates使用,过滤出特定运行状态的应用。


如果不指定,则默认输出SUBMITTED, ACCEPTED, RUNNING三种状态的应用列表。输出结果包括Application-Id(应用ID),Application-Name(应用名称),Application-Type (应用类型),User(提交用户),Queue(队列),State(当前状态),Final-State(最终状态),Progress(进度),Tracking-URL(详细信息链接)。


 
 
# 命令使用示例	
yarn application -list -appStates RUNNING



5.2 kill


该命令常用于杀死一个特定的应用,需要指定应用的ApplicationID,可以通过上述list命令找出要杀死的应用的ApplicationID。

 
 
# 命令使用示例	
yarn application -kill application_1559424668670_13394

 


0 6

YARN WebUI


6.1 各组成部分


640?wx_fmt=png


YARN的界面包含内容较多,我们只对常用的地方做下标注。点击标记1可以跳转到当前这个界面,标记2的位置可以跳转到从节点界面,可以查看相关从节点的健康情况和资源使用情况,标记3展示的是队列信息,标记4展示的是队列内的应用列表,点击标记3中的队列名,标记4位置会过滤出对应队列内的应用列表。


6.2 查看从节点状态


点击6.1中截图的标记2位置,会进入下面的界面,值得关注的是红框标注的列,空白表示健康,如果有错误提示,需尽早联系运维处理故障点。


640?wx_fmt=png


6.3 搜索指定作业


640?wx_fmt=png


可以在上图红框里输入关键字,过滤出你关心的作业,之后执行其他操作,如查看日志等。


6.4 杀死作业



640?wx_fmt=png


640?wx_fmt=png


依次点击上面两个图中的123位置,可以杀死一个正在执行的作业,该操作方式要比命令行方便得多。杀死作业前,请确认不会对其他应用造成影响。


6.5 查看日志



640?wx_fmt=png


点击红框位置,可以跳转到查看日志界面。日志分为stdout和stderr两种,分别对应标准输出和标准错误输出。


640?wx_fmt=png


日志内容有时非常多,从头看起非常耗时,不容易定位问题。而我们的程序通常报错后就会退出,不再继续写日志,因此错误信息往往就在末尾。这里教给大家一个小技巧,如何查看日志的末尾。非常简单,先点开日志,然后修改地址栏url的最后一个参数start,将其值0改为负值即可,负值的大小表示查看末尾的多少字节,如-3000表示查看末尾3000字节的内容。如下面两个图所示,请关注箭头所指位置。


640?wx_fmt=png


640?wx_fmt=png


6.6 跟踪作业执行细节


640?wx_fmt=png


点击红框位置,可进入对应的作业执行页面,查看作业的执行细节。


6.7查看目前生效的配置


640?wx_fmt=png


点击红框位置后,可以跳转到配置信息页面,如下图所示。这个页面展示的是目前生效的配置,并标注了配置的来源,非常实用。


640?wx_fmt=png



0 7

总结


本文从偏实用的角度,结合多年工作经验,重点讲解了HDFS和YARN需要了解的重要概念、常用命令及Web界面使用方法,应该基本可以满足日常工作需要了。


但是,应对面试还远远不够,因为很多面试官会喜欢问有关基础理论和运行原理的问题,尽管这些内容对于大数据分析师来说,实际工作中通常用不上。因此,如果是准备面试,建议还是重点复习下HDFS和YARN的面试题。


如果大家在这方面的需求比较多,请在文章下面留言,我们也会考虑帮大家整理一篇相关的面试题合集。


-end-

 

640?wx_fmt=png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据与智能

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值