kafka-5-常用命令和异常解决

1 常用命令

1.1 集群相关命令

1.1.1 启动kafka

一、单独安装zookeeper

(1)启动zookeeper
绝对路径
/usr/local/zookeeper/bin/zkServer.sh start 
/usr/local/zookeeper/conf/zoo.cfg
或者
zkServer.sh start启动
zkServer.sh status查看状态
zkServer.sh stop停止
(2)启动kafka
绝对路径
/usr/local/kafka/bin/kafka-server-start.sh -daemon 
/usr/local/kafka/config/server0.properties
或者
cd /usr/local/kafka_2.12-2.2.0/
nohup ./bin/kafka-server-start.sh切换路径 
	./config/server.properties >> /tmp/kafkaoutput.log 2>&1 &

二、自带的zookeeper

cd /usr/local/kafka_2.13-3.4.0/
(1)启动zookeeper
后台方式
nohup ./bin/zookeeper-server-start.sh ./config/zookeeper.properties >> /tmp/zookeeperoutput.log 2>&1 &
(2)启动kafka
后台方式
nohup ./bin/kafka-server-start.sh ./config/server.properties >> /tmp/kafkaoutput.log 2>&1 &

(3)查看进程
jps
3297 Jps
2137 QuorumPeerMain
2684 Kafka

(4)停止kafka
cd /usr/local/kafka_2.13-3.4.0/
停止kafka
kafka-server-stop.sh
停止zookeeper
zookeeper-server-stop.sh


1.1.2 查看集群的broker id

zkCli.sh ls /brokers/ids

1.1.3 集群之间拷贝数据

集群之间拷贝数据:

bin/Kafka-run-class.sh Kafka.tools.MirrorMaker 
--consumer.config consumer-1.properties 
--consumer.config consumer-2.properties 
--producer.config producer.properties 
--whitelist your-Topic

1.2 主题相关命令

1.2.1 查看集群中的topic

方法一
kafka-topics.sh --list --zookeeper pda1:2181
方法二
zkCli.sh ls /brokers/topics

1.2.2 创建topic

kafka-topic.sh --create
--zookeeper pda1:2181
--replication-factor 1
--partitions 1
--topic test

1.2.3 查看topic详细信息

(1)查看集群中的topic
kafka-topics.sh --list --zookeeper myname:2181
(2)查看topic详细信息
kafka-topics.sh --describe --zookeeper myname:2181 --topic test
(3)删除topic
kafka-topics.sh --delete --zookeeper myname:2181 --topic test

在这里插入图片描述

1.3 控制台生产消费

(1)启动控制台生产者
kafka-console-producer.sh --broker-list myname:9092 --topic test

(2)启动控制台消费者
kafka-console-consumer.sh --bootstrap-server myname:9092 --topic test --from-beginning

(3)查看消费者的offset
kafka在0.9.0.0版本之后,kafka.tools.ConsumerOffsetChecker已经不支持了。
应该使用kafka.admin.ConsumerGroupCommand
(或bin/kafka-consumer-groups.sh脚本)来管理消费者组
(3-1)查看所有组
kafka-consumer-groups.sh --bootstrap-server myname:9092 --list
(3-2)然后查看具体组的详细描述信息,就可以看到offset的情况
kafka-consumer-groups.sh --bootstrap-server myname:9092 --describe --group groupname

1.4 查看offset

查看topic的offset和消费者组的offset。

(1)查看某个topic的offset
kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list myubuntu:9092 --topic test
输出test:0:2
分区0的偏移量2

(2)查看消费者组对某个topic的消费情况
(2-1)查看consumer group列表,使用--list参数
kafka-consumer-groups.sh  --bootstrap-server myubuntu:9092 --list

(2-2)查看特定consumer group 详情,使用--group与--describe参数
kafka-consumer-groups.sh  --bootstrap-server myubuntu:9092 --group TestGroup111 --describe

(3)举例如下
kafka-consumer-groups.sh --bootstrap-server 192.168.108.201:9092 --list

kafka-consumer-groups.sh --bootstrap-server 192.168.108.201:9092 --group group1 --describe

(4)注意
如果是一个消费者组,开了多个进程,则CONSUMER-ID会出来多个,例如python。
注意Spark Streaming消费kafka的Direct模式,自动多线程。

2 监控管理命令

2.1 查看偏移量

(1)查看某个topic的offset

kafka-run-class.sh kafka.tools.GetOffsetShell 
	--broker-list 10.70.70.74:9092 
	--topic E2ALARM_IN

输出如下
E2ALARM_IN:0:53

(2)查看消费者组对某个topic的消费情况
此时也可以看到该toipc的偏移量
(2-1)查看consumer group列表,使用- -list参数

# kafka-consumer-groups.sh  
	--bootstrap-server hbak1:9092 
	--list
输出如下
group-204
d9a7211e-579f-4589-bdaf-62f884c4e435
consumer1

(2-2)查看特定consumer group 详情,使用- -group与- -describe参数

# kafka-consumer-groups.sh  
	--bootstrap-server hbak1:9092 
	--group consumer1 
	--describe
输出如下
分区2,当前偏移量为2
分区1,当前偏移量为0
分区0,当前偏移量为13

在这里插入图片描述
参数如下

TOPIC			主题名
PARTITION		分区
CURRENT-OFFSET	消费者组的当前偏移量
LOG-END-OFFSET	topic的最新偏移量
LAG				消费者的延迟偏移量
CONSUMER-ID
HOST
CLIENT-ID

如果是一个消费者组,开了多个进程,则CONSUMER-ID会出来多个,例如python。
注意Spark Streaming消费kafka的Direct模式,自动多线程。

2.2 删除topic步骤

删除kafka topic及其数据,严格来说并不是很难的操作。但是,往往给kafka 使用者带来诸多问题。项目组之前接触过多个开发者,发现都会偶然出现无法彻底删除kafka的情况。

cd /usr/local/kafka_2.13-3.4.0/
(1)启动zookeeper
bin/zookeeper-server-start.sh config/zookeeper.properties
后台方式
nohup ./bin/zookeeper-server-start.sh ./config/zookeeper.properties >> /tmp/zookeeperoutput.log 2>&1 &
(2)启动kafka
bin/kafka-server-start.sh config/server.properties
后台方式
nohup ./bin/kafka-server-start.sh ./config/server.properties >> /tmp/kafkaoutput.log 2>&1 &

(3)查看进程
jps
3297 Jps
2137 QuorumPeerMain
2684 Kafka

(4)停止kafka
cd /usr/local/kafka_2.13-3.4.0/
停止kafka
kafka-server-stop.sh
停止zookeeper
zookeeper-server-stop.sh

2.2.1 删除步骤

首先确保,配置文件,/usr/local/kafka_2.12-2.2.0/config/server.properties
delete.topic.enable=true

第一步:bin/kafka-topics.sh --bootstrap-server myubuntu:9092 --delete --topic topicName

第二步:进入zookeeper命令行,删除三个目录
(1)rmr /brokers/topics/market 
(2)rmr /admin/delete_topics/market 
(3)rmr /config/topics/market

第三步:重启kafka
然后重建同名topic的时候/brokers/topics/market目录下有partitions/0了。

重启kafka
nohup ./bin/kafka-server-start.sh ./config/server.properties >> /tmp/kafkaoutput.log 2>&1 &

第一步
(1)如果需要被删除topic 此时正在被程序 produce和consume,则这些生产和消费程序需要停止。因为如果有程序正在生产或者消费该topic,则该topic的offset信息一致会在broker更新,调用kafka delete命令则无法删除该topic。

(2)同时,需要设置 auto.create.topics.enable = false,默认设置为true。
如果设置为true,则producer或者fetch不存在的topic也会自动创建这个topic。
这样会给删除topic带来很多意向不到的问题。

所以,这一步很重要,设置auto.create.topics.enable = false,并认真把生产和消费程序彻底全部停止。

第二步:
server.properties设置delete.topic.enable=true
如果没有设置 delete.topic.enable=true,则调用kafka 的delete命令无法真正将topic删除,而是显示(marked for deletion)

第三步:
调用命令删除topic:

bin/kafka-topics.sh --bootstrap-server myubuntu:9092 --delete --topic topicName

第四步:
删除kafka存储目录(server.properties文件log.dirs配置,默认为"/data/kafka-logs")相关topic的数据目录。

注意:如果kafka有多个broker,且每个broker 配置了多个数据盘(比如 /data/kafka-logs,/data1/kafka-logs …),且topic也有多个分区和replica,则需要对所有broker的所有数据盘进行扫描,删除该topic的所有分区数据。

一般而言,经过上面4步就可以正常删除掉topic和topic的数据。
但是,如果经过上面四步,还是无法正常删除topic,则需要对kafka在zookeeper的存储信息进行删除。

具体操作如下:(注意:以下步骤里面,kafka在zk里面的节点信息是采用默认值,如果你的系统修改过kafka在zk里面的节点信息,则需要根据系统的实际情况找到准确位置进行操作)。

第五步:
找一台部署了zk的服务器,
(1)使用命令:bin/zkCli.sh -server 【zookeeper server:port】登录到zk shell,
然后找到topic所在的目录:ls /brokers/topics,找到要删除的topic,
然后执行命令:deleteall /brokers/topics/【topic name】即可,此时topic被彻底删除。

(2)如果topic 是被标记为 marked for deletion,
则通过命令 ls /admin/delete_topics,找到要删除的topic,
然后执行命令:rmr /admin/delete_topics/【topic name】

(3)备注:网络上很多其它文章还说明,需要删除topic在zk上面的消费节点记录、配置节点记录,比如:
deleteall /consumers/【consumer-group】
deleteall /config/topics/【topic name】

其实正常情况是不需要进行这两个操作的,如果需要,那都是由于操作不当导致的。比如第一步停止生产和消费程序没有做,第二步没有正确配置。也就是说,正常情况下严格按照第一步到第五步的步骤,是一定能够正常删除topic的。

第六步:
完成之后,调用命令:./bin/kafka-topics.sh --list --bootstrap-server myubuntu:9092
查看现在kafka的topic信息,正常情况下删除的topic就不会再显示。
但是,如果还能够查询到删除的topic,则重启zk和kafka即可。

2.2.2 示例一

kafka tools里创建主题mytopic,分区1个,复制因子1,然后写入一些数据。
会自动出现/var/kafka-logs/mytopic-0。
第一步:停止所有消费者和生产者。
第二步:完成设置。
第三步:执行删除。

kafka-topics.sh --list --bootstrap-server myubuntu:9092

kafka-topics.sh --delete --bootstrap-server myubuntu:9092 --topic test
发现/tmp/kafka-logs/test-0也自动被删除
应该是设置为delete.topic.enable=true的缘故

第四步:已自动完成。
第五步:感兴趣可以查看一下

zkCli.sh -server 10.70.70.74:2181 ls /
zkCli.sh ls /admin/delete_topics无mytopic
zkCli.sh ls /brokers/topics有mytopic
zkCli.sh ls /config/topics有mytopic
deleteall /brokers/topics/mytopic
deleteall /config/topics/mytopic

第六步:

kafka-topics.sh --list --zookeeper 10.70.70.74:2181
重启kafka
nohup ./bin/kafka-server-start.sh ./config/server.properties >> /tmp/kafkaoutput.log 2>&1 &

2.2.3 示例二

二、举例如下

(1)查看已有topic
kafka-topics.sh --zookeeper 10.70.70.74:2181 --list
(2)删除topic
kafka-topics.sh --zookeeper 10.70.70.74:2181 --delete --topic E2ALARM_IN
输出如下
Topic E2ALARM_IN is marked for deletion.
Note: This will have no impact if delete.topic.enable is not set to true.
(3)重复删除topic
kafka-topics.sh --zookeeper 10.70.70.74:2181 --delete --topic E2ALARM_IN
输出如下
Topic E2ALARM_IN is already marked for deletion.
(4)再次查看topic
kafka-topics.sh --zookeeper 10.70.70.74:2181 --list
输出如下
E2ALARM_IN - marked for deletion

修改配置文件

cd /usr/local/kafka_2.12-2.2.0/config/
vi server.properties
输入
delete.topic.enable=true

连接zookeeper

zkCli.sh -server 10.70.70.74:2181
删除三个目录
deleteall /brokers/topics/market 
deleteall /admin/delete_topics/market 
deleteall /config/topics/market
例如
[zk: 10.70.70.74:2181(CONNECTED) 4] deleteall /admin/delete_topics/E2ALARM_IN
[zk: 10.70.70.74:2181(CONNECTED) 5] deleteall /brokers/topics/E2ALARM_IN
[zk: 10.70.70.74:2181(CONNECTED) 6] deleteall /config/topics/E2ALARM_IN

在这里插入图片描述
三、彻底删除Kafka中的所有Topic

(0)关闭Kafka

(1)登录zookeeper客户端
./bin/zkCli.sh
ls /brokers/topics查看topic信息
deleteall /brokers/topics删除所有topic

(2)删除kafka日志文件
cd /usr/local/kafka_2.12-2.2.0/logs
rm -rf kafka/logs/* 
然后删除log.dirs文件夹下的所有数据文件
查看配置log.dirs=/var/kafka-logs
rm -rf /var/kafka-logs/*

(3)启动Kafka

3 异常解决

3.1 消费者consumer无法消费的异常

(1)异常现象:
服务器:record is corrupt(记录损坏)不明原因,有可能磁盘空间不足导致,导致消费者无法正常消费消息,卡在某一个offset不能继续消费。
(2)解决办法:
先停掉消费者程序,杀掉进程(不可关闭kafka服务)然后手动设置偏移量,跳过卡在的offset位置。
进入kafka目录,命令:
#bin/kafka-consumer-groups.sh --bootstrap-server ip:9092 --group groupName --reset-offsets --to-offset 1000 --topic topicName --execute
然后重启消费者程序。
(3)举例
在这里插入图片描述当前消费到的偏移量
实际已经写入的偏移量
延迟的偏移量

查看特定consumer group 详情,使用–group与–describe参数
#kafka-consumer-groups.sh --bootstrap-server hbak1:9092 --group consumer1 --describe
在这里插入图片描述分区2,当前偏移量为2
分区1,当前偏移量为0
分区0,当前偏移量为13

(3-1)设为offset10
#kafka-consumer-groups.sh --bootstrap-server hbak1:9092 --group consumer1 --re set-offsets --to-offset 10 --topic zb --execute
(3-2)设为offset0
#kafka-consumer-groups.sh --bootstrap-server hbak1:9092 --group consumer1 --re set-offsets --to-offset 0 --topic zb --execute
在这里插入图片描述从图中可以看出,如果设置偏移量为10。
分区2,偏移量会被设置为2
分区1,偏移量会被设置为0
(3-3)然后运行如下的程序
就会从偏移量位置开始消费了。

from kafka import KafkaConsumer

consumer = KafkaConsumer('zb', bootstrap_servers=['IP:9092'],group_id = "consumer1")
for msg in consumer:
    print((msg.value).decode('utf8'))

3.2 kafka的broker异常停止

(1)异常信息
[2020-11-14 03:19:25,498] INFO [ReplicaManager broker=0] Stopping serving replicas in dir /usr/local/kafka-logs (kafka.server.ReplicaManager)
[2020-11-14 03:19:25,498] ERROR Uncaught exception in scheduled task ‘kafka-log-start-offset-checkpoint’ (kafka.utils.KafkaScheduler)
org.apache.kafka.common.errors.KafkaStorageException: Error while writing to checkpoint file /usr/local/kafka-logs/log-start-offset-checkpoint
Caused by: java.io.FileNotFoundException: /usr/local/kafka-logs/log-start-offset-checkpoint.tmp (Too many open files)
在这里插入图片描述[2020-11-14 03:19:25,598] ERROR Shutdown broker because all log dirs in /usr/local/kafka-logs have failed (kafka.log.LogManager)
在这里插入图片描述 ERROR Shutdown broker because all log dirs in…have failed

kafka删除配置的log.dirs目录后,重启服务,报错如上。

解决方案:除了删除kafka该目录内容外,还需要删除zookeeper配置的dataDir目录内容,再重启zookeeper和kafka服务。

如果是重要数据,删除数据之前注意备份。

3.3 Zookeeper 3.5启动时 8080端口被占用

在这里插入图片描述发现8080端口被占用,通过查阅Zookeeper3.5的官方文档,发现这是Zookeeper3.5的新特性:这是Zookeeper AdminServer,默认使用8080端口,它的配置属性如下:
在这里插入图片描述
解决方式:修改在zoo.cfg中修改AdminServer的端口: admin.serverPort=8888

保存后,再次启动,Zookeeper启动成功。

3.4 kafka消费者报错INVALID_FETCH_SESSION_EPOCH

(1)警告信息

%2020-12-03 13:00:03:244 INFO  [org.springframework.kafka.KafkaListenerEndpointContainer#1-0-C-1]
 [o.a.k.c.FetchSessionHandler] - [Consumer clientId=consumer-4, groupId=realtime1] 
 Node 0 was unable to process the fetch request with (sessionId=1423337916, epoch=1079): 
 INVALID_FETCH_SESSION_EPOCH.

报错时,消费速率大大的减慢。
(2)问题原因
kafka的segement是可以滚动的,比如配置了
“log.roll.hours”: 24
那么每24小时就会滚动一次
或者配置了
“log.retention.hours”: 48
48小时以前的就会被删除
每次kafka滚动或者删除时消费者就会报这个错
(3)解决方案
这是一个kafka的bug,在高版本修复。2.0.0及之前的版本有问题,升级到2.0.4之后解决了这个问题。升级后虽然会继续报错,但不会影响任何东西。

3.5 kafka默认__consumer_offsets自动创建失败

kafka在0.10.x版本后默认将消费者组的位移提交到自带的topic__consumer_offsets里面,当有消费者第一次消费kafka数据时就会自动创建,它的副本数不受集群配置的topic副本数限制,分区数默认50(可以配置),默认压缩策略为compact。

因为创建kafka的topic时可以通过命令指定。

kafka-topic.sh --create
--zookeeper pda1:2181
--replication-factor 1
--partitions 1
--topic test

也会在客户端未指定一些参数时,使用默认参数。

broker.id=1
listeners=PLAINTEXT://pda1:9092
log.dir=/usr/local/kafka/datalog
num.partitions=5
log.retention.hours=24
zookeeper.connect=pda1:2181
zookeeper.connection.timeout.ms=60000
offsets.topic.replication.factor=1

注意offsets.topic.replication.factor=1这个参数跟broker的个数相关,如果只有一个broker则只能设为1。否则会出问题,默认的__consmer_offsets不会自动创建。

3.6 Rebalance触发条件

rebalance触发的条件有以下3个。
(1)组成员发生变更,比如新consumer加入组,或已有consumer主动离开组,再或是已有consumer崩溃时则触发rebalance。
#tail -f server.log
在这里插入图片描述一般在重新启用程序时,会发生一次rebalance。

(2)组订阅topic数发生变更,比如使用基于正则表达式的订阅,当匹配正则表达式的新topic被创建时则会触发rebalance。

(3)组订阅topic的分区数发生变更,比如使用命令脚本增加了订阅topic的分区数。

真实应用场景中引发rebalance最常见的原因就是违背了第一个条件,特别是consumer崩溃的情况。这里的崩溃不一定就是指consumer进程“挂掉”或consumer进程所在的机器宕机。当consumer无法在指定的时间内完成消息的处理,那么coordinator就认为该consumer已经崩溃,从而引发新一轮rebalance。

相关的配置参数如下:

3.6.1 max.poll.interval.ms

max.poll.interval.ms参数用于指定consumer两次poll的最大时间间隔(默认5分钟),如果超过了该间隔consumer client会主动向coordinator发起LeaveGroup请求,触发rebalance;然后consumer重新发送JoinGroup请求。

max.poll.interval.ms默认值是5分钟,如果需要加大时长就需要给这个参数重新赋值。为什么要修改这个参数:因为第一次接收kafka数据,需要加载一堆基础数据,大概执行时间要8分钟,而5分钟后,kafka认为我没消费,又重新发送,导致我这边收到许多重复数据,所以我需要调大这个值,避免接收重复数据
max.poll.interval.ms = 600000

使用建议
(1)实际应用中,消费到的数据处理时长不宜超过max.poll.interval.ms,否则会触发rebalance。
(2)如果处理消费到的数据耗时,可以尝试通过减小max.poll.records的方式减小单次拉取的记录数(默认是500条)。

max.poll.records
该属性用于控制单次调用 call() 方法能够返回的记录数量,可以帮你控制在轮询里需要处理的数据量。

session.timeout.ms

该属性指定了消费者在被认为死亡之前可以与服务器断开连接的时间,默认是 3s。

如果消费者没有在 session.timeout.ms 指定的时间内发送心跳给群组协调器,就被认为已经死亡,协调器就会触发再均衡,把它的分区分配给群组里的其他消费者。

该属性与 heartbeat.interval.ms 紧密相关。heartbeat.interval.ms 指定了 poll() 方法向协调器发送心跳的频率,session.timeout.ms 则指定了消费者可以多久不发送心跳。

所以,一般需要同时修改这两个属性,heartbeat.interval.ms 必须比 session.timeout.ms 小,一般是 session.timeout.ms 的三分之一。如果session.timeout.ms 是 3s,那么 heartbeat.interval.ms 应该是 1s。把 session.timeout.ms 值设得比默认值小,可以更快地检测和恢复崩溃的节点,不过长时间的轮询或垃圾收集可能导致非预期的再均衡。把该属性的值设置得大一些,可以减少意外的再均衡,不过检测节点崩溃需要更长的时间。

3.7 kafka生产中消费速度慢的问题

最近在生产中,发现消费速度跟不上生产速度,kafka号称高吞吐,难道是kafka吐的太慢了?后来查了很多资料,发现是自己的消费者消费能力不行导致。

生产者一般不会有啥问题,因为是写进kafka,数据如果要处理的话,处理中的数据和kafka还没关系,等数据处理完要最终写入kafka的时候,这时候才是kafka吞的时候,一般不会有什么问题。

而消费者经常会有问题,大部分时候不是kafka吐数据能力不行,而是自己写的消费数据的程序不行,这个消费能力会受到比较多的因素影响,比如消费了一条数据就要把这条数据发给第三方接口,或者要经过复杂的逻辑处理等。这样一条数据消费完了才能继续消费下条数据。所以说要向实现消费追上甚至超过生产能力的话,就要多线程消费,批量消费。

(1)如果是Kafka消费能力不足,则可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。(两者缺一不可)
(2)如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间<生产速度),使处理的数据小于生产的数据,也会造成数据积压。

多线程消费:
既然一个线程消费不过来,那么就多开线程,开十个线程,消费能力就提高了10倍。但前提是,要消费的topic的partition数也要相应的提高到10(partition数的大小决定最大消费线程数)。
举个例子:一个topic类似于一个蓄水池,而partition则是把这个蓄水池分成多个不同的小蓄水池,一个topic默认一个partition,而一个消费者就是一个人在这蓄水池取水,而这时候说的消费能力不足就是这个人取水的速度慢于蓄水池进水的速度,这样数据就会一直增加。
解决办法:
(1)提高这个人取水的速度(但这在实际生产中一般都是有上限的)
(2)多个一样的人一起取水(也就是上面说的多线程了),但是一个蓄水池(topic)只有一个分区(partition)开十个消费者线程(consumer )也是没用的,因为一个蓄水池只能同时由一个人来取水,其他九个就空闲了。而一个蓄水池分成十个小蓄水池后但只有一个消费者同样也是没用的,这个消费者的消费能力固定且要负责十个蓄水池的取水。所以分区消费者数量一样是合理的。
批量消费:
一次消费一批数据,然后在封装处理,总比一次消费一条数据来得快,但要注意,处理这一批数据的时间可能比处理一条数据的时间来的久,如果处理时间太久,超过了kafka的认定时间,kafka就会认为这个消费者挂了,从而踢掉重新分配一个消费者。
处理方式可以是:
(1)一次不拉过多的数据。
(2)kafka认定消费者挂了的时间设置久点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

皮皮冰燃

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

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

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

打赏作者

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

抵扣说明:

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

余额充值