MogileFS部署流程

MogileFS部署文档


简介

MogileFS 是一个开源的分布式文件系统,用于组建分布式文件集群,由 LiveJournal 旗下 DangaInteractive 公司开发,Danga 团队开发了包括 Memcached、MogileFS、Perlbal 等不错的开源项目(注:Perlbal 是一个强大的 Perl 写的反向代理服务器)。 目前使用 MogileFS 的公司非常多,比如国外的一些公司,日本前几名的公司基本都在使用这个,国内所知道的使用 MogileFS 的公司有图片托管网站 yupoo 又拍、digg、 土豆、 豆瓣、1 号店、大众点评、搜狗、安居客等等网站。基本很多网站容量,图片都超过 30T 以上。

特性

  • 应用层提供服务,不需要使用核心组件
  • 无单点:三大组件(tracker、mogstore,database)皆可实现高可用
  • 自动文件复制:复制的最小单位不是文件,而是 class,文件可以被自动复制到多个有足够存储空间的存储节点上
  • 传输中立:无特殊协议,可以通过 NFS 或 HTTP 实现通信
  • 简单的命名空间:文件通过一个给定的 key 来确定,是全局的命名空间,没有目录基于域实现文件隔离
  • 不共享任何数据:无需通过昂贵的 SAN 来共享磁盘,每个存储节点只需维护自己所属的存储设备(device)

原理

组成部分

Trackers(跟踪器)

mogilefsd 即 trackers 程序,是整套系统的核心,trackers 负责调度工作,职责:Replication ,Deletion,Query,Reaper,Monitor 等等。mogadm,mogtool 的所有操作都要跟 trackers 打交 道,Client 的一些操作也需要定义好 trackers,因此最好同时运行多个 trackers 来做负载均衡。trackers 也可以只运行在一台机器 上,也可以跟其他程序运行在一起,只要你配置好他的配置文件即可,默认在/etc/mogilefs/mogilefsd.conf。

Storage(存储节点)

mogstored 程序的启动将使本机成为一个存储节点。启动时默认去读/etc/mogilefs/mogstored.conf ,具体配置可以参考配置部分。mogstored 启动后,便可以通过 mogadm 增加这台机器到 cluster 中。一台机器可以只运行一个 mogstored 作为存储节点即可,也可以同时运行其他程序。

Database(数据库)

数据库保存了 Mogilefs 的所有元数据。这部分非常重要,类似邮件系统的认证中心,如果这部分挂了,那么整个 Mogilefs 将处于不可用状态。这应该设置一个高可用性(HA)的环境以防止单点失败。

术语解释

设备(device) 一个存储节点,可以有多个 device,就是用来存放文件的目录,每个设备都有一个设备 ID,需要在 mogstored 配置文件中 docroot 配置,设备不能删除,只能将设备的状态置为 dead,置为 dead 之后数据就无法恢复了,并且设备 ID 也无法使用。(建议每个节点只有一个 device,文件存储多份时,有多余数据备份在当前节点其他设备,等于没有备份,若只备份2份,节点发生故障,数据就会丢失)

**域(domain) **   一个域中的键值是惟一的,一个 MogileFS 可以有多个域,域可以用来存储不同应用类型的数据的容器。

类(class) 复制文件的最小单位 (最大为64M,如果一个单文件超出此大小将拆分为多个 class 存储)。在一个域中可以有多个类,主要是用来控制复制单元的,类是用来做属性管理的,类是比域 domain 低一个级别,可以定义一个文件存储在不同 device 中的份数。一个文件必须通过 domain、class 和 key 才能定位到。

部署过程

安装环境说明

系统环境:CentOS release 6.9 (Final)

注意:以下所有步骤均在 CentOS Release 6.9下执行通过。服务使用源码编译安装,理论上具有通用性。

角色划分:

角色hostnameIP安装软件
存储节点 storage01Rybh101172.16.1.101MogileFS
存储节点 storage02Rybh102172.16.1.102MogileFS
Tracker,DatabaseRybh103172.16.1.103MogileFS,MariaDB

安装过程

1. 安装 MogileFS 服务(所有主机)

  • 安装环境依赖

RedHat/CentOS

yum install -y epel-release
yum -y install make gcc unzip perl-DBD-MySQL perl perl-CPAN perl- YAML perl-Time-HiRes perl-ExtUtils-MakeMaker perl-Net-Netmask perl-IO-AIO
  • MogileFS 是基于 Perl 语言构建的项目,因此需要从 CPAN 上面下载 MogileFS 的模块,因此需要保证被部署的机器能够直接或者通过代理连接至互联网,如果无法联网,则需要梳理模块的依赖关系,通过其他途径下载所有所需要的 perl 的模块,并且手工编译安装。

首先,在两台机器上面安装 cpanm 工具,用于安装模块:

curl -L https://cpanmin.us/ -o /usr/bin/cpanm
chmod +x /usr/bin/cpanm

设置环境变量:

export LC_ALL=C
alias cpanm='cpanm --sudo --mirror http://mirrors.163.com/cpan --mirror-only'

cpanm 安装完毕之后,在两台机器上面安装 MogileFS 所需要的模块

cpanm App::cpanminus
cpanm IO::AIO
cpanm IO::WrapTie
cpanm Danga::Socket
cpanm DBD::mysql
cpanm MogileFS::Server
cpanm MogileFS::Client
cpanm MogileFS::Utils

安装完成后,生成的相关命令如下图所示:

在这里插入图片描述

2. 配置 MogileFS 服务(所有主机)

首先在三台机器上面创建/etc/mogilefs 这个目录,用于存放配置文件。其次在两台机器上面创建 mogilefs 组和 mogilefs 用户,用于运行 mogileFS 相关的进程(笔者将上述用户和组创建为系统用户和系统组)。之后再在两台机器上面创建/alidata 目录,用于模拟 storage 的设备目录的父目录,并赋予 mogilefs 用户和 mogilefs 用户组权限。

mkdir /etc/mogilefs
groupadd -r mogilefs
useradd -r -g mogilefs -d /home/mogilefs -s /bin/bash -m mogilefs
mkdir /alidata/
chown mogilefs.mogilefs /alidata

由于利用 CPAN 安装的 MogileFS 并未涉及到配置文件,因此这里使用了 GitHub 上面提供的 mogilefsd.conf 文件和 mogstored.conf 文件作为 MogileFS 系统的配置文件。mogilefsd.conf 文件作为 tracker 的配置,而 mogstored.conf 为 storage 进行配置。将上述两个文件下载,并拷贝到两台机器的/etc/mogilefs 目录下面:

wget https://github.com/hachi/MogileFS-Server/archive/master.zip -O /opt/MogileFS-Server-master.zip
cd /opt
unzip MogileFS-Server-master.zip
cp MogileFS-Server-master/conf/* /etc/mogilefs
  • 数据库节点配置(172.16.1.103)

配置 mariadb 的 yum 安装源

cat >>/etc/yum.repos.d/MariaDB.repo<<'EOF'
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.0/centos7-amd64
gpkgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
EOF

yum 安装 mariadb,启动数据库服务

yum install -y MariaDB-server MariaDB-client

创建 mogilefs 的连接用户,这里的账号和密码在 tracker 服务里需要用到

MariaDB [(none)]> USE mysql;
Database changed

MariaDB [mysql]> GRANT ALL ON mogilefs.* TO 'moguser'@'172.16.%.%'  IDENTIFIED BY 'mogpass';
Query OK, 0 rows affected (0.00 sec)

MariaDB [mysql]> GRANT ALL ON *.* TO 'root'@'172.16.%.%' IDENTIFIED BY 'rootpass';
Query OK, 0 rows affected (0.00 sec)

MariaDB [mysql]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
  • Tracker 节点配置(172.16.1.103

初始化 mogilefs 数据库。

mogdbsetup --dbhost=172.16.1.103 --dbrootuser=root \
--dbrootpass=rootpass --dbuser=moguser --dbpass=mogpass --dbname=mogilefs --yes

数据库初始化完毕之后,登录数据库查看是否生成数据表。

MariaDB [(none)]> use mogilefs;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [mogilefs]>> show tables;
+----------------------+
| Tables_in_mogilefs   |
+----------------------+
| checksum             |
| class               |
| device               |
| domain               |
| file                 |
| file_on             |
| file_on_corrupt     |
| file_to_delete       |
| file_to_delete2     |
| file_to_delete_later |
| file_to_queue       |
| file_to_replicate   |
| fsck_log             |
| host                 |
| server_settings     |
| tempfile             |
| unreachable_fids     |
+----------------------+
17 rows in set (0.00 sec)

修改 trakcer 的主配置文件:

# cat /etc/mogilefs/mogilefsd.conf
daemonize = 1                           #是否以守护进程运行
pidfile = /home/mogilefs/mogilefsd.pid
db_dsn = DBI:mysql:mogilefs:host=172.16.1.103  #定义数据库名及主机
db_user = moguser                       #数据库用户名
db_pass = mogpass                       #数据库用户密码
listen = 172.16.1.103:7001                  #监听地址
conf_port = 7001
query_jobs = 10
delete_jobs = 1
replicate_jobs = 5
reaper_jobs = 1

启动 trakcer 服务

su - mogilefs -c "/usr/local/bin/mogilefsd -c /etc/mogilefs/mogilefsd.conf --daemon"
  • Storage 节点配置(172.16.1.101和172.16.1.102)

修改 storage 节点的主配置文件,定义根目录(所有设备目录的父目录)为/alidata。

# cat /etc/mogilefs/mogstored.conf
maxconns = 10000
httplisten = 0.0.0.0:7500
mgmtlisten = 0.0.0.0:7501
docroot = /alidata/

启动 storage 服务

su - mogilefs -c "/usr/local/bin/mogstored -c /etc/mogilefs/mogstored.conf --daemon"

亦可以将启动命令封装成启动脚本:

Mogilefsd 启动脚本:

#!/bin/bash
#
# chkconfig: - 85 15
# description: MogileFS tracker
# processname: mogilefsd
# config: /etc/mogilefs/mogilefsd.conf
# pidfile: /home/mogilefs/mogilefsd.pid

. /etc/rc.d/init.d/functions

lockfile=${LOCKFILE-/var/lock/subsys/mogilefsd}
RETVAL=0

pidfile='/home/mogilefs/mogilefsd.pid'

start() {
       ulimit -n 65535
        echo -n $"Starting mogilefsd"
        su - mogilefs -c "/usr/local/bin/mogilefsd -c /etc/mogilefs/mogilefsd.conf --daemon" &> /dev/null
        RETVAL=$?
       [ $RETVAL = 0 ] && success && touch ${lockfile} && pidof /usr/local/bin/mogilefsd > $pidfile || failure
        echo
       return $RETVAL
}

stop() {
        echo -n $"Stopping mogilefsd"
       netstat -nlp|grep "mogilefsd"|grep -v grep|awk '{print $7}' |awk -F"/" '{print $1}'|xargs kill -9
        RETVAL=$?
       [ $RETVAL = 0 ] && success && rm -f ${lockfile} || failure
        echo
}

reload() {
        echo -n $"Reloading mogilefsd: "
        killall mogilefsd -HUP
        RETVAL=$?
       [ $RETVAL = 0 ] && success || failure
        echo
}

case "$1" in
        start)
                start
               ;;
        stop)
                stop
               ;;
       status)
               status mogilefsd
                RETVAL=$?
               ;;
        restart)
                stop
                sleep 1
                start
               ;;
       reload)
               reload
               ;;
       *)
                echo $"Usage: mogilefsd {start|stop|restart|reload|status}"
                exit 1
esac
exit $RETVAL

Mogstored 启动脚本:

#!/bin/bash
#
# chkconfig: - 86 14
# description: MogileFS storage
# processname: mogstored
# config: /etc/mogilefs/mogstored.conf
# pidfile: /home/mogilefs/mogstored.pid

. /etc/rc.d/init.d/functions

lockfile=${LOCKFILE-/var/lock/subsys/mogstored}
RETVAL=0

configfile="/etc/mogilefs/mogstored.conf"
pidfile="/home/mogilefs/mogstored.pid"

prog=$(which mogstored)

start() {
       ulimit -n 65535
        echo -n $"Starting mogstored"
        su - mogilefs -c "/usr/local/bin/mogstored -c $configfile --daemon" &> /dev/null
        RETVAL=$?
       [ $RETVAL = 0 ] && success && touch ${lockfile} && pidof /usr/local/bin/mogstored > $pidfile || failure
        echo
       return $RETVAL
}

stop() {
        echo -n $"Stopping mogstored"
       netstat -nlp|grep "mogstored"|grep -v grep|awk '{print $7}'|awk -F"/" '{print $1}'|xargs kill -9
        RETVAL=$?
       [ $RETVAL = 0 ] && success && rm -f ${lockfile} ${pidfile} || failure
        echo
}

reload() {
        echo -n $"Reloading mogstored: "
        killall mogstored -HUP
        RETVAL=$?
       [ $RETVAL = 0 ] && success || failure
        echo
}

case "$1" in
        start)
                start
               ;;
        stop)
                stop
               ;;
       status)
               status mogstored
                RETVAL=$?
               ;;
        restart)
                stop
                sleep 1
                start
               ;;
       reload)
               reload
               ;;
       *)
                echo $"Usage: mogstored {start|stop|restart|reload|status}"
                exit 1
esac
exit $RETVAL

服务启动后,可用 netstat 命令检查相关端口是否正常监听,7001是 mogilefsd 的端口,7500是 mogstored 的端口:

netstat -lntup|egrep "7500|7001"

3. 管理 MogileFS 集群

  • 使用 mogadm 命令检测集群状态,指定 tracker 节点为172.16.1.103
$ mogadm --trackers=172.16.1.103:7001 check
Checking trackers...
  172.16.1.103:7001 ... OK

Checking hosts...
No devices found on tracker(s).
  • 添加 Storage 节点

添加 hosts,即 storage 节点。将添加的 storage 节点分别命名为 store1和 store2。添加完毕之后分别利用 check 和 host list 子命令来查看状态,正常情况下可以看到 storage 节点已经添加完毕,并且状态为 alive。

$ mogadm --trackers=172.16.1.103:7001 host add store1 --ip=172.16.1.101 --status=alive
$ mogadm --trackers=172.16.1.103:7001 host list
store1 [1]: alive
 IP:       172.16.1.101:7500

$ mogadm --trackers=172.16.1.103:7001 host add store2 --ip=172.16.1.102 --status=alive
$ mogadm --trackers=172.16.1.103:7001 host list
store1 [1]: alive
 IP:       172.16.1.101:7500

store2 [2]: alive
 IP:       172.16.1.102:7500

$ mogadm --trackers=172.16.1.103:7001 check
Checking trackers...
  172.16.1.103:7001 ... OK

Checking hosts...
 [ 1] store1 ... OK
 [ 2] store2 ... OK

Checking devices...
 host device         size(G)   used(G)   free(G)   use%   ob state   I/O%
  ---- ------------ ---------- ---------- ---------- ------ ---------- -----
  ---- ------------ ---------- ---------- ---------- ------
             total:     0.000      0.000      0.000   0.00%
  • 给 Storage 节点添加设备 device

目前集群的 docroot 定义为/alidata,首先在节点上创建对应目录,并都赋予 mogilefs 用户权限和 mogilefs 组权限:

1)节点 storage01:/alidata/dev1

2)节点 storage02:/alidata/dev2

节点 storage01:

$ mkdir -pv /alidata/dev1
$ chown mogilefs.mogilefs /alidata/dev1

节点 storage02:

$ mkdir -pv /alidata/dev2
$ chown mogilefs.mogilefs /alidata/dev2

通过 mogadm 的 device add 子命令,在节点 storage01上面添加 dev1,在节点 storage02上面添加 dev2。添加完毕之后,用 device list 子命令进行查看。正常情况下,可以看到 store1和 store2下面分别多出了 dev1和 dev2设备,以及 dev1和 dev2设备的可用情况。 注:在添加的时候,dev1的节点编号为1,dev2的节点编号为2,以此类推,devn 的节点编号为 n…

$ mogadm --trackers=172.16.1.103:7001 device add store1 1
$ mogadm --trackers=172.16.1.103:7001 device add store2 2
$ mogadm --trackers=172.16.1.103:7001 device list
store1 [1]: alive
                   used(G)   free(G)   total(G) weight(%)
   dev1:   alive      1.072     36.378     37.450        100

store2 [2]: alive
                   used(G)   free(G)   total(G) weight(%)
   dev2:   alive      1.010     36.440     37.450        100

执行完成后,在设备目录下生成了一系列文件,结构如下:

在这里插入图片描述

  • 创建 Domain

MogileFS 使用 Domain 来存放文件。每一个 Domain 的实例,管理了一组 key-value 的”元数据-数据”对象,可以创建一个 Domain 的实例,名称为 text,用于专门存储文本文件;可以创建另一个 Domain 的实例,名称为 images,用于专门存储图片文件。每一 Domain 实例下面的 key 代表了一个被存储的文件的元数据索引,对应着被存储的文件本身,即 value。

$ mogadm --trackers=172.16.1.103:7001 domain add images
$ mogadm --trackers=172.16.1.103:7001 domain add text
$ mogadm --trackers=172.16.1.103:7001 domain list
domain               class               mindevcount   replpolicy   hashtype
-------------------- -------------------- ------------- ------------ -------
 images               default                   2       MultipleHosts() NONE  

 text                 default                   2       MultipleHosts() NONE

在每一个区域中建立 class,即文件复制的最小单位:

$ mogadm --trackers=172.16.1.103:7001 class add images class1 --mindevcount=2
$ mogadm --trackers=172.16.1.103:7001 class add images class2 --mindevcount=2
$ mogadm --trackers=172.16.1.103:7001 class add text class1 --mindevcount=2
$ mogadm --trackers=172.16.1.103:7001 class add text class2 --mindevcount=2
$ mogadm --trackers=172.16.1.103:7001 class list
domain               class               mindevcount   replpolicy   hashtype
-------------------- -------------------- ------------- ------------ -------
 images               class1                    2       MultipleHosts() NONE
 images               class2                    2       MultipleHosts() NONE
 images               default                   2       MultipleHosts() NONE

 text                 class1                    2       MultipleHosts() NONE
 text                 class2                    2       MultipleHosts() NONE
 text                 default                   2       MultipleHosts() NONE
  • 使用 mogupload 上传文件测试,并使用 mogfileinfo 命令进行查看文件信息
## 上传图片
$ mogupload --trackers=172.16.1.103:7001 --domain=images --key='/images/1k.jpg' \
--file='/root/wings.jpg'
$ moglistkeys --trackers=172.16.1.103:7001 --domain=images
/images/1k.jpg
$ mogfileinfo --trackers=172.16.1.103:7001 --domain=images --key=/images/1k.jpg
- file: /images/1k.jpg
     class:             default
 devcount:                    1
   domain:               images
       fid:                    2
       key:       /images/1k.jpg
   length:                96225  
 - http://172.16.1.102:7500/dev2/0/000/000/0000000002.fid

## 上传文本
$ mogupload --trackers=172.16.1.103:7001 --domain=text --key='/text/hosts.html' --file='/etc/hosts'
$ moglistkeys --trackers=172.16.1.103:7001 --domain=text
/text/hosts.html
$ mogfileinfo --trackers=172.16.1.103:7001 --domain=text --key=/text/hosts.html
- file: /text/hosts.html
     class:             default
 devcount:                    1
   domain:                 text
       fid:                    4
       key:     /text/hosts.html
   length:                  158
 - http://172.16.1.101:7500/dev1/0/000/000/0000000004.fid

在 storage 节点上相关路径下可以看到文件信息:

## 节点 storage01
$ /alidata/dev1/0/000/000/0000000004.fid: ASCII text 

## 节点 storage02:
$ file /alidata/dev2/0/000/000/0000000002.fid
/alidata/dev2/0/000/000/0000000002.fid: JPEG image data, JFIF standard 1.01
  • 通过浏览器访问资源上面的 HTTP 地址:

在这里插入图片描述
在这里插入图片描述

使用 Nginx 代理 MogileFS 集群

默认情况下是直接以 fid 形式的标识符去访问资源,这样很不方便。使用 Nginx 的第三方模块 mogilefs-module,可以将 Nginx 作为 tracker 和 storage 的反向代理,实现通过访问定义的 key 值获取到指定的资源。由于要静态编译第三方模块,所以这里的 nginx 需要使用源码编译安装。

cd /tmp
wget http://nginx.org/download/nginx-1.9.1.tar.gz
wget http://www.grid.net.ru/nginx/download/nginx_mogilefs_module-1.0.4.tar.gz

①编译前确保安装依赖

yum install pcre-devel openssl-devel -y
yum install make zlib zlib-devel gcc-c++ libtool
groupadd www && useradd www -g www -M -s /sbin/nologin
cd /tmp
wget http://nginx.org/download/nginx-1.8.1.tar.gz
git clone https://github.com/vkholodkov/nginx-mogilefs-module.git
tar zxf nginx-1.8.1.tar.gz
cd nginx-1.8.1

②编译安装 nginx(这里提供一份自己常用的编译参数)

./configure --prefix=/usr/local/nginx \
    --sbin-path=${prefix}/sbin/nginx \
    --conf-path=${prefix}/conf/nginx.conf   \
    --error-log-path=${prefix}/logs/error.log \
    --http-log-path=${prefix}/logs/access.log   \
    --pid-path=${prefix}/logs/nginx.pid   \
    --lock-path=${prefix}/logs/nginx.lock \
    --http-client-body-temp-path=${prefix}/cache/client_temp \
    --http-proxy-temp-path=${prefix}/cache/proxy_temp \
    --http-fastcgi-temp-path=${prefix}/cache/fastcgi_temp \
    --http-uwsgi-temp-path=${prefix}/cache/uwsgi_temp \
    --http-scgi-temp-path=${prefix}/cache/scgi_temp \
    --user=www \
    --group=www   \
    --with-pcre \
    --with-http_ssl_module \
    --with-http_spdy_module \
    --with-http_stub_status_module \
    --with-http_realip_module \
    --with-http_addition_module \
    --with-http_sub_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_mp4_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_random_index_module \
    --with-http_secure_link_module \
    --with-http_degradation_module \
    --with-http_auth_request_module \
    --with-file-aio \
    --add-module=../nginx-mogilefs-module

这里有一个 bug,需要手动修改编译生成的 Makefile 文件:

$ vim objs/Makefile
CFLAGS =  -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g
修改为
CFLAGS =  -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -g
修改完成后再行编译安装:
make -j8 && make install

③nginx 配置,配置文件如下:

具体可参考:

http://www.grid.net.ru/nginx/mogilefs.en.html

worker_processes  1;
events {
   worker_connections  1024;
}
http {
   include       mime.types;
   default_type application/octet-stream;
   sendfile       on;
   keepalive_timeout  65;

   upstream mogfs_cluster {
       server 172.16.1.103:7001;
   }
   server {
       listen       80;
       server_name localhost;
       location / {
           root   html;
           index index.html index.htm;
       }
       location ~* ^(/images/.*)$ {
           mogilefs_tracker mogfs_cluster;
           mogilefs_domain images;
           mogilefs_noverify on;
           mogilefs_pass $1 {
               proxy_pass $mogilefs_path;
               proxy_hide_header Content-Type;
               proxy_buffering off;
           }
       }
       location ~* ^(/text/.*)$ {
           mogilefs_tracker mogfs_cluster;
           mogilefs_domain text;
           mogilefs_noverify on;
           mogilefs_pass $1 {
               proxy_pass $mogilefs_path;
               proxy_hide_header Content-Type;
               proxy_buffering off;
           }
       }
       error_page   500 502 503 504 /50x.html;
       location = /50x.html {
           root   html;
       }
   }
}

Nginx 配置完成并启动后,即可通过自定义的 key 值访问资源了:

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值