为了账号安全,请及时绑定邮箱和手机立即绑定

分布式集群入门:新手指南

概述

分布式集群是一种将多个计算资源组合在一起,协同工作的系统,能够实现数据的并行处理、高可用性和负载均衡等功能。本文将详细介绍分布式集群入门知识,包括其基本概念、应用场景和优势。通过多个示例代码和配置步骤,帮助读者更好地理解和搭建分布式集群。

分布式集群简介

分布式集群是一种将多个计算资源组合在一起,形成一个协同工作的系统。通过分布式集群,可以实现数据的并行处理、高可用性、负载均衡等功能。本节将从概念入手,介绍分布式集群的基本知识。

什么是分布式集群

分布式集群是一种计算机网络系统,它由多个计算节点组成,通过网络连接在一起,协同完成任务。在分布式集群中,每个节点都是一个独立的计算机系统,可以运行自己的操作系统和应用程序。节点之间通过网络进行通信和协作,共同完成数据处理、计算任务等。

分布式集群的核心在于“分布式”和“集群”。分布式指的是计算资源的分布性,计算任务可以分布在多个节点上并行处理;而集群则是指这些分布式节点协同工作,形成一个整体,共同完成任务。

分布式集群系统的主要特点包括:

  • 可扩展性:通过增加更多的节点,可以线性地增加系统处理能力和存储空间。
  • 高可用性:当某个节点故障时,其他节点可以接管其任务,保证系统的持续运行。
  • 负载均衡:通过合理分配任务,可以均衡每个节点的工作负担,避免部分节点过于繁忙而其他节点空闲。
  • 容错性:分布式系统设计中考虑了节点故障情况,通过冗余和备份机制保证数据的安全性。
分布式集群的应用场景

分布式集群广泛应用于各个领域,下面列出了几个典型的场景:

  • 云计算:大规模数据处理和计算任务,例如大数据分析、机器学习模型训练等。
  • 网站后端:提高网站的响应速度和稳定性,处理大量并发请求。
  • 数据库集群:提高数据库读写速度和数据安全性,实现数据的冗余备份。
  • 文件存储:通过分布式文件系统提供大规模文件存储服务,如Google的GFS、Hadoop的HDFS等。
  • 游戏服务器:为在线多人游戏提供稳定的游戏服务,处理玩家的并发请求。
  • 视频流媒体:通过分布式缓存技术,提供高质量的视频流媒体服务。

这些应用场景都利用了分布式集群的特性,实现了高效、高可用、可扩展的计算资源利用。

分布式集群的优势

分布式集群的优势主要体现在以下几个方面:

  1. 可扩展性:通过添加更多的计算节点,可以提升系统的处理能力和存储容量。
  2. 高可用性:分布式集群在某个节点出现故障时,其他节点可以继续提供服务,从而保证系统的连续运行。
  3. 负载均衡:合理地分配任务到各个节点,可以避免某些节点过载,提高系统整体的处理能力。
  4. 容错性:通过冗余备份和故障切换机制,能够保证数据的安全性。
  5. 高并发处理:可以同时处理大量的并发请求,提高系统响应速度。
  6. 资源利用率:通过分布式计算资源的高效调度,可以充分利用计算资源。

分布式集群的这些优势使其成为当今许多大型企业和项目的基础架构,能够更好地应对复杂的业务需求和大规模的数据处理任务。

示例代码:分布式任务分配

下面是一个简单的Python示例,展示了如何将任务分发到多个节点上进行处理:

import random
import time

class TaskDistributor:
    def __init__(self, nodes):
        self.nodes = nodes

    def distribute_task(self, task):
        node = random.choice(self.nodes)
        node.process(task)

class Node:
    def process(self, task):
        print(f"Processing task {task} on node {id(self)}")
        time.sleep(random.randint(1, 3))

nodes = [Node(), Node(), Node()]
distributor = TaskDistributor(nodes)

tasks = [1, 2, 3, 4, 5, 6]
for task in tasks:
    distributor.distribute_task(task)
分布式集群的组成部分

分布式集群的设计需要考虑多个关键组成部分,这些组成部分包括节点、网络通信和存储系统。本节将逐一介绍这些组成部分及其在分布式集群中的作用。

节点

节点是分布式集群的最小单位,每个节点都是一个独立的计算资源。节点可以是一台物理服务器、虚拟机或者容器。为了确保分布式集群的高效运行,节点应具备以下特点:

  • 独立性:每个节点拥有独立的计算资源(如CPU、内存)和操作系统。
  • 可访问性:节点之间可以通过网络相互访问,进行数据交换和任务调度。
  • 可扩展性:节点可以动态地添加或移除,以适应不同的负载需求。
  • 容错性:节点能够处理各种故障情况,确保整个集群的高可用性。

节点在分布式集群中的主要功能包括:

  • 计算任务执行:处理由任务调度器分发给它的计算任务。
  • 数据存储:存储分配给该节点的数据。
  • 通信:与其他节点通信,共享数据和状态信息。

示例代码:创建节点

下面是一个简单的Python示例,展示了如何定义一个节点类,并模拟节点之间的通信:

import random

class Node:
    def __init__(self, node_id):
        self.node_id = node_id
        self.tasks = []

    def receive_task(self, task):
        self.tasks.append(task)

    def process_task(self):
        if self.tasks:
            task = self.tasks.pop(0)
            print(f"Node {self.node_id} processing task {task}")
        else:
            print(f"Node {self.node_id} has no tasks")

nodes = [Node(1), Node(2), Node(3)]
tasks = [1, 2, 3, 4, 5]

for task in tasks:
    node = random.choice(nodes)
    node.receive_task(task)

for node in nodes:
    node.process_task()
网络通信

网络通信是分布式集群中最重要的组成部分之一,它负责节点之间的数据交换和任务调度。网络通信通常包括以下几个方面:

  • 通信协议:定义节点之间如何交换信息,常见的协议有HTTP、TCP/IP、RPC(远程过程调用)等。
  • 数据传输:节点之间传输的数据可以是任务请求、计算结果、状态更新等。
  • 负载均衡:合理地分配任务到不同的节点,确保每个节点的负载均衡。
  • 故障恢复:当某个节点发生故障时,其他节点能够接管其任务,确保系统的高可用性。

网络通信在分布式集群中的作用包括:

  • 任务调度:将任务分配到合适的节点上执行。
  • 数据同步:保持节点之间数据的一致性。
  • 状态维护:更新节点的状态信息,以便其他节点能够了解集群的最新状态。

示例代码:模拟网络通信

下面是一个简单的Python示例,展示了如何使用Socket进行节点之间的通信:

import socket
import threading

class Node:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def start(self):
        self.socket.bind((self.ip, self.port))
        self.socket.listen(5)
        print(f"Node listening on {self.ip}:{self.port}")
        threading.Thread(target=self.accept_connections).start()

    def accept_connections(self):
        while True:
            conn, addr = self.socket.accept()
            threading.Thread(target=self.handle_connection, args=(conn,)).start()

    def handle_connection(self, conn):
        while True:
            data = conn.recv(1024).decode('utf-8')
            if not data:
                break
            print(f"Received data: {data}")
            conn.sendall(f"Echo: {data}".encode('utf-8'))
        conn.close()

class Client:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    def connect(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((self.ip, self.port))
        sock.sendall("Hello, node!".encode('utf-8'))
        response = sock.recv(1024).decode('utf-8')
        print(f"Received response: {response}")
        sock.close()

node = Node('127.0.0.1', 12345)
node.start()

client = Client('127.0.0.1', 12345)
client.connect()
存储系统

分布式存储系统是分布式集群的一个重要组成部分,它负责数据的存储、备份和管理。存储系统的主要功能包括:

  • 数据存储:将数据分散存储在多个节点上,以提高存储空间的利用率。
  • 数据冗余:通过复制数据副本,提高数据的可靠性和容错性。
  • 数据访问:提供高效的数据访问机制,支持读写操作。
  • 数据一致性:确保分布式系统中的数据一致性,防止数据的不一致更新。

常见的分布式存储系统有:

  • Hadoop Distributed File System (HDFS):Hadoop生态系统中的分布式文件系统。
  • Google File System (GFS):Google公司内部使用的分布式文件系统。
  • Ceph:一个开源的分布式存储系统,支持对象存储、块存储和文件系统。

示例代码:使用Ceph存储系统

下面是一个简单的Python示例,展示了如何使用Ceph存储系统进行数据读写操作:

import rados
import rbd

cluster = rados.Rados(conffile='/etc/ceph/ceph.conf')
cluster.connect()

ioctx = cluster.open_ioctx('my_pool')
image = rbd.Image(ioctx, 'my_image', read_only=False)

data = image.read(0, 1024)  # 读取数据
print(f"Read data: {data}")

image.write(b'Hello, Ceph!', 0, 1024)  # 写入数据
image.flush()

ioctx.close()
cluster.shutdown()
分布式集群的常见类型

分布式集群根据其内部结构和工作模式,可以分为多种类型。这些类型包括对等式集群、主从式集群、环状集群等。每种类型都有其特点和适用场景。

对等式集群

在对等式集群中,所有节点的地位平等,没有主节点和从节点之分。每个节点都可以接受任务,执行任务,并将结果返回给其他节点。这种结构的优点在于所有节点都是独立的,没有单点故障,提高了系统的容错性和可用性。然而,由于没有中心节点,任务调度和一致性维护较为复杂。

示例代码:对等式集群

下面是一个简单的Python示例,展示了如何实现一个对等式集群,其中每个节点既可以作为任务发起者也可以作为任务执行者:

import random
import time
import threading

class PeerNode:
    def __init__(self, node_id, peers):
        self.node_id = node_id
        self.peers = peers
        self.tasks = []
        self.results = {}

    def send_task(self, task):
        target_node = random.choice(self.peers)
        target_node.receive_task(task)

    def receive_task(self, task):
        self.tasks.append(task)
        threading.Thread(target=self.process_task).start()

    def process_task(self):
        task = self.tasks.pop(0)
        time.sleep(random.randint(1, 3))
        result = f"Task {task} processed by Node {self.node_id}"
        print(result)
        self.results[task] = result

    def get_results(self):
        return self.results

nodes = [PeerNode(1, [2, 3]), PeerNode(2, [1, 3]), PeerNode(3, [1, 2])]
tasks = [1, 2, 3, 4, 5]

for node in nodes:
    for task in tasks:
        node.send_task(task)

time.sleep(5)

for node in nodes:
    print(f"Node {node.node_id} results: {node.get_results()}")
主从式集群

主从式集群中有一个主节点(Master)和多个从节点(Slave)。主节点负责任务调度和状态管理,而从节点执行具体的任务。主节点可以通过分发任务给从节点来实现负载均衡。当从节点发生故障时,主节点可以接管其任务,确保系统的高可用性。

示例代码:主从式集群

下面是一个简单的Python示例,展示了如何实现一个主从式集群,其中主节点负责任务调度,从节点执行任务:

import random
import time
import threading

class MasterNode:
    def __init__(self, slaves):
        self.slaves = slaves
        self.tasks = []
        self.results = {}

    def distribute_task(self, task):
        slave = random.choice(self.slaves)
        slave.receive_task(task)

    def receive_result(self, task, result):
        self.results[task] = result

    def get_results(self):
        return self.results

class SlaveNode:
    def __init__(self):
        self.tasks = []
        self.results = {}

    def receive_task(self, task):
        self.tasks.append(task)
        threading.Thread(target=self.process_task).start()

    def process_task(self):
        task = self.tasks.pop(0)
        time.sleep(random.randint(1, 3))
        result = f"Task {task} processed by Slave"
        print(result)
        self.results[task] = result

master = MasterNode([SlaveNode(), SlaveNode(), SlaveNode()])
tasks = [1, 2, 3, 4, 5]

for task in tasks:
    master.distribute_task(task)

time.sleep(5)

print(f"Master results: {master.get_results()}")
环状集群

环状集群是一种特殊的主从式集群,其中节点形成一个环形结构,每个节点既是前一个节点的从节点,又是后一个节点的主节点。这种结构的优点是提高了数据的一致性和可用性,因为每个节点都有前后两个节点作为备份。环状集群常用于实现分布式数据库和分布式存储系统。

示例代码:环状集群

下面是一个简单的Python示例,展示了如何实现一个环状集群,其中每个节点既是前一个节点的从节点也是后一个节点的主节点:

import random
import time
import threading

class RingNode:
    def __init__(self, node_id, predecessor, successor):
        self.node_id = node_id
        self.predecessor = predecessor
        self.successor = successor
        self.tasks = []
        self.results = {}

    def receive_task(self, task):
        self.tasks.append(task)
        threading.Thread(target=self.process_task).start()

    def process_task(self):
        task = self.tasks.pop(0)
        time.sleep(random.randint(1, 3))
        result = f"Task {task} processed by Node {self.node_id}"
        print(result)
        self.results[task] = result

    def send_result(self, task, result):
        self.successor.receive_result(task, result)

class Ring:
    def __init__(self, nodes):
        self.nodes = nodes
        for i in range(len(nodes)):
            nodes[i].predecessor = nodes[(i - 1) % len(nodes)]
            nodes[i].successor = nodes[(i + 1) % len(nodes)]

    def distribute_task(self, task):
        node = random.choice(self.nodes)
        node.receive_task(task)

    def get_results(self):
        results = {}
        for node in self.nodes:
            results.update(node.results)
        return results

nodes = [RingNode(1, None, None), RingNode(2, None, None), RingNode(3, None, None)]
ring = Ring(nodes)
ring.distribute_task(1)

time.sleep(5)

print(f"Ring results: {ring.get_results()}")
分布式集群的搭建步骤

搭建分布式集群需要经过一系列的步骤,包括环境准备、安装配置和测试运行。每个步骤都需要仔细规划和执行,以确保集群能够稳定运行。

环境准备

在搭建分布式集群之前,需要准备必要的硬件和软件环境。

  • 硬件:选择合适的服务器或云实例,确保有足够的计算资源(如CPU、内存等)。节点之间需要通过网络连接,确保网络带宽足够。
  • 操作系统:选择适合的服务器操作系统,如Linux(Ubuntu、CentOS等)。
  • 网络配置:确保所有节点之间可以互相访问,并且网络延迟低。
  • 存储资源:按需配置分布式存储系统,如HDFS、Ceph等。

示例代码:基本网络配置

下面是一个简单的网络配置脚本示例,用于设置防火墙规则,确保节点之间可以互相访问:

# 设置防火墙规则,允许TCP和UDP端口通信
sudo ufw allow 10000:20000/tcp
sudo ufw allow 10000:20000/udp

# 开启防火墙
sudo ufw enable
安装配置

安装配置是搭建分布式集群的核心步骤,包括安装必要的软件、配置集群环境等。

  • 安装软件:根据集群类型选择合适的软件,如Hadoop、Spark、Kubernetes等,并安装到各个节点上。
  • 配置集群:修改配置文件,设置节点之间的网络地址、端口等信息。
  • 初始化集群:运行初始化脚本或命令,启动集群的各个组件。
  • 测试连接:测试节点之间的网络连接是否正常,确保通信无误。

示例代码:安装Hadoop集群

下面是一个简单的Hadoop安装配置示例:

# 安装Hadoop
wget http://mirror.bit.edu.cn/apache/hadoop/common/hadoop-3.3.1/hadoop-3.3.1.tar.gz
tar -xzvf hadoop-3.3.1.tar.gz
cd hadoop-3.3.1
cp -r ./etc/hadoop /etc/hadoop

# 配置环境变量
echo 'export HADOOP_HOME=/path/to/hadoop' >> ~/.bashrc
echo 'export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin' >> ~/.bashrc
source ~/.bashrc

# 配置hadoop-site.xml
cat <<EOF > /etc/hadoop/hadoop-env.sh
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export HADOOP_HOME=/path/to/hadoop
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
EOF

cat <<EOF > /etc/hadoop/core-site.xml
<configuration>
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://localhost:9000</value>
    </property>
</configuration>
EOF

cat <<EOF > /etc/hadoop/hdfs-site.xml
<configuration>
    <property>
        <name>dfs.replication</name>
        <value>1</value>
    </property>
</configuration>
EOF

# 格式化HDFS
hdfs namenode -format

# 启动Hadoop集群
sbin/start-dfs.sh
sbin/start-yarn.sh
测试运行

测试运行是搭建分布式集群的最后一步,通过实际运行任务来验证集群的稳定性和性能。

  • 启动集群:启动所有的节点服务,确保所有节点都能正常运行。
  • 运行任务:运行一些典型的任务,测试集群的性能和稳定性。
  • 结果验证:检查任务结果,确保任务执行正确。
  • 性能优化:根据测试结果进行性能优化,提高集群的运行效率。

示例代码:运行Hadoop任务

下面是一个简单的Hadoop任务运行示例,读取数据文件并进行WordCount操作:

# 创建输入数据文件
echo "hello hadoop world" > input.txt

# 将输入文件上传到HDFS
hdfs dfs -put input.txt /user/hadoop/input

# 提交WordCount任务
hadoop jar /path/to/hadoop-mapreduce-examples-3.3.1.jar wordcount /user/hadoop/input /user/hadoop/output

# 读取输出结果
hdfs dfs -cat /user/hadoop/output/*
分布式集群的常见问题及解决方法

在搭建和运行分布式集群时,可能会遇到各种问题,包括通信故障、节点故障和数据一致性问题。本节将介绍这些常见问题及其解决方法。

通信故障

通信故障是指节点之间无法正常通信,导致任务调度和数据交换失败。常见的原因包括网络延迟高、防火墙规则错误、端口冲突等。

解决方法

  • 检查网络配置:确保所有节点之间可以互相访问,网络延迟低。
  • 检查防火墙规则:确保没有阻止节点之间的通信。
  • 检查端口配置:确保节点之间的通信端口没有冲突。
  • 使用监控工具:实时监控节点之间的通信状态,及时发现并解决问题。

示例代码:网络监控脚本

下面是一个简单的网络监控脚本示例,用于检查节点之间的网络连接状态:

#!/bin/bash

# 检查网络连接状态
ping -c 4 192.168.1.100 > /dev/null 2>&1
if [ $? -eq 0 ]; then
    echo "Node 192.168.1.100 is reachable"
else
    echo "Node 192.168.1.100 is unreachable"
fi
节点故障

节点故障是指节点出现硬件或软件故障,导致任务执行失败。常见的原因包括硬件故障、内存泄漏、程序崩溃等。

解决方法

  • 增加冗余节点:通过增加更多的节点,提高系统的容错性。
  • 使用容器化技术:通过使用Docker等容器化技术,提高节点的隔离性和稳定性。
  • 定期维护:定期检查和维护节点,确保其正常运行。
  • 监控和报警:实时监控节点的状态,及时发现并处理故障。

示例代码:故障切换脚本

下面是一个简单的故障切换脚本示例,当主节点故障时,切换到备用节点:

#!/bin/bash

# 主节点
MASTER_NODE=192.168.1.100
# 备用节点
BACKUP_NODE=192.168.1.101

# 检查主节点是否可达
ping -c 4 $MASTER_NODE > /dev/null 2>&1
if [ $? -eq 0 ]; then
    echo "Master node is reachable"
else
    echo "Master node is unreachable, switching to backup node"
    # 执行切换操作
    ssh $BACKUP_NODE "sudo systemctl start hadoop"
fi
数据一致性问题

数据一致性问题是指在分布式集群中,由于节点之间的时间不同步或网络延迟等原因,导致数据的不一致更新。

解决方法

  • 使用分布式事务:通过分布式事务,确保数据的一致性更新。
  • 使用分布式锁:通过分布式锁,确保同一时间只有一个节点能够修改数据。
  • 使用时间戳:通过时间戳,判断数据的新旧程度,确保最新的数据被更新。
  • 定期同步:定期同步节点之间的数据,确保数据的一致性。

示例代码:分布式锁实现

下面是一个简单的分布式锁实现示例,使用Redis实现:

import redis

class DistributedLock:
    def __init__(self, key):
        self.key = key
        self.client = redis.Redis(host='localhost', port=6379, db=0)

    def acquire(self):
        return self.client.setnx(self.key, 'locked')

    def release(self):
        self.client.delete(self.key)

lock = DistributedLock('my_lock')
if lock.acquire():
    print("Lock acquired")
    # 执行操作
    lock.release()
else:
    print("Lock already acquired")
分布式集群优化与维护

分布式集群在运行过程中需要不断优化和维护,以提高系统的性能和稳定性。本节将介绍优化和维护的几个关键方面,包括性能优化、安全维护和日常监控。

性能优化

性能优化是提高分布式集群运行效率的关键。可以通过以下几个方面进行优化:

  • 负载均衡:合理地分配任务到不同的节点,确保每个节点的负载均衡。
  • 缓存机制:通过缓存技术,减少数据的读取时间。
  • 数据压缩:通过压缩数据,减少数据传输的时间和存储空间。
  • 并行计算:利用多核处理器和多线程技术,提高计算效率。

示例代码:负载均衡实现

下面是一个简单的Python示例,展示了如何实现一个简单的负载均衡器,根据节点的负载情况分配任务:

import random
import time

class LoadBalancer:
    def __init__(self, nodes):
        self.nodes = nodes

    def distribute_task(self, task):
        node = self.select_node()
        node.receive_task(task)

    def select_node(self):
        node = random.choice(self.nodes)
        return node

class Node:
    def __init__(self, node_id):
        self.node_id = node_id
        self.tasks = []
        self.load = 0

    def receive_task(self, task):
        self.tasks.append(task)
        self.load += 1
        print(f"Node {self.node_id} received task {task}, current load: {self.load}")

nodes = [Node(1), Node(2), Node(3)]
load_balancer = LoadBalancer(nodes)
tasks = [1, 2, 3, 4, 5, 6]

for task in tasks:
    load_balancer.distribute_task(task)
安全维护

安全维护是确保分布式集群的安全性和稳定性的关键。可以通过以下几个方面进行维护:

  • 身份认证:通过身份认证机制,确保只有授权用户才能访问集群。
  • 数据加密:通过数据加密技术,保护数据的安全性。
  • 访问控制:通过访问控制机制,限制用户的访问权限。
  • 日志审计:通过日志审计,监控和追踪用户的操作记录。

示例代码:身份认证实现

下面是一个简单的Python示例,展示了如何实现一个简单的身份认证机制,通过用户名和密码进行身份验证:

import hashlib

class AuthService:
    def __init__(self):
        self.users = {
            'admin': '5e884898da2831344b22d76c5a338bb8576148c8c9e63b7e6c5b91b180b010c9'
        }
        # Hash of 'admin' password using SHA-1

    def authenticate(self, username, password):
        if username in self.users and self.hash_password(password) == self.users[username]:
            return True
        return False

    def hash_password(self, password):
        return hashlib.sha1(password.encode('utf-8')).hexdigest()

username = 'admin'
password = 'password'

auth_service = AuthService()
if auth_service.authenticate(username, password):
    print(f"User {username} authenticated successfully")
else:
    print("Authentication failed")
日常监控

日常监控是确保分布式集群正常运行的重要手段。可以通过以下几个方面进行监控:

  • 性能监控:监控集群的性能指标,如CPU使用率、内存使用率等。
  • 日志分析:分析日志文件,发现潜在的问题。
  • 异常检测:通过异常检测技术,发现集群中的异常行为。
  • 报警通知:设置报警规则,及时通知管理员。

示例代码:性能监控实现

下面是一个简单的Python示例,展示了如何实现一个简单的性能监控器,监控节点的CPU使用率:

import psutil
import time

class PerformanceMonitor:
    def __init__(self):
        self.cpu_usage = 0

    def monitor_cpu(self):
        self.cpu_usage = psutil.cpu_percent(interval=1)
        print(f"Current CPU usage: {self.cpu_usage}%")

    def alert(self, threshold):
        if self.cpu_usage > threshold:
            print(f"CPU usage exceeds threshold {threshold}%")
            # 发送报警通知

monitor = PerformanceMonitor()
while True:
    monitor.monitor_cpu()
    monitor.alert(80)
    time.sleep(5)
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消