HBase系列(三)、读写原理,Flush刷写,HFile Compact合并,Region Split切分

【HBase-读写流程】HBase的读写流程与内部执行机制 1、客户端发起写入数据的请求,然后首先要连接 zookeeper,通过 zookeeper 去找到 HBase 中的 meta 文件对应的 region 所对应的 regionserver 的地址,连接 meta 文件所在的 regionserver,通过要写入数据的 rowkey,找到 rowkey 对应的 region(底层是根据 region 的范围去寻找的),然后找到 region 对应的 regionserver 的地址。 阅读详情

目录

写原理

读原理

Flush流程

HFile合并流程

Region拆分流程

数据删除时间


HBase系列:


写原理

客户端请求HBase写请求(PUT,DELETE)流程如下:

  1. Client 先访问ZK中的/hbase/meta-region-server 这个Znode,获取 hbase:meta 表所在的RegionServer;
  2. ZK返回META表所在的RS01信息;
  3. Client 访问META所在的RS01,查询hbase:meta;
  4. RS01将HBase元数据信息meta返回给客户端;
  5. Client 将得到的元数据信息进行缓存,之后再有读取请求时可以免去步骤1~5节约时间和资源;
  6. Client 向目标表所在的RS02发送写请求(PUT/DELETE);
  7. RS02将数据顺序追加到WAL(HLog)内;
  8. RS02将数据写入对应的Region内的MemStore,数据会在MemStore 进行排序;
  9. RS02向Client 返回应答信息完成写操作;
  10. 当满足Flush策略时,memstore内的数据会被刷写至HFile内;

读原理

客户端请求HBase读请求(GET)流程如下: 前面1~5步骤和写请求一样。

  1. Client 先访问ZK中的/hbase/meta-region-server 这个Znode,获取 hbase:meta 表所在的RegionServer;
  2. ZK返回META表所在的RS01信息;
  3. Client 访问META所在的RS01,查询hbase:meta;
  4. RS01将HBase元数据信息meta返回给客户端;
  5. Client 将得到的元数据信息进行缓存,之后再有读取请求时可以免去步骤1~5节约时间和资源;
  6. Client 向目标表所在的RS02发送读请求(GET);
  7. 从BlockCache(块缓存),MemStore 和 StoreFile(HFile)中查询目标数据,然后根据RowKey和时间戳进行数据合并;
  8. 将从StoreFile(HFile)中读到的数据缓存到BlockCache内供下次查询时使用,免去再次读取文件的磁盘IO消耗;
  9. 将合并后的结果返回给客户端;

注意:

  • 这里并不是先读内存,如果内存没有该数据再读磁盘,而是同时查询内存(BlockCache,MemStore)以及磁盘(StoreFile)。这样做的原因是当相同的rowkey在StoreFile文件内的数据时间戳大于MemStore中的时间戳时,如果先读MemStore的话会给客户端返回一个旧的数据,因此需要同时读内存和磁盘里的数据,然后根据rowkey为主键,以timestamp为版本进行数据合并;
  • 同时,在读磁盘的时候会将磁盘中的HFile缓存到BlockCache内,这样的话在下一次访问该HFile时就可以先到BlockCache中拿了,如果BlockCache内没有该文件,再去StoreFile中取。这里不必担心万一缓存到BlockCache之后又修改了该rowkey的数据会不会与BlockCache内的数据不一致,因为当数据被修改之后再次读取时:
    • 如果在此期间没有触发flush,该数据会在MemStore内,下次读取数据时会将BlockCache和MemStore中的该rowkey的数据进行合并;
    • 如果在此期间触发了flush,新的数据会在StoreFile中另一个新的HFile内,此时客户端再次请求读该RowKey的数据时会同时访问BlockCache内的包含旧版本数据的HFile以及StoreFile中的新HFile进行数据合并,然后会再将新的HFile缓存至BlockCache;
  • 也即是说每次读HBase时,如果该数据不在内存中,都会产生一次磁盘IO,而写数据是直接追加写WAL和内存,因此HBase是写比读更快。

Flush流程

上面多次提到了Flush刷写机制,表示的就是将内存中的MemStore数据持久化到HDFS内,即可以避免内存压力过大又可以保证数据安全,我们知道一个Region内包含多个列族,即在同一个Region内的每个Store表示了不同的列族,而每次Flush都会将MemStore持久化到HDFS内的一个HFile中,因此一个Store的数据最终会落到很多HFile中。

MemStore触发Flush刷写的条件如下,基本上就是按时间和容量:

  1. 当Region内某个MemStore 的大小达到了参数( hbase.hregion.memstore.flush.size)的值(默认值 128M),该Region内所有 MemStore 都会刷写;
  2. 当MemStore 的大小达到了公式 [hbase.hregion.memstore.flush.size(默认128MB) * hbase.hregion.memstore.block.multiplier(默认4)] 时,会阻止继续往该MemStore中写数据;
  3. 当 RegionServer 中 MemStore 的总大小达到公式[java_heapsize * hbase.regionserver.global.memstore.size(默认值 0.4)*hbase.regionserver.global.memstore.size.lower.limit(默认值 0.95)] 时,Region会按照其所有MemStore 的大小顺序(由大到小)依次进行刷写。直到 该RegionServer 中所有 MemStore 的总大小减小到上述值以下。
  4. 当 RegionServer 中 MemStore 的总大小达到公式[java_heapsize * hbase.regionserver.global.memstore.size(默认值 0.4)] 时,会阻止继续往该RegionServer 中所有MemStore中写数据;
  5. 通过配置参数(hbase.regionserver.optionalcacheflushinterval)进行自动刷写(默认 1 小时);
  6. 当 WAL 文件的数量超过最大数量 hbase.regionserver.max.logs,region 会按照时间顺序依次进行刷写,直到 WAL 文件数量减小到 hbase.regionserver.max.log 以下(该属性名已经废弃,现无需手动设置,默认值为 32)。

HFile合并流程

由于MemStore 每次刷写都会生成一个新的HFile,且同一个字段的不同版本(timestamp)和不同类型(Put/Delete)有可能会分布在不同的 HFile 中,因此查询时需要遍历很多 HFile文件。为了减少 HFile 的个数,以及清理掉过期和删除的数据,HBase会对StoreFile 进行Compaction(合并)。

Compaction 分为两种:

  • Minor Compaction:将临近的若干个较小的 HFile 合并成一个较大的 HFile,但不会清理过期和删除的数据;minor的过程一般较快,而且IO相对较低。当HFile数量达到参数(minFilesToCompact,默认3个)最低标准时,此命令才会触发,否则忽略本次操作。当待合并的HFile大小超过参数(maxCompactSize)时会将多的文件过滤掉不进行合并。
  • Major Compaction:将一个 Store 下的所有的 HFile 合并成一个大 HFile,并且会清理掉过期和删除的数据;由于此合并策略影响读写性能,因此一般在生产环境中,都会禁用major自动合并操作(参数hbase.hregion.majorcompaction设为0,默认是7天),只在空闲的时段手动或定时执行;

HBase会将队列中的HFile 按照文件年龄排序(older to younger),Minor Compaction总是从older HFile 开始选择,然后将选择出来的HFiles进行Minor Compaction:

  1. 如果该文件小于hbase.hstore.compaction.min.size(为memestoreFlushSize)则一定会被添加到合并队列中。
  2. 如果该文件大于hbase.hstore.compaction.max.size(Long.MAX_VALUE)则一定会被排除,这个值很大,一般不会有。
  3. 如果该文件的大小 小于它后面hbase.hstore.compaction.max(默认为10) 个HFile 的大小之和乘以一个ratio(配置项是hbase.hstore.compaction.ratio,默认为1.2),则该HFile 也将加入到minor compaction 中。如果他后面不足10个文件,那么也就是取他后面几个文件总和*ratio。

相关参数:

参数名配置项

默认值

含义
minFileToCompacthbase.hstore.compactionThreshold3最低合并HFile数量
maxFileToCompacthbase.hstore.compaction.max10最大合并HFile数量
minCompactSizehbase.hstore.compaction.min.sizememstoreFlushSize最小合并HFile文件大小
maxCompactSizehbase.hstore.compaction.max.sizeLong.MAX_VALUE最大合并HFile文件大小
majorCompactionhbase.hregion.majorcompaction7天

自动触发Major 间隔时间

Region拆分流程

默认情况下,每个 Table 起初只有一个 Region,随着数据的不断写入,Region 会越来越大然后自动进行拆分(Split)。刚拆分时,两个子 Region 都位于当前的 RegionServer,但出于负载均衡的考虑,HMaster 有可能会将某个 Region 转移给其他的 RegionServer。 

Region 拆分时机:

  1. 当1个region中的某个Store下所有StoreFile的总大小超过hbase.hregion.max.filesize(默认10GB),该 Region 就会进行拆分(0.94 版本之前)。
  2. 当1个region 中的某个 Store 下所有 StoreFile 的总大小超过公式Min(R^2 * "hbase.hregion.memstore.flush.size(默认128MB)",hbase.hregion.max.filesize(默认10GB)"),该 Region 就会进行拆分,其中 R 为当前 RegionServer 中属于该 Table 的Region个数(0.94 版本之后)。

可以看出,在新版之后,Region的拆分条件会默认从128MB不断的变大一直到10GB,这样就会导致某个表的不同Region内的数据不均衡的情况,因此在实际应用中都会提前设置预分区以及RowKey优化,避免因自动拆分导致的数据倾斜的情况。  

数据删除时间

当HBase中执行PUT修改相同RowKey的数据或者执行DELETE删除RowKey的数据时,我们可以通过命令查看到历史版本,那么什么时候这些过期数据和删除数据才会被删除呢?

其实失效数据在Flush和Compact都会被删除,但它们实现的地方不一样:

  • Flush刷写时:
    • Flush将MemStore内的数据进行合并然后去除小于该列族设置的VERSION号以前的数据,将剩余数据持久化到HFile;
    • 当执行DELETE时,Flush操作不会删掉MemStore里的该删除标记记录,只会删掉MemStore内该RowKey的在该删除标记操作的timestamp之前的操作,原因是可能在之前已持久化到HFile物理文件中也有该RowKey记录的历史版本,如果把内存里的删除标记也删除的话,再次查询就会将物理文件中的历史版本查出来,这样就不对了,因此Flush不会删除MemStore内的删除标记记录。
  • Compact合并时:
    • Compact命令会真正将内存和磁盘上的文件进行merge,去除小于该列族设置的VERSION号以前的数据,将剩余数据合并为一个新的HFile;

 

希望本文对你有帮助,请点个赞鼓励一下作者吧~ 谢谢! 

【信息科学与工程学】【数据科学】第一百二十二篇 大数据产品中的函数与算法01 它通常指。下面按照你给出的表格列💡 说明:下表中的"产品"以开源/主流商业组件为具象载体(Hadoop、Spark、Flink、Kafka、Hive、HBase、Iceberg、Atlas、Ranger、TensorFlow 等),它们共同构成一个完整的大数据产品家族;代码为实现示例,用于说明算法在工程系统中的落地方式。 阅读详情

相关推荐

【雷达信号处理实战】从原理到代码:脉冲多普勒(PD)处理全流程解析与MATLAB仿真

本文深入解析了脉冲多普勒(PD)雷达信号处理的核心原理与全流程。通过剖析多普勒效应、脉冲压缩与慢时间FFT等关键技术,并结合详细的MATLAB仿真代码,手把手指导如何从信号建模、回波模拟到最终生成距离-多普勒谱,实现运动目标的精确测距与测速,直观展示了相参积累带来的显著性能增益。

pca5navigator的博客 953

HBase2.x(十二)HBase 文件合并机制

MinorCompaction会将临近的若干个较小的 HFile 合并成一个较大的 HFile,并清理掉部分过期和删除的数据,有系统使用一组参数自动控制,Major Compaction 会将一个 Store 下的所有的 HFile 合并成一个大 HFile,并且会清理掉所有过期和删除的数据,由参数 hbase.hregion.majorcompaction控制,默认 7 天。(2)hbase.hstore.compaction.min(默认 3) 为 Minor Compaction 的最少文件个数。

weixin_45417821的博客 1579

用Python对CAPM和Fama French Three Factor model的初步学习

用Python对CAPM和Fama French Three Factor model的初步学习概述介绍建模与分析CAPMFama French Three-Factor Model总结 概述 本文主要使用CAPM(资本资产定价模型)和Fama French Three Factor model来评估中国股票市场的股票价格。 使用CAPM来选择投资组合,然后建立Fama法国三因素模型来评估投资组合...

weixin_43168138的博客 5458

HBase学习笔记(四)——HBase的flush、compact机制

在HBase中数据被写入 WAL 和 MemStore 后就可以说数据已经被成功写入到 Hbase 了。MemStore 中的数据达到一定的阈值,会被 Flush 成 HDFS 中的 HFile 文件。但是随着 Flush 次数的不断增多,HFile 的文件数量也会不断增多。从多个 HFile 文件中读取记录,将导致更多的 IOPS,这会使得读取时延不断增大。 Compaction 可以将一些 HFile 文件合并成为较大的 HFile 文件,也可以把所有的 HFile 文件合并成为一个大的 HFi

u011047968的专栏 2401

H265/HEVC视频分层码流分析语义元素解释

一、H265概述 H265/HEVC(Hight Efficiency Video Coding)是由ITU-T和ISO/IEC两大组织在H264/AVC的基础之上推出的新一代高效视频编码标准,主要为应对高清和超高清视频在网络传输和数据存储方面带来的挑战。上一篇文章对H264/AVC视频码流进行了详细的分析,本文继续从数据处理的角度对H265/HEVC视频码流进行详细分析。 二、H265分层结构 H265的分层结构与H264类似,分为视频编码层(VCL:Video Code Layer)和网络抽象层(NAL

weixin_43876729的博客 9431

Java对接(BSC)币安链 | BNB与BEP20的开发实践(三)水龙头 WEB3

这一节我们讲一个币安测试链如何获取到BNB、USDT等BEP20数字货币(水龙头)来让我们前期测试开发。如图:我们将创建的地址填入相应输入框,来获取到测试BNB以及其他BEP20数字币。发币可能需要交易等待,请耐心等待即可,交易完成后,币会到达您的地址内。上一节我们用代码来实现BNB转账、BEP20转账、链上交易监控。2.MetaMask(小狐狸)浏览器插件 🪜。使用EDGE浏览器可以在浏览器直接打开。使用Chrome浏览器,请使用🪜打开。基本工作就绪后,即可进行开发测试。3. 测试区块链浏览器 🪜。

大猩猩的专栏 2790

HBase Region管理(拆分+合并+负载均衡)

每个 RegionServer 包含多个 Region,而每个 Region 又对应多个 Store,每一个 Store 对应表中一个列族的存储,且每个 Store 由一个 MemStore 和多个 StoreFile 文件组成。StoreFile 在底层文件系统中由 HFile 实现,也可以把 Store 看作由一个 MemStore 和多个 HFile 文件组成。...

因上努力,果上随缘。但行好事,莫问前程。 2398

Python从0到100(二):Python语言介绍及第一个Pyhon程序

Python从0到100(二):Python语言介绍及第一个Pyhon程序。与C和Java比,Python的学习成本和难度曲线不是低一点,更适合新手入门,自底向上的技术攀爬路线。

拥有百余位万粉技术博主、200余位可合作代发博主,私域技术社群规模达千人,商务合作私信 5440

HBase篇(6)-HFile合并过程详解

简单地说Compaction 合并是指一个 region 的一个 store 中的一些 HFile 合为一个 HFile 的操作。过程是先从这些待合并的数据文件中读出 KeyValues...

wujiandao的专栏 2992

TC3XX - MCAL知识点(三十五):Tasking编译器下,Tc3xx的MCAL代码如何使用多核,多核中断、多核任务、多核外设之间的MCAL配置与代码例程

文章用于记录在裸机情况下使用多核Tc387芯片,如何高效运行以及正确的代码、工程属性、链接文件配置等问题,相互结合、相互影响的地方,以示后续使用记录。

梦想技术家 962

UI自动化控制PC端微信获取当前群聊的群友列表

在一个月前,某个群友在获取整个群的群友信息时遇到了一点问题: 对整个群进行群友数据获取经测试确实有点棘手,下面我将我的解决过程公布给大家。 基础教程详见: https://blog.youkuaiyun.com/as604049322/article/details/121391639 人工打开要抓取的群聊窗口后,首先获取微信窗口并点击聊天信息按钮: import uiautomation as auto auto.uiautomation.SetGlobalSearchTimeout(1) wechatWind

小小明-代码实体的专栏 3万+

Apache HBase 三个重要机制 Flush Compact Split

Flush机制 1.(hbase.regionserver.global.memstore.size)默认;堆大小的40% regionServer的全局memstore的大小,超过该大小会触发flush到磁盘的操作,默认是堆大小的40%, 而且regionserver级别的flush会阻塞客户端读写 2.(hbase.hregion.memstore.flush.size)默认:128M 单个r...

大数据流浪法师的学习笔记与分享 642

【图像拼接(Image Stitching)】关于【图像拼接论文精读】专栏的相关说明,包含专栏使用方法、阅读顺序、创新思路、文章汇总、源码汇总、数据集汇总等。总之,【图像拼接论文相关】看这一篇就够了

为什么会有这篇文章?因为专栏简介里写不下太多东西,只能通过这篇文章和大家交流,算是一个专栏阅读指南吧。说点心里话本来吧,我只想用优快云来记录自己学习【图像拼接】领域论文的过程,对每篇文章有个细致的理解,方便自己反复查阅。设置为付费也是因为涉及论文和本人其他项目需要,防止查重和其他问题,所以价格最开始设置的是专栏付费价格里最高的。起初,确实没有人看,一切也都平淡地度过着。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 4万+

【HBase】HBase入门详解(五)

(图片来源于网络,侵删) 一、Master、RegionServer的上下线以及Region的管理 Master上线 1) 从Zookeeper上获取唯一一个代表Active Master的锁,用来阻止其他Master成为真正的Master 2) 扫描Zookeeper上的/hbase/rs节点,获取当前可用的Region server列表 3) 和每个RegionServer通信,获得当...

Together 4441

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Hbase三个重要机制

Hbase三个重要机制 文章目录Hbase三个重要机制1、flush机制2、compact机制3、split机制 1、flush机制 1.(hbase.regionserver.global.memstore.size)默认;堆大小的40% regionServer的全局memstore的大小,超过该大小会触发flush到磁盘的操作,默认是堆大小的40%,而且regionserver级别的flu...

Mr_Yang888的博客 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Hbase compact以及split跟踪

  2017年06月30日 10:13:48 tom_fans 阅读数:847 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.youkuaiyun.com/tom_fans/article/details/73937375 为了准确了解HBASE内部工作原理,我们需要做一些测试,在大量数据插入的情况下,HBASE内部到底有什么表现?  比如插入速度,  hstore c...

大JAVA解决方案 417

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

HBase三个重要机制

1、flush机制 1.(hbase.regionserver.global.memstore.size)默认;堆大小的40% regionServer的全局memstore的大小,超过该大小会触发flush到磁盘的操作,默认是堆大小的40%,而且regionserver级别的flush会阻塞客户端读写 2.(hbase.hregion.memstore.flush.size)默认:128M 单个...

weixin_44361667的博客 245

hbase的hfile compaction 以及region的split

hfile compaction 由于memstore每次刷写都会生成一个新的HFile,且同一个字段的不同版本(timestamp)和不同类型(Put/Delete)有可能会分布在不同的HFile中,因此查询时需要遍历所有的HFile。为了减少HFile的个数,以及清理掉过期和删除的数据,会进行StoreFile Compaction。 Compaction分为两种,分别是Minor Compa...

sghuu的博客 538

深入理解 HBase Compaction 机制

HBase有很多话题可以聊,包括读写路径上涉及到的一些数据结构,性能优化以及优化读写做的一些设计等。今天要探讨的Compaction机制就是HBase架构上做的一个重要优化!

Focus on Lakehouse 1万+

HBase的架构和原理(四)--MemStore的Flush动作和HFile的Compaction机制

Hbase中MemStore的Flush动作和HFile的Compaction机制

weixin_37536020的博客 423

hbase-memstore flush剖析

memstore是hbase中一个非常重要的组件,对于hbase的读写操作的性能起到举足轻重的作用,下面讲从memstore概述、memstore flush触发条件、memstore flush流程、memstore flush流程源码四个方面对memstore进行说明 memstore概述 一个RegionServer上对应多个Region,一个Region对应多个Store,一个Store对应一个Memstore和多个HFile,几者之间的关系如下图 Regionserve...

zfs_sir的博客 507

HBase MemStore flush执行流程

前言 上一篇博客中(https://blog.youkuaiyun.com/qq_35542970/article/details/109390109),我们分析了memstore flush的几种触发条件,从中可以看出HBase将需要flush的请求存放于MemStoreFlusher中定义的flushQueue中。那么队列中的flush请求又是如何处理的呢? 1、flush队列的处理 1.1、flush请求队列的处理流程: 以put等操作触发的flush为例,流程如下: (图片来自链接https://blog.cs

qq_35542970的博客 752

memstore的flush流程分析

memstore的flush流程分析 memstore的flush发起主要从以下几个地方进行:  a.在HRegionServer调用multi进行更新时,检查是否超过全局的memstore配置的最大值与最小值,    如果是,发起一个WakeupFlushThread的flush请求,如果超过全局memory的最大值,需要等待flush完成。  b.在HRegionServer进行数据...

隔壁老杨的专栏 350

HFile的合并

一.之前说到了BlockBache的优化以及MemStore的优化 这篇文章主要介绍一下HFIle的合并 我们首先要明白的是,为什么HFile要进行合并? 1.StoreFile是HFile的抽象,MemStore的每一次刷写都会产生一个HFile,如果HFile数量过多会产生什么问题?读取速度下降,因为读取数据涉及到一个操作:寻址 如果是传统硬盘那就是磁头的移动。 寻址,这是一个很慢的动作。当H...

qq_38304320的博客 1595

Region使用全解

代码地址如下:http://www.demodashi.com/demo/14799.html ####前言 Region,即为区域,它表示的是canvas图层上的某一块封闭的区域。很多时候,我们会利用Region来构造一个图形。 今天要讲的内容有: Region的直接构造方法 Region的间接构造方法 Region的setPath(Path path, Region clip)方法介绍 ...

findhappy117的博客 1万+

hbase的写和读,大合并和小合并

hbase写: 客户端向hbase服务器端发送写的请求时,hbase会同时进行两个动作,把记录写在WAL(write ahead log)日志文件中,每台服务器所有表都共享这个WAL文件。然后会写到memStore内存中,memStore是内存中的写入缓存区,如果memStore写满就刷新写到硬盘,生成HFile文件。当服务器宕机时memStore内存中的内容就没了,这时可以通过回放WAL日志文件

share_free的博客 9006
上一篇: HBase系列(二)、架构原理
下一篇: HBase系列(四)、HBase优化之RowKey 设计
王义凯_Rick
王义凯_Rick 领域专家: 大数据技术领域 领域专家: 大数据技术领域
博客等级 码龄14年 858粉丝 162原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

王义凯_Rick

遇见即是缘,路过就给个评论吧~

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

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

打赏作者

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

抵扣说明:

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

余额充值