OpenGauss6.0企业版+keepalived集群高可用部署

OpenGauss集群搭建

节点信息:一主两备

172.17.103.11

172.17.103.12

172.17.103.13

  1. 部署前准备

1.1 环境准备

##主机host设置 

主库:hostnamectl set-hostname apptrace11 

备库1:hostnamectl set-hostname apptrace12

备库2:hostnamectl set-hostname apptrace13

##添加hosts配置

sudo vim /etc/hosts

172.18.202.100 apptrace100

172.18.202.101 apptrace101

172.18.202.102 apptrace102

1.2 关闭SeLinux(所有节点都需要执行)

sed -i 's/^SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

setenforce 0

1.3 关闭防火墙

注:主备库均做如下操作

1.检查防火墙是否关闭

systemctl status firewalld

若防火墙状态显示为active (running),则表示防火墙未关闭

若防火墙状态显示为inactive (dead),则无需再关闭防火墙

2.关闭防火墙并禁止开机重启

systemctl disable firewalld.service

systemctl stop firewalld.service

1.4 设置时区和时间

注:主备库均做如下操作,需要保证主备节点时间同步

timedatectl #查看节点时间

date -s "2024-8-26 15:30:30" #修改时间

1.5 内核修改

##系统资源及内核参数 # vi /etc/security/limits.conf 

echo "* soft nofile 1000000">>/etc/security/limits.conf

echo "* hard nofile 1000000">>/etc/security/limits.conf

echo "* soft nproc unlimited">>/etc/security/limits.conf

echo "* hard nproc unlimited">>/etc/security/limits.conf

内核参数配置

cat>> /etc/sysctl.conf <<EOF 

net.ipv4.tcp_max_tw_buckets = 10000

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_tw_recycle = 1

net.ipv4.tcp_keepalive_time = 30

net.ipv4.tcp_keepalive_intvl = 30

net.ipv4.tcp_retries2 = 12

net.core.wmem_max = 21299200

net.core.rmem_max = 21299200

net.core.wmem_default = 21299200

net.core.rmem_default = 21299200

kernel.sem = 250 6400000 1000 25600

vm.min_free_kbytes = 813306

kernel.shmall = 1152921504606846720

kernel.shmmax = 18446744073709551615

EOF

sysctl -p  # 使内核参数生效

1.5 关闭透明大页

# 使用root用户各服务器节点均执行 

echo never > /sys/kernel/mm/transparent_hugepage/defrag

echo never > /sys/kernel/mm/transparent_hugepage/enabled

chmod +x /etc/rc.d/rc.local

grep Huge /proc/meminfo  #HugePages_Total:显示0 表示设置成功

1.6 python安装(非必须)

cd /opt

 tar -zxvf Python-3.6.15.tgz

 cd Python-3.6.15/

 ./configure --prefix=/usr/local/python3 --enable-shared

编译安装

 make -j4

 make install

注意:make编译时间比较长,耐心等待

OS上设置python的软连接

ln -s /usr/local/python3/bin/python3.6 /usr/bin/python3

ln -s /usr/local/python3/bin/pip3 /usr/bin/pip

环境校验 python3: error while loading shared libraries: libpython3.6m.so.1.0: cannot open shared object file: No such file or directory

 cp /opt/apptrace/Python-3.6.15/libpython3.6m.so.1.0 /usr/lib64/

python3 -V  #查看版本

1.7 openssl安装(所有节点都需要执行)

openssl version -a  #查看openssl版本

如果查看的openssl版本低于1.1.1版本需要更新openssl,否则安装执行后会报./gs_ctl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory错误

1.7.1 解压openssl

tar -zxvf openssl-1.1.1i.tar.gz

1.7.2 切换到解压好的openssl目录

cd /opt/openssl-1.1.1i

1.7.3 配置openssl安装目录

./config --prefix=/usr/local/openssl

1.7.4 编译&&安装

make && make install

等待安装完成即可。

1.7.5 创建软链接

说明:创建的软链接和之前没升级通过whereis openssl保持一致即可。

mv /usr/bin/openssl /usr/bin/openssl_bak

ln -s /usr/local/openssl/bin/openssl /usr/bin/openssl

ln -s /usr/local/openssl/include/openssl /usr/include/openssl

1.7.6 添加动态链接库数据

echo "/usr/local/openssl/lib/" >> /etc/ld.so.conf

检查一下,已经在/etc/ld.so.conf中存在。

1.7.7 更新动态链接库:ldconfig -v

1.7.8验证openssl

查看openssl版本 openssl version -a会显示全面详细信息。

到此openssl升级完成。

 

  1. 2. 一主两备安装
    1. 用户及组创建(主备均操作)

##创建用户组apptrace

 groupadd apptrace

##创建用户组dbgrp下的普通用户omm,并设置密码为Gauss_123

useradd -g apptrace apptrace

passwd apptrace  #用户密码可自定义

##赋予sudo权限

visudo

在root ALL=(ALL)ALL 后添加如下

Apptrace ALL=(ALL) NOPASSWD: ALL

2.2 安装包解压

注意:上传安装包到服务器/opt/openGauss,主节点apptrace用户操作即可

mkdir /opt/apptrace/openGauss

##解压安装包

chmod 755 -R /opt/apptrace/openGauss

cd /opt/apptrace/openGauss

tar -zxvf openGauss-6.0.0-RC1-CentOS-64bit-all.tar.gz

tar -zxvf openGauss-6.0.0-RC1-CentOS-64bit-om.tar.gz

2.3 XML配置文件

安装openGauss前需要创建cluster_config.xml文件。 cluster_config.xml文件包含部署openGauss的服务器信息、安装路径、IP地址以及端口号等。

编辑配置XML文件: vi /opt/openGauss/cluster_config.xml

vi /opt/apptrace/openGauss/cluster_config.xml

注:标红内容均需要修改为搭建集群地址、目录信息;

<?xml version="1.0" encoding="UTF-8"?>

<ROOT>

    <!-- openGauss整体信息 -->

    <CLUSTER>

        <PARAM name="clusterName" value="Cluster_opengauss" />

        <PARAM name="nodeNames" value="apptrace11,apptrace12,apptrace13" />

        <!-- 数据库安装目录,与数据库所需其它路径相互独立,没有包含关系-->

        <PARAM name="gaussdbAppPath" value="/opt/apptrace/gauss/app" />

        <!-- 日志目录-->

        <PARAM name="gaussdbLogPath" value="/opt/apptrace/gauss/log" />

        <!-- 临时文件目录-->

        <PARAM name="tmpMppdbPath" value="/opt/apptrace/gauss/tmp"/>

        <!-- 数据库工具目录-->

        <PARAM name="gaussdbToolPath" value="/opt/apptrace/gauss/om" />

        <!-- 数据库core文件目录-->

        <PARAM name="corePath" value="/opt/apptrace/gauss/corefile"/>

        <!-- 节点IP,与数据库节点名称列表一一对应 -->

        <PARAM name="backIp1s" value="172.17.103.11,172.17.103.12,172.17.103.13"/>

    </CLUSTER>

    <!-- 每台服务器上的节点部署信息 -->

    <DEVICELIST>

        <!-- node1上的节点部署信息 -->

        <DEVICE sn="apptrace11">

            <PARAM name="name" value="apptrace11"/>

            <PARAM name="azName" value="AZ1"/>

            <PARAM name="azPriority" value="1"/>

            <!-- 如果服务器只有一个网卡可用,将backIP1和sshIP1配置成同一个IP -->

            <PARAM name="backIp1" value="172.17.103.11"/>

            <PARAM name="sshIp1" value="172.17.103.11"/>

            <!--CM节点部署信息-->

            <PARAM name="cmsNum" value="1"/>

            <PARAM name="cmServerPortBase" value="15000"/>

            <PARAM name="cmServerListenIp1" value="172.17.103.11,172.17.103.12,172.17.103.13"/>

            <PARAM name="cmServerHaIp1" value="172.17.103.11,172.17.103.12,172.17.103.13"/>

            <PARAM name="cmServerlevel" value="1"/>

            <PARAM name="cmServerRelation" value="apptrace11,apptrace12,apptrace13"/>

            <PARAM name="cmDir" value="/opt/apptrace/gauss/cm"/>

              <!--dn-->

 <PARAM name="dataNum" value="1"/>

                  <PARAM name="dataPortBase" value="15400"/>

                  <PARAM name="dataNode1" value="/opt/apptrace/gauss/data/dn,apptrace12,/opt/apptrace/gauss/data/dn,apptrace13,/opt/apptrace/gauss/data/dn"/>

            <PARAM name="dataNode1_syncNum" value="0"/>

        </DEVICE>

        <!-- node2上的节点部署信息,其中"name"的值配置为主机名称 -->

        <DEVICE sn="apptrace12">

            <PARAM name="name" value="apptrace12"/>

            <PARAM name="azName" value="AZ1"/>

            <PARAM name="azPriority" value="1"/>

            <!-- 如果服务器只有一个网卡可用,将backIP1和sshIP1配置成同一个IP -->

            <PARAM name="backIp1" value="172.17.103.12"/>

            <PARAM name="sshIp1" value="172.17.103.12"/>

            <!-- cm -->

            <PARAM name="cmServerPortStandby" value="15000"/>

            <PARAM name="cmDir" value="/opt/apptrace/gauss/cm"/>

               </DEVICE>

        <!-- node3上的节点部署信息,其中"name"的值配置为主机名称 -->

        <DEVICE sn="apptrace13">

            <PARAM name="name" value="apptrace13"/>

            <PARAM name="azName" value="AZ1"/>

            <PARAM name="azPriority" value="1"/>

            <!-- 如果服务器只有一个网卡可用,将backIP1和sshIP1配置成同一个IP -->

            <PARAM name="backIp1" value="172.17.103.13"/>

            <PARAM name="sshIp1" value="172.17.103.13"/>

            <!-- cm -->

            <PARAM name="cmServerPortStandby" value="15000"/>

            <PARAM name="cmDir" value="/opt/apptrace/gauss/cm"/>

        </DEVICE>

    </DEVICELIST>

</ROOT>

2.4 初始化安装(主备均需要操作)

chmod  -R 755 /opt/apptrace/gauss

cd /opt/apptrace/openGauss

echo '/usr/share/abrt/apport-hook-ccpp %p %s %c %d %P %E' | sudo tee /proc/sys/kernel/core_pattern

#添加环境变量至~/.bash_profile里

export LD_LIBRARY_PATH=/opt/apptrace/openGauss/script/gspylib/clib:$LD_LIBRARY_PATH

export PGHOST=172.17.103.11

export PATH=$PATH:/opt/apptrace/gauss/app/bin

#保存后执行

source ~/.bash_profile

PGHOST=172.17.103.11 此参数需修改为当前机器IP,比如apptrace11机器ip是172.17.103.11,那apptrace12机器ip是172.17.103.12,此参数则需要修改为12。

注:只在主库上做操作即可,确保主库和备库root密码相同,用户和组以及目录授权同时在主备库操作

cd  /opt/apptrace/openGauss/script 

./gs_preinstall -U apptrace -G apptrace -X /opt/apptrace/openGauss/cluster_config.xml --sep-env-file=/home/apptrace/envfile

注:初始化安装会检查安装环境,如监测A1-A14有集群报错,需要先处理报错再往后安装;

2.5 正式安装(主节点执行)

在执行过程中,用户需根据提示输入数据库的密码,密码具有一定的复杂度,为保证正常使用该数据库,请记住输入的数据库密码;

设置的密码要符合复杂度要求:

最少包含8个字符,最多包含16个字符。

不能和用户名、当前密码(ALTER)、或当前密码反序相同。

至少包含大写字母(A-Z)、小写字母(a-z)、数字、非字母数字字符(限定为~!@#$%^&*()-_=+\|[{}];:,<.>/?)四类字符中的三类字符。 

示例:Apptrace123!

ll /opt/apptrace/openGauss/cluster_config.xml

source /home/omm/envfile

echo "source /home/apptrace/envfile" >> ~/.bash_profile

#安装

./gs_install  -X /opt/apptrace/openGauss/cluster_config.xml

示例:

2.6 安装验证

以apptrace用户身份登录服务器。 执行如下命令检查数据库状态是否正常,"cluster_state"显示"Normal"表示数据库可正常使用。

gs_om -t status

gs_om -t status --detail

2.7 数据库登录

gsql -d postgres -p 15400

2.8 集群启动及关闭

gs_om -t stop  #集群启动

gs_om -t start #集群关闭

gs_om -t status --detail #集群查看

  1. Keepalived(所有节点执行)

3.1 安装keepalived(所有节点执行)

ar -zxf keepalived-2.3.1-centos7.9.tar.gz

cd keepalived-2.3.1

./configure --prefix=/usr/local/keepalived    (编译好的包此步骤可忽略)

sudo make install

sudo cp /usr/local/keepalived/sbin/keepalived /etc/init.d/

sudo cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/

sudo cp /usr/local/keepalived/sbin/keepalived /usr/sbin/

编译时如果报截屏错误,需要安装下openssl-devel

命令:sudo yum  -y  install openssl-devel

3.2 添加keepalived信息

(1)主节点keepalived配置

vim /etc/keepalived/keepalived.conf

注意配置: priority 95  #优先级,数字越大优先级越高,建议主节点200,备1节点199,备2节点198(给故障转移修复给出充足空间)

## 全局定义

global_defs {

  router_id Keepalived_openGauss          #运行 keepalived 服务器的一个标识

  script_user apptrace                        #执行脚本的用户

}

## VRRP实例定义

## 通常如果master服务Down掉后backup会变成master,但是当master服务又好了的时候 master此时会抢占VIP,这样就会发生两次数据库切换。

## 建议使用nopreempt参数设置为非抢占模式,此时主库从故障中恢复后,不会从新的主库抢回VIP,但这需要将master和backup的state都设置成backup。

vrrp_instance VI_1 {

  state BACKUP                            #指定Keepalived的角色(BACKUP需大写)

  interface ens192                          #指定 HA 监测的网络接口

  virtual_router_id 16                    #虚拟路由的数字标识,同一个 vrrp_instance 下,MASTER 和 BACKUP 一致

  nopreempt                               #非抢占模式,主库从故障中恢复后,不会从新的主库抢回VIP

  priority 95                            #优先级,备节点需要适当降低优先级

  advert_int 1                            #MASTER 和 BACKUP 负载均衡器同步检查的时间间隔(秒)

  authentication {                        #设置验证码和验证类型

      auth_type PASS

      auth_pass 1111

  }

  virtual_ipaddress {                     #设置虚拟 IP 地址,可以设置多个,每个一行

      172.17.103.201/16

  }

}

## 虚拟服务器定义

virtual_server 172.17.103.201  26000 {        #设置虚拟服务器的 IP 和端口,用空格隔开

  delay_loop 6                             #设置运行情况检查时间,单位是秒

# lb_algo rr                               #负载调度算法(轮询)

# lb_kind DR                               #负载均衡机制(NAT、TUN、DR)

  persistence_timeout 50                   #会话保持时间(秒)

  protocol TCP                             #转发协议类型

   real_server 172.17.103.11 26000 {        #配置服务节点

          weight 100                       #配置服务节点的权重

          notify_down /etc/keepalived/failoverdb.sh #故障响应脚本

          TCP_CHECK {                      #使用TCP_CHECK方式进行健康检查

              connect_timeout 20           #10秒无响应即超时

              delay_before_retry 3         #重试间隔时间

          }

      }

}

创建主节点故障切换脚本

vim /etc/keepalived/failoverdb.sh

#!/bin/bash

echo "Start to failover openGauss database."

pkill keepalived

ssh 172.17.103.12 "su - apptrace -c 'gs_ctl failover -D /opt/apptrace/gauss/data/dn'"

ssh 172.17.103.12 "su - apptrace -c 'gs_om -t refreshconf'"

echo 'Failover operation is completed.'

赋予权限(无需赋予其它权限,权限不对启动后会存在报错)

chmod 600 keepalived.conf failoverdb.sh

  1. 备节点keepalived配置(备节点都需要执行)

vim /etc/keepalived/keepalived.conf

## 全局定义

global_defs {

  router_id Keepalived_openGauss          #运行 keepalived 服务器的一个标识

  script_user apptrace                        #执行脚本的用户

}

vrrp_script check_server {

   script "/etc/keepalived/check.sh"

   interval 5

   timeout 10

}

## VRRP实例定义

## 通常如果master服务Down掉后backup会变成master,但是当master服务又好了的时候 master此时会抢占VIP,这样就会发生两次数据库切换。

## 建议使用nopreempt参数设置为非抢占模式,此时主库从故障中恢复后,不会从新的主库抢回VIP,但这需要将master和backup的state都设置成backup。

vrrp_instance VI_1 {

  state BACKUP                            #指定Keepalived的角色(BACKUP需大写)

  interface ens192                          #指定 HA 监测的网络接口

  virtual_router_id 16                    #虚拟路由的数字标识,同一个 vrrp_instance 下,MASTER 和 BACKUP 一致

  nopreempt                               #非抢占模式,主库从故障中恢复后,不会从新的主库抢回VIP

  priority 94                            #优先级,备节点需要适当降低优先级

  advert_int 1                            #MASTER 和 BACKUP 负载均衡器同步检查的时间间隔(秒)

  authentication {                        #设置验证码和验证类型

      auth_type PASS

      auth_pass 1111

  }

  virtual_ipaddress {                     #设置虚拟 IP 地址,可以设置多个,每个一行

      172.17.103.201/16

  }

   # 调用 check_server 脚本

         track_script {

             check_server

   }

}

## 虚拟服务器定义

virtual_server 172.17.103.201  26000 {        #设置虚拟服务器的 IP 和端口,用空格隔开

  delay_loop 6                             #设置运行情况检查时间,单位是秒

# lb_algo rr                               #负载调度算法(轮询)

# lb_kind DR                               #负载均衡机制(NAT、TUN、DR)

  persistence_timeout 50                   #会话保持时间(秒)

  protocol TCP                             #转发协议类型

   real_server 172.17.103.12 26000 {        #配置服务节点

          weight 60                       #配置服务节点的权重

          notify_down /etc/keepalived/failoverdb.sh #故障响应脚本

          TCP_CHECK {

              connect_timeout 20           #10秒无响应即超时

              delay_before_retry 3         #重试间隔时间

          }

      }

}

创建备节点故障切换脚本 (注意在将备节点扩展至第二个时(即构建一主两备架构),需在备节点2脚本中明确包含主节点的IP地址,以确保实现主备之间的有效循环

vim /etc/keepalived/failoverdb.sh

#!/bin/bash

echo "Start to failover openGauss database."

pkill keepalived

ssh 172.17.103.13 "su - apptrace -c 'gs_ctl failover -D /opt/apptrace/gauss/data/dn'"

ssh 172.17.103.13 "su - apptrace -c 'gs_om -t refreshconf'"

echo 'Failover operation is completed.'

备节点健康检查脚本 (注意在将备节点扩展至第二个时(即构建一主两备架构),需在备节点2脚本中明确包含主节点的IP地址,以确保实现主备之间的有效循环

vim /etc/keepalived/check.sh

ssh 172.17.103.11   "su - apptrace -c \"gsql -d postgres -p 26000 -t -A -c 'select 1;'\""

赋予权限(无需赋予其它权限,权限不对启动后会存在报错)

chmod 600 keepalived.conf failoverdb.sh check.sh

3.3 启动keepalived(所有节点执行)

sudo systemctl start keepalived   #主节点先执行,在依次在备1和备2节点执行

执行完成后,在主节点使用ip a查看是否已有VIP地址

3.4 修改 postgresql.conf(所有节点执行)

在安装的/opt/apptrace/gauss/data/dn目录,修改以下参数

listen_addresses = '*'

local_bind_address = '0.0.0.0'

password_encryption_type = 1

hot_standby = on

3.5 修改 pg_hba.conf(所有节点执行)

在安装的/opt/apptrace/gauss/data/dn/pg_hba.conf文件中,添加其它节点的访问权限:

#根据需求添加对应ip

host    all             all             172.17.103.11/0         md5

host    all             all             172.17.103.12/0        md5

host    all             all             172.17.103.13/0        md5

host    all             all             172.18.201.30/0        md5

host    all             all             0.0.0.0/0         md5

host    replication     repl             172.17.103.11/0         md5

host    replication     repl            172.17.103.12/0        md5

host    replication     repl             172.17.103.13/0        md5

host    replication    repl    0.0.0.0/0    md5

#172.18.201.30为应用的服务地址

修改后重启服务

gs_om -t stop && gs_om -t start

3.6 openGauss创建非apptrace用户登录

由于oepnGauss限制初始用户登录,需要创建个非apptrace

#创建复制流所用的数据库

gsql -U apptrace -d postgres -c "

CREATE ROLE repl WITH REPLICATION LOGIN PASSWORD 'Admin123!';

ALTER USER repl WITH Replication;

ALTER USER repl WITH Sysadmin;"

3.7 测试并检查复制流状态

    1. 检查复制流状态

查看主节点复制流状态

gsql -h 172.17.103.11 -p 15400 -U apptrace -d postgres -c "SELECT pid, usename, application_name, client_addr, state, sync_state FROM pg_stat_replication;"

结果:

    1. 测试复制流是否正常

创建表格

psql -h 172.17.103.11 -p 15400 -U apptrace -d postgres -c "CREATE TABLE test_table (id SERIAL PRIMARY KEY,name VARCHAR(100))";

添加数据

psql -h 172.17.103.11 -p 15400 -U apptrace -d postgres -c "INSERT INTO test_table (name) VALUES ('Alice'), ('Bob'), ('Charlie');"  #可以多执行几次

查看数据是否添加成功

psql -h 172.17.103.11 -p  15400 -U apptrace -d postgres -c "SELECT * FROM test_table;"

查看备1和备2节点是否成功同步数据

psql -h 172.17.103.12 -p 15400 -U repl  -d postgres -c "SELECT * FROM test_table;"

psql -h 172.17.103.13 -p 15400 -U repl  -d postgres -c "SELECT * FROM test_table;"

  1. 故障测试
    1. 停止主节点服务

ps -ef | grep gauss

kill 掉服务id

停止keealived服务

sudo systemctl stop keepalived.service

停止主节点的openGauss后,vip会切换到备1节点机器上

使用ip a命令查看VIP是否已转移到备1节点

原主节点:

原备1节点:

切换过去后原主节点openGauss会自动拉起来

    1. 查看是否切换正常

查看是否已切换成主节点

gsql -h 172.17.103.12  -p 15400  -U repl  -d postgres -c "SELECT pg_is_in_recovery()"

#  f为主节点,t为备节点

添加数据

psql -h 172.17.103.12 -p 15400 -U apptrace -d postgres -c "INSERT INTO test_table (name) VALUES ('Alice'), ('Bob'), ('Charlie');"  #可以多执行几次

查看数据是否添加成功

psql -h 172.17.103.12 -p  15400 -U apptrace -d postgres -c "SELECT * FROM test_table;"

查看备1和备2节点是否成功同步数据

psql -h 172.17.103.11 -p 15400 -U repl  -d postgres -c "SELECT * FROM test_table;"

psql -h 172.17.103.13 -p 15400 -U repl  -d postgres -c "SELECT * FROM test_table;"

  1. 故障恢复(在原主节点上执行)
5.1 修改原主节点的keepalived信息

sudo vim /etc/keepalived/keepalived.conf

#将priority 参数调整到比备2节点要高

priority 197

5.2  调整后重启keepalived

sudo systemctl restart keepalived.service

由于部署包的服务进程带有管理工具,服务挂掉后会自动拉起,无需手动添加启动;

添加数据

psql -h 172.17.103.12 -p 15400 -U apptrace -d postgres -c "INSERT INTO test_table (name) VALUES ('Alice'), ('Bob'), ('Charlie');"  #可以多执行几次

查看数据是否添加成功

psql -h 172.17.103.12 -p  15400 -U apptrace -d postgres -c "SELECT * FROM test_table;"

查看备1和备2节点是否成功同步数据

psql -h 172.17.103.11 -p 15400 -U repl  -d postgres -c "SELECT * FROM test_table;"

psql -h 172.17.103.13 -p 15400 -U repl  -d postgres -c "SELECT * FROM test_table;"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冬零六

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

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

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

打赏作者

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

抵扣说明:

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

余额充值