生产环境-Mysql高可用配置(dble+mysql+keeplived)

一、架构分析

1.体系

dble+mysql+keeplived

2.机器与软件描述

mysql01(172.28.8.65)

mysql02(172.28.8.61)

dble01(172.28.8.62)

dble02(172.28.8.63)

keeplived01(172.28.8.62)

keeplived02(172.28.8.63)

3.架构图

在这里插入图片描述

二、主主同步

1.拉取镜像

docker pull mysql:5.7 

2.主从机创建文件docker.cnf

创建文件夹(两个容器不要共用文件夹

mkdir /usr/local/mysql
cd mysql/
mkdir conf data

在这里插入图片描述

在conf下创建docker.cnf

vim /usr/local/mysql/conf/docker.cnf

添加

[mysqld]
server-id=1
log-bin=master-bin  #只是读写,就只要主库配置即可.如果要做主从切换,那么主库和从库都需要开启.
skip-host-cache
skip-name-resolve
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server = utf8
[mysql]  
default-character-set=utf8
[client]  
default-character-set=utf8
[mysqld]
server-id=2
log-bin=master-bin 
skip-host-cache
skip-name-resolve
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server = utf8
[mysql]  
default-character-set=utf8
[client]  
default-character-set=utf8

3.关闭防火墙

systemctl disable firewalld

4.启动Mysql主机和从机

docker run --name mysqlmastertwo -p 3306:3306 -p 33060:33060 -v /usr/local/mysql/conf:/etc/mysql/conf.d -v /usr/local/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --privileged=true -d mysql:5.7
docker run --name mysqlslave -p 3307:3306 -p 33070:33060 -v /usr/local/mysql2/conf:/etc/mysql/conf.d -v /usr/local/mysql2/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --privileged=true -d mysql:5.7
docker run --name mysqlpart1 -p 3308:3306 -p 33080:33060 -v /data/db_group/part_data/conf:/etc/mysql/conf.d -v /data/db_group/part_data/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --privileged=true -d mysql:5.7
docker run --name mysqlpart1 -p 3309:3306 -p 33090:33060 -v /data/db_group/part2_data/conf:/etc/mysql/conf.d -v /data/db_group/part2_data/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --privileged=true -d mysql:5.7

5.开启主从复制

mysql主机

进入mysql容器

docker exec -it mysqlmaster /bin/bash

启动mysql

mysql -uroot -proot

创建slave用户

 create user 'hzero'@'%'  identified by 'hzero';

授权

grant replication slave on *.* to 'hzero'@'%';

刷新权限

flush privileges;

查看状态

show master status;

在这里插入图片描述

show master status\G
mysql> show master status\G;
*************************** 1. row ***************************
             File: master-bin.000004
         Position: 154
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)
mysql从机

进入mysql容器

docker exec -it mysqlmastertwo /bin/bash 

启动mysql

mysql -uroot -proot

执行主从

change master to master_host='172.28.8.61',master_port=3306,master_user='hzero',master_password='hzero',master_log_file='master-bin.000003',master_log_pos=745;

在这里插入图片描述

开启复制

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

查看主从是否成功

show slave status \G;

停止

stop slave;

6.检测是否主从搭建成功

show slave status \G;

截图

在这里插入图片描述

在写库创建一条记录

在这里插入图片描述

读库自动同步

在这里插入图片描述

注意:由于是主主架构,刚才的步骤,两台机器互换角色,再配置一次,保证两台机器可以相互同步

三、dble配置mysql集群

1.dble01(172.28.8.62)配置

1.安装docker-compose

1、安装python-pip

yum -y install epel-release

yum -y install python-pip

2、安装docker-compose

pip install docker-compose

待安装完成后,执行查询版本的命令,即可安装docker-compose

docker-compose version

2.docker-compose编排安装DBLE

创建docker-compose.yml

version: '2'
services:
    dble-server:
        image: actiontech/dble:latest
        container_name: dble-server
        hostname: dble-server
        privileged: true
        stdin_open: true
        tty: true
        volumes:
            - ./config/:/opt/dble/extra/
        ports:
            - "8066:8066"
            - "9066:9066"

在对应目录下执行

docker-compose up -d

3.配置SSH访问容器

docker exec -it DBLE容器ID /bin/bash
yum -y install passwd openssl openssh-server openssh-clients
# 创建 /var/run/sshd/目录,要不然sshd服务启动会报错
mkdir /var/run/sshd/
# 编辑sshd的配置文件/etc/ssh/sshd_config,将其中的UsePAM yes改为UsePAM no
sed -i "s/UsePAM.*/UsePAM no/g" /etc/ssh/sshd_config
# 7.创建公私密钥,输入命令后,直接按两次enter键确认就行了
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
#8.完成上述几步后,可以开启ssh服务了(&表示后台启动)
/usr/sbin/sshd -D &
# 9.此时使用命令ps -ef | grep sshd  便可以看到效果
#10.查询22端口是否处于监听状态
yum -y install lsof
lsof -i:22
# 11.修改root密码
.
#12.测试
#输入命令ssh localhost,然后输入之前设置的root密码

#13.如何配置外部客户端访问docker里的centos7.4容器
docker ps -a
#提交容器成为新的镜像,例如叫做sshd_centos7.4,输入
docker commit 容器ID sshd_dble:0.0.1
#启动这个镜像的容器,并映射本地的一个闲置的端口(例如15000)到容器的22端口,并启动容器的sshd(只要端口不冲突可以同时启动多个容器,如下图)
docker run -d -p 15000:22 -p 8066:8066 -p 9066:9066 sshd_dble:0.0.1 /usr/sbin/sshd -D
#现在打开新的终端,输入ssh root@宿主机IP地址 -p 15000,如果能连接成功,会要求输入密码的,输入刚才passwd命令设置的root账户密码就可以进入容器的终端了

#如果连接失败,请检查防火墙是否未开放该端口。 

finalShell连接容器

在这里插入图片描述

4.配置dble容器自启动

新建文件夹/data/dockerfile

cd /data/dockerfile

1.创建DockerFile文件
from sshd_dble:0.0.1
MAINTAINER pigic from hand-china.com(guchang.pan@hand-china.com)
WORKDIR /
ADD run.sh /run.sh
RUN chmod 777 /*.sh
EXPOSE 8066
EXPOSE 9066
EXPOSE 22
ENTRYPOINT ["/run.sh"]
2.同目录创建run.sh
#!/bin/bash
/opt/dble/bin/docker_init_start.sh
/usr/sbin/sshd -D
3.生成新的容器并启动
docker build -t sshd_dble:0.0.2 .
docker run -d -p 15000:22 -p 8066:8066 -p 9066:9066 sshd_dble:0.0.2

进入容器

5修改DBLE配置Mysql集群

cd /opt/dble/conf

修改server.xml和schema.xml

1.修改server.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright (C) 2016-2019 ActionTech.
  ~ License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
  -->

<!-- - - Licensed under the Apache License, Version 2.0 (the "License");
	- you may not use this file except in compliance with the License. - You 
	may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 
	- - Unless required by applicable law or agreed to in writing, software - 
	distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 
	WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the 
	License for the specific language governing permissions and - limitations 
	under the License. -->
<!DOCTYPE dble:server SYSTEM "server.dtd">
<dble:server xmlns:dble="http://dble.cloud/" version="2.0">
    <system>
        <!-- base config -->
        <!--<property name="bindIp">0.0.0.0</property>-->
        <property name="serverPort">8066</property>
        <property name="managerPort">9066</property>
        <!--<property name="maxCon">0</property> -->
        <!--<property name="processors">4</property>-->
        <!--<property name="backendProcessors">12</property>-->
        <!--<property name="processorExecutor">4</property> -->
        <!--<property name="backendProcessorExecutor">12</property> -->
        <!--<property name="complexExecutor">8</property> -->
        <!--<property name="writeToBackendExecutor">4</property> -->

        <!--<property name="fakeMySQLVersion">5.6.20</property>-->
        <property name="sequnceHandlerType">2</property>
        <!-- serverBacklog size,default 2048-->
        <property name="serverBacklog">2048</property>
        <!--<property name="serverNodeId">1</property>-->
        <!--<property name="showBinlogStatusTimeout">60000</property>-->

        <!--option-->
        <!--<property name="useCompression">1</property>-->
        <!--<property name="usingAIO">0</property>-->
        <!--<property name="useZKSwitch">true</property>-->
        <!--<property name="useThreadUsageStat">0</property>-->
        <!--<property name="usePerformanceMode">0</property>-->

        <!-- query time cost statistics-->
        <!--<property name="useCostTimeStat">0</property>-->
        <!--<property name="maxCostStatSize">100</property>-->
        <!--<property name="costSamplePercent">1</property>-->

        <!--connection -->
        <!--<property name="charset">utf8</property>-->
        <!--<property name="maxPacketSize">4194304</property>-->
        <!--<property name="txIsolation">3</property>-->

        <!--consistency-->
        <!-- check the consistency of table structure between nodes,default not -->
        <property name="checkTableConsistency">0</property>
        <!-- check periodt, he default period is 60000 milliseconds -->
        <property name="checkTableConsistencyPeriod">60000</property>

        <!-- heartbeat check period -->
        <property name="dataNodeIdleCheckPeriod">300000</property>
        <property name="dataNodeHeartbeatPeriod">10000</property>

        <!-- processor check conn-->
        <property name="processorCheckPeriod">1000</property><!-- unit millisecond -->
        <property name="sqlExecuteTimeout">300</property><!-- unit second -->
        <property name="idleTimeout">1800000</property><!-- unit millisecond -->

        <!-- transaction log -->
        <!-- 1 enable record the transaction log, 0 disable -->
        <property name="recordTxn">0</property>
        <!--<property name="transactionLogBaseDir">/txlogs</property>-->
        <!--<property name="transactionLogBaseName">server-tx</property>-->
        <!--<property name="transactionRatateSize">16</property>--><!-- unit M -->

        <!-- XA transaction -->
        <!-- use XA transaction ,if the mysql service crash,the unfinished XA commit/rollback will retry for several times
       it is the check period for ,default is 1000 milliseconds-->
        <property name="xaSessionCheckPeriod">1000</property>
        <!-- use XA transaction ,the finished XA log will removed. the default period is 1000 milliseconds-->
        <property name="xaLogCleanPeriod">1000</property>
        <!-- XA Recovery Log path -->
        <!--<property name="xaRecoveryLogBaseDir">/tmlogs/</property>-->
        <!-- XA Recovery Log name -->
        <!--<property name="xaRecoveryLogBaseName">tmlog</property>-->
        <!-- XA Retry count, retry times in backend, 0 means always retry until success -->
        <!--<property name="xaRetryCount">0</property>-->

        <!-- true is use JoinStrategy, default false-->
        <property name="useJoinStrategy">true</property>
        <property name="nestLoopConnSize">4</property>
        <property name="nestLoopRowsSize">2000</property>

        <!-- query memory used for per session,unit is M-->
        <property name="otherMemSize">4</property>
        <property name="orderMemSize">4</property>
        <property name="joinMemSize">4</property>

        <!-- off Heap unit:bytes-->
        <property name="bufferPoolChunkSize">4096</property>
        <property name="bufferPoolPageNumber">256</property>
        <property name="bufferPoolPageSize">2097152</property>
        <!--<property name="mappedFileSize">2097152</property>-->

        <!-- sql statistics-->
        <!-- 1 means use SQL statistics, 0 means not -->
        <property name="useSqlStat">0</property>
        <!--<property name="bufferUsagePercent">80</property>-->
        <!--<property name="clearBigSqLResultSetMapMs">600000</property>-->
        <!--<property name="sqlRecordCount">10</property>-->
        <!--<property name="maxResultSet">524288</property>-->

        <!-- backSocket unit:bytes-->
        <!--<property name="backSocketSoRcvbuf">4194304</property>-->
        <!--<property name="backSocketSoSndbuf">1048576</property>-->
        <!--<property name="backSocketNoDelay">1</property>-->

        <!-- frontSocket-->
        <!--<property name="frontSocketSoRcvbuf">1048576</property>-->
        <!--<property name="frontSocketSoSndbuf">4194304</property>-->
        <!--<property name="frontSocketNoDelay">1</property>-->

        <!-- for join tmp results -->
        <!--<property name="mergeQueueSize">1024</property>-->
        <!--<property name="orderByQueueSize">1024</property>-->
        <!--<property name="joinQueueSize">1024</property>-->

        <!-- if enable the slow query log -->
        <property name="enableSlowLog">0</property>
        <!-- the slow query log location -->
        <!--<property name="slowLogBaseDir">./slowlogs</property>-->
        <!--<property name="slowLogBaseName">slow-query</property>-->
        <!-- the max period for flushing the slow query log from memory to disk  after last time , unit is second -->
        <property name="flushSlowLogPeriod">1</property>
        <!-- the max records for flushing the slow query log from memory to disk after last time -->
        <property name="flushSlowLogSize">1000</property>
        <!-- the threshold for judging if the query is slow , unit is millisecond -->
        <property name="sqlSlowTime">100</property>
        <!-- used for load data,maxCharsPerColumn means max chars length for per column when load data  -->
        <!--<property name="maxCharsPerColumn">65535</property>-->
        <!-- used for load data, because dble need save to disk if loading file contains large size -->
        <!--<property name="maxRowSizeToFile">10000</property>-->

    </system>

    <!-- firewall config -->
    <!--
    <firewall>
    <whitehost>
          <host host="127.0.0.1" user="root"/>
          <host host="0:0:0:0:0:0:0:1" user="root"/>
       </whitehost>
       <blacklist check="true">
       <property name="selelctAllow">false</property>
       </blacklist>
    </firewall>
    -->
    <user name="man1">
        <property name="password">654321</property>
        <property name="manager">true</property>
        <!-- manager user can't set schema-->
    </user>

    <user name="hzero">
        <property name="password">bHaxWqczzmUSil0/mziGTukB+pqPC7NM3E/Qqstd1GT90OQLX9APJLT0toyHEtwr/X3S72LPe98CDe66oN098Q==</property> <!-- 密码为:hzero-->
        <property name="usingDecrypt">1</property>
        <property name="schemas">hzero_platform</property>
    </user>

</dble:server>

2.修改schema.xml
<?xml version="1.0"?>
<!--
  ~ Copyright (C) 2016-2019 ActionTech.
  ~ License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
  -->

<!DOCTYPE dble:schema SYSTEM "schema.dtd">
<dble:schema xmlns:dble="http://dble.cloud/" version="2.0">

    <!-- schema testdb route to database named dn1 in backend-mysql1  -->
	<schema name="hzero_platform" dataNode="dn1">
    </schema>

	<dataNode name="dn1" dataHost="backend-mysql" database="hzero_platform"/>

    <dataHost name="backend-mysql" maxCon="1000" minCon="10" balance="2" switchType="1" slaveThreshold="100">
        <heartbeat>show slave status</heartbeat>
        <writeHost host="MySQLA" url="172.28.8.65:3306" user="hzero" password="hzero">
        </writeHost>
	   <writeHost host="MySQLB" url="172.28.8.61:3306" user="hzero" password="hzero">
        </writeHost>
    </dataHost>
</dble:schema>
3.生成server.xml加密密码

生成工具:/opt/dble/bin/encrypt.sh

修改/opt/dble/bin/encrypt.sh

#!/bin/sh

#set HOME
CURR_DIR=`pwd`
cd `dirname "$0"`/..
APP_HOME=`pwd`
cd $CURR_DIR
if [ -z "$APP_HOME" ] ; then
    echo
    echo "Error: APP_HOME environment variable is not defined correctly."
    echo
    exit 1
fi 

#============run encrypt
input=$1
PASSWORD=${input/password=/""}
RUN_CMD="/bin/java -cp $APP_HOME/lib/dble*.jar com.actiontech.dble.util.DecryptUtil $PASSWORD"
echo "/bin/java -cp $APP_HOME/lib/dble*.jar com.actiontech.dble.util.DecryptUtil password=******"
eval $RUN_CMD
EXIT_STATUS=$?
exit $EXIT_STATUS
#==============================================================================

生成密码:

0:{用户名}:{密码}

例如:

[root@8086449c1aec bin]# ./encrypt.sh 0:hzero:hzero
/bin/java -cp /opt/dble/lib/dble*.jar com.actiontech.dble.util.DecryptUtil password=******
bHaxWqczzmUSil0/mziGTukB+pqPC7NM3E/Qqstd1GT90OQLX9APJLT0toyHEtwr/X3S72LPe98CDe66oN098Q==
4.修改docker_init_start.sh
#!/bin/sh

echo "dble init&start in docker"

sh /opt/dble/bin/dble start
sh /opt/dble/bin/wait-for-it.sh 127.0.0.1:8066

echo "dble init finish"

/bin/bash

5.启动dble

cd /opt/dble/bin
./docker_init_start.sh

同理在dble02(172.28.8.63)相同配置方式。

至此DBLE和Mysql都搭建好了,测试一下

在这里插入图片描述

在这里插入图片描述

四、配置keeplived保证容灾高可用

1.keeplived作用是什么

1.类似于主机备机,本身不具备负载均衡,只能生效一台机器,当且仅当主机器宕机后,才会切换其它机器。

2.自身提供虚拟IP地址,用户只需要关注虚拟IP地址,通过虚拟VIP去访问应用,底层会根据物理机器情况,选择可用机器。

例如有3台机器(01,02,03),我们设置了

01作为主机器,优先级为110

02作为从机器,优先级为100

03作为从机器,优先级为90

当用户配置完keeplived后,会提供一个虚拟VIP假设为04

用户只需访问04,实际每次请求都会走到01去,永远到01,直到01发生意外宕机,此时再访问04,请求会分发到02,同样一直走02,直到02也宕机,才会走03。如果01某个时间经过运维人员修复,恢复运行,因为优先级最高,此时访问04,请求会优先分发到刚恢复的01机器。

原理是这样,下面介绍具体使用,我们以172.28.8.62为例,搭建一份完整案例。172.28.8.63同理

2.安装keeplived

yum install -y keepalived 

3.配置keeplived

cd /etc/keepalived
主机器修改keepalived.conf
! Configuration File for keepalived

global_defs {
   notification_email {
     guchang.pan@hand-china.com
     2660292608@qq.com
   }
   notification_email_from guchang.pan@hand-china.com
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id MYCAT_HA
}

vrrp_script chk_mysql_port {     #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
    script "/opt/chk_mysql.sh"   #这里通过脚本监测
    interval 2                   #脚本执行间隔,每2s检测一次
    weight -5                    #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
    fall 2                    #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
    rise 1                    #检测1次成功就算成功。但不修改优先级
}

vrrp_instance VI_1 {
    state MASTER
    interface ens192
    virtual_router_id 51   #路由器标识,MASTER和BACKUP必须是一致的
    priority 101           #定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级。这样MASTER故障恢复后,就可以将VIP资源再次抢回来 
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.28.8.112/24
    }

    track_script {               
    chk_mysql_port             
   }
}

virtual_server 172.28.8.112 8066 {
    delay_loop 6
    protocol TCP

    real_server 172.28.8.63 8066 {
        notify_down "kill -9 $(cat /var/run/keepalived.pid)" 
        TCP_CHECK { 
            connect_port 8066  
            connect_timeout 3  
            nb_get_retry 3  
            delay_before_retry 3  
        }
    }
}

BACKUP从机器配置修改keepalived.conf

其他BACKUP从机器后面这样修改keepalived.conf(注意:针对其他从机器的keeplived

! Configuration File for keepalived

global_defs {
   notification_email {
     guchang.pan@hand-china.com
     2660292608@qq.com
   }
   notification_email_from guchang.pan@hand-china.com
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id MYCAT_HA
}

vrrp_script chk_mysql_port {     #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
    script "/opt/chk_mysql.sh"   #这里通过脚本监测
    interval 2                   #脚本执行间隔,每2s检测一次
    weight -5                    #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
    fall 2                    #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
    rise 1                    #检测1次成功就算成功。但不修改优先级
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens192
    virtual_router_id 51   #路由器标识,MASTER和BACKUP必须是一致的
    priority 99           #定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级。这样MASTER故障恢复后,就可以将VIP资源再次抢回来 
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.28.8.112/24
    }

    track_script {               
    chk_mysql_port             
   }
}

virtual_server 172.28.8.112 8066 {
    delay_loop 6
    protocol TCP

    real_server 172.28.8.62 8066 {
        notify_down "kill -9 $(cat /var/run/keepalived.pid)" 
        TCP_CHECK { 
            connect_port 8066  
            connect_timeout 3  
            nb_get_retry 3  
            delay_before_retry 3  
        }
    }
}

新建脚本/opt/chk_mysql.sh

作用:检测8066端口是否还被使用,即dble是否宕机,如果宕机,当前节点keeplived自杀,强制停止,让其他节点keeplived生效,进行抢占VIP

#!/bin/bash
counter=$(netstat -na|grep "LISTEN"|grep "8066"|wc -l)
if [ "${counter}" -eq 0 ]; then
    systemctl stop keepalived.service
fi

4.启动keeplived

service keepalived start

关闭keepalived服务
systemctl stop keepalived.service

# 配置开机自启动
systemctl enable keepalived

#查看服务启动情况:
ps -aux |grep keepalived

#查看启动日志:
journalctl -xe

#查看keepalived日志,实时查看最后100行keepalived日志
tail -100f /var/log/messages

另一台机器同理配置,keepalived.conf配置参考上面提供的(BACKUP从机器配置修改keepalived.conf)。

至此高可用集群搭建完毕

5.查看启动进程id
cat /var/run/keepalived.pid

五、演示

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

潘顾昌

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

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

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

打赏作者

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

抵扣说明:

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

余额充值