uuid.js实战应用:多场景UUID生成最佳实践

uuid.js实战应用:多场景UUID生成最佳实践

【免费下载链接】uuid Generate RFC-compliant UUIDs in JavaScript 【免费下载链接】uuid 项目地址: https://gitcode.com/gh_mirrors/uu/uuid

本文深入探讨了uuid.js库在现代应用开发中的多场景实践应用,涵盖了数据库主键生成、分布式系统ID生成策略、不同UUID版本(v1/v3/v4/v5/v6/v7)的性能比较与选择指南,以及浏览器环境和React Native中的集成方案。文章通过详细的代码示例、性能数据对比和架构图,为开发者提供了全面的UUID生成最佳实践。

数据库主键与分布式系统ID生成

在现代分布式系统架构中,唯一标识符的生成策略对系统性能和可扩展性至关重要。UUID.js库提供了多种RFC兼容的UUID版本,为数据库主键和分布式ID生成提供了专业解决方案。

UUID版本选择策略

不同版本的UUID适用于不同的应用场景,选择合适的版本对系统性能有显著影响:

UUID版本生成方式排序性冲突概率适用场景
v1时间戳+MAC地址时间有序极低传统时间序列数据
v4完全随机无序极低通用随机标识符
v6时间戳重排序时间有序极低现代时间序列数据
v7Unix时间戳时间有序极低分布式系统时间序列

数据库主键最佳实践

在关系型数据库中,使用UUID作为主键需要特别注意索引性能和存储效率:

import { v4, v7 } from 'uuid';

// 随机主键 - 适用于写入密集型场景
const randomPrimaryKey = v4();

// 时间有序主键 - 适用于查询密集型场景
const timeOrderedPrimaryKey = v7();

// 批量插入时的性能优化
const batchIds = Array.from({ length: 1000 }, () => v7());

mermaid

分布式系统ID生成架构

在微服务架构中,分布式ID生成需要保证全局唯一性和高性能:

// 分布式ID生成服务
class DistributedIdGenerator {
    constructor() {
        this.lastTimestamp = 0;
        this.sequence = 0;
    }

    generateId() {
        const now = Date.now();
        
        if (now === this.lastTimestamp) {
            this.sequence = (this.sequence + 1) & 0xffff;
            if (this.sequence === 0) {
                // 序列号溢出,等待下一毫秒
                while (Date.now() <= now) {}
            }
        } else {
            this.sequence = 0;
        }
        
        this.lastTimestamp = now;
        return v7({ msecs: now, seq: this.sequence });
    }
}

// 使用示例
const idGenerator = new DistributedIdGenerator();
const distributedId = idGenerator.generateId();

分片数据库中的UUID策略

在分片数据库环境中,UUID的选择直接影响数据分布和查询性能:

// 基于UUID的分片策略
function getShardIndex(uuid, totalShards) {
    const bytes = parse(uuid);
    // 使用UUID的前几个字节计算分片索引
    const hash = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
    return hash % totalShards;
}

// 时间有序UUID确保数据在分片间均匀分布
const shardCount = 8;
const userId = v7();
const targetShard = getShardIndex(userId, shardCount);

性能优化技巧

  1. 二进制存储优化
// 使用二进制格式存储,减少存储空间
const binaryUuid = v4(null, new Uint8Array(16));
// 存储到数据库
db.insert({ id: binaryUuid, data: '...' });

// 查询时转换回字符串
const result = db.query('SELECT * FROM table WHERE id = ?', [stringify(binaryUuid)]);
  1. 批量生成优化
// 批量生成UUID减少函数调用开销
function generateBatch(size, version = 'v7') {
    const generator = {
        v1: () => v1(),
        v4: () => v4(),
        v7: () => v7()
    }[version];
    
    return Array.from({ length: size }, generator);
}

const batchIds = generateBatch(1000, 'v7');

监控和诊断

建立完善的UUID生成监控体系:

// UUID生成性能监控
class UuidMonitor {
    constructor() {
        this.stats = {
            v1: { count: 0, totalTime: 0 },
            v4: { count: 0, totalTime: 0 },
            v7: { count: 0, totalTime: 0 }
        };
    }

    trackGeneration(version, startTime) {
        const duration = Date.now() - startTime;
        this.stats[version].count++;
        this.stats[version].totalTime += duration;
    }

    getStats() {
        return Object.entries(this.stats).map(([version, data]) => ({
            version,
            count: data.count,
            avgTime: data.count > 0 ? data.totalTime / data.count : 0
        }));
    }
}

// 使用监控
const monitor = new UuidMonitor();
const start = Date.now();
const id = v7();
monitor.trackGeneration('v7', start);

通过合理的UUID版本选择和优化策略,可以在分布式系统中实现高效、可靠的唯一标识符生成,为数据库设计和系统架构提供坚实基础。

命名空间UUID(v3/v5)的实际应用

在现代分布式系统中,UUID(通用唯一标识符)的应用场景日益广泛。其中,基于命名空间的UUID(v3和v5版本)因其确定性生成特性,在特定业务场景中展现出独特的价值。本文将深入探讨命名空间UUID的实际应用场景、技术实现细节以及最佳实践。

命名空间UUID的核心概念

命名空间UUID基于RFC 9562标准,通过将名称(name)与命名空间(namespace)结合,使用哈希算法生成确定性UUID。v3版本使用MD5哈希算法,而v5版本使用更安全的SHA-1算法。

mermaid

预定义命名空间的使用

uuid.js库提供了两个RFC标准预定义命名空间:

命名空间类型UUID值描述
DNS6ba7b810-9dad-11d1-80b4-00c04fd430c8用于DNS域名相关的UUID生成
URL6ba7b811-9dad-11d1-80b4-00c04fd430c8用于URL相关的UUID生成
import { v3, v5 } from 'uuid';

// 使用预定义DNS命名空间生成UUID
const dnsUUIDv3 = v3('example.com', v3.DNS);
const dnsUUIDv5 = v5('example.com', v5.DNS);

// 使用预定义URL命名空间生成UUID  
const urlUUIDv3 = v3('https://example.com/path', v3.URL);
const urlUUIDv5 = v5('https://example.com/path', v5.URL);

自定义命名空间的创建与应用

除了预定义命名空间,开发者可以创建自定义命名空间来满足特定业务需求:

// 创建自定义命名空间(使用UUID生成器生成)
const MY_APP_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';

// 为用户数据生成确定性UUID
function generateUserUUID(userId, userEmail) {
    // 组合用户标识信息
    const userIdentifier = `${userId}:${userEmail}`;
    
    // 使用v5版本(SHA-1更安全)
    return v5(userIdentifier, MY_APP_NAMESPACE);
}

// 为产品数据生成确定性UUID
function generateProductUUID(productId, category) {
    const productIdentifier = `product:${category}:${productId}`;
    return v5(productIdentifier, MY_APP_NAMESPACE);
}

实际应用场景分析

1. 数据关联与一致性保证

在分布式系统中,命名空间UUID可以确保相同输入始终生成相同输出,这对于数据关联和一致性验证至关重要:

// 跨服务数据关联示例
class DataConsistencyService {
    constructor() {
        this.USER_NAMESPACE = 'c0d3d3a7-5a1b-4c3d-8e2f-9a1b2c3d4e5f';
    }
    
    // 生成用户相关数据的确定性UUID
    generateUserDataUUID(userId, dataType, dataKey) {
        const compositeKey = `${userId}:${dataType}:${dataKey}`;
        return v5(compositeKey, this.USER_NAMESPACE);
    }
    
    // 验证数据一致性
    verifyDataConsistency(userId, dataType, dataKey, expectedUUID) {
        const generatedUUID = this.generateUserDataUUID(userId, dataType, dataKey);
        return generatedUUID === expectedUUID;
    }
}
2. 缓存键生成与版本管理

命名空间UUID非常适合用于生成缓存键,确保相同查询参数总是生成相同的缓存键:

class CacheManager {
    constructor() {
        this.CACHE_NAMESPACE = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';
    }
    
    generateCacheKey(apiEndpoint, params) {
        // 将参数排序后序列化,确保参数顺序不影响结果
        const sortedParams = Object.keys(params)
            .sort()
            .map(key => `${key}=${params[key]}`)
            .join('&');
        
        const cacheIdentifier = `${apiEndpoint}?${sortedParams}`;
        return v5(cacheIdentifier, this.CACHE_NAMESPACE);
    }
    
    async getCachedData(apiEndpoint, params) {
        const cacheKey = this.generateCacheKey(apiEndpoint, params);
        // 使用生成的UUID作为缓存键
        return await cache.get(cacheKey);
    }
}
3. 文件存储与内容寻址

在文件存储系统中,命名空间UUID可以用于内容寻址,确保相同内容具有相同标识符:

const FILE_NAMESPACE = 'd4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90';

function generateContentAddressableUUID(content, metadata = {}) {
    // 计算内容哈希
    const contentHash = crypto.createHash('sha256').update(content).digest('hex');
    
    // 组合元数据
    const metaString = JSON.stringify(metadata, Object.keys(metadata).sort());
    
    // 生成确定性UUID
    const identifier = `${contentHash}:${metaString}`;
    return v5(identifier, FILE_NAMESPACE);
}

// 示例:相同内容生成相同UUID
const content1 = 'Hello, World!';
const content2 = 'Hello, World!';
const uuid1 = generateContentAddressableUUID(content1);
const uuid2 = generateContentAddressableUUID(content2);
// uuid1 === uuid2 为 true

性能优化与最佳实践

字节数组操作优化

对于高性能场景,可以直接操作字节数组来避免字符串转换开销:

function generateOptimizedUUID(name, namespaceUUID) {
    // 直接使用字节数组操作
    const nameBytes = new TextEncoder().encode(name);
    const namespaceBytes = parse(namespaceUUID);
    
    // 使用v5生成UUID(返回字节数组)
    return v5(nameBytes, namespaceBytes, new Uint8Array(16));
}
批量生成优化

当需要批量生成大量UUID时,可以复用缓冲区来提高性能:

class BatchUUIDGenerator {
    constructor(namespace) {
        this.namespace = namespace;
        this.buffer = new Uint8Array(16);
    }
    
    generate(name) {
        // 复用缓冲区,避免重复分配内存
        return v5(name, this.namespace, this.buffer);
    }
    
    generateBatch(names) {
        return names.map(name => this.generate(name));
    }
}

安全考虑与版本选择

在选择v3还是v5时,需要考虑安全性和兼容性因素:

特性v3 (MD5)v5 (SHA-1)
安全性较低,存在碰撞风险较高,相对更安全
性能较快稍慢
RFC推荐不推荐用于新项目推荐使用
适用场景兼容旧系统新项目开发

mermaid

错误处理与验证

在实际应用中,需要妥善处理可能的错误情况:

class SafeUUIDGenerator {
    static generatev5(name, namespace) {
        try {
            // 验证命名空间格式
            if (typeof namespace === 'string' && !validate(namespace)) {
                throw new Error('Invalid namespace UUID format');
            }
            
            // 验证名称类型
            if (typeof name !== 'string' && !(name instanceof Uint8Array)) {
                throw new Error('Name must be string or Uint8Array');
            }
            
            return v5(name, namespace);
        } catch (error) {
            console.error('UUID generation failed:', error.message);
            // 返回fallback UUID或抛出特定业务异常
            return null;
        }
    }
}

测试策略与验证

为确保命名空间UUID的正确性,需要建立完善的测试套件:

// 测试相同输入生成相同输出
assert.strictEqual(
    v5('test', v5.DNS),
    v5('test', v5.DNS)
);

// 测试不同输入生成不同输出
assert.notStrictEqual(
    v5('test1', v5.DNS),
    v5('test2', v5.DNS)
);

// 测试命名空间影响
assert.notStrictEqual(
    v5('test', v5.DNS),
    v5('test', v5.URL)
);

通过以上实际应用场景的分析和技术实现细节的探讨,我们可以看到命名空间UUID在确保数据一致性、缓存管理、内容寻址等场景中具有重要价值。正确选择版本(v3或v5)、合理设计命名空间策略、优化性能处理,将使命名空间UUID成为分布式系统开发中的强大工具。

时间戳UUID(v1/v6/v7)的性能考量

在现代应用开发中,UUID生成性能往往成为系统瓶颈的关键因素。时间戳UUID(v1、v6、v7)因其包含时间信息而备受青睐,但不同版本在性能表现上存在显著差异。深入理解这些差异对于构建高性能系统至关重要。

时间戳UUID的性能架构分析

时间戳UUID的核心性能差异源于其内部实现机制和RFC规范要求。让我们通过架构图来理解各版本的处理流程:

mermaid

各版本性能特征对比

版本时间精度随机性要求状态管理性能特点适用场景
v1100ns中等复杂状态中等性能传统系统兼容
v6100ns中等复杂状态略低于v1时间排序优化
v71ms简单状态高性能现代高并发系统

v1版本的性能瓶颈

v1 UUID的实现复杂度最高,主要性能开销体现在:

时间戳处理开销

// v1时间戳处理的核心代码
msecs += 12219292800000; // Gregorian epoch偏移
const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;

这种时间转换涉及大数运算和位操作,在JavaScript中会产生显著的性能开销。特别是在高频率生成时,时间精度维护成为主要瓶颈。

状态管理复杂度 v1需要维护全局状态来确保时钟序列和节点ID的一致性:

const _state: V1State = {
  node?: Uint8Array;      // 节点ID (47位随机)
  clockseq?: number;      // 序列号 (14位)
  msecs?: number;         // 时间戳 (毫秒)
  nsecs?: number;         // 纳秒偏移
};

这种状态管理在并发环境下需要额外的同步机制,进一步影响性能。

v6版本的性能优化与代价

v6作为v1的改进版本,主要优化了字段布局以提高数据库索引效率,但性能特征与v1相似:

// v6通过v1生成后重排序字段
let bytes = v1({ ...options, _v6: true }, new Uint8Array(16));
bytes = v1ToV6(bytes); // 字段重排序操作

这种实现方式带来了额外的内存分配和拷贝开销,但在排序性能上有所提升。

v7版本的性能突破

v7代表了时间戳UUID的性能飞跃,其设计针对现代硬件和高并发场景进行了优化:

简化的时间处理

// v7使用Unix时间戳,避免复杂的时间转换
buf[offset++] = (msecs / 0x10000000000) & 0xff;
buf[offset++] = (msecs / 0x100000000) & 0xff;
// ... 简单的位操作

高效的状态管理 v7的状态管理更加轻量:

type V7State = {
  msecs?: number; // 时间,毫秒
  seq?: number;   // 序列号 (32位)
};

优化的序列号生成

// 32位序列号,支持更高的生成频率
state.seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9];

性能基准测试数据

根据实际基准测试,各版本在Node.js环境下的性能表现如下(操作/秒):

mermaid

从测试数据可以看出,v7版本的性能几乎是v1/v6版本的两倍以上,这主要得益于其简化的时间处理和状态管理机制。

内存使用效率分析

不同版本在内存使用方面也存在差异:

版本内存分配次数内存占用GC压力缓存友好性
v13-4次较高中等一般
v64-5次较高中等较好
v72-3次较低优秀

v7通过减少中间状态和优化内存布局,显著降低了垃圾回收压力。

并发环境下的性能考量

在高并发场景中,时间戳UUID的性能表现尤为重要:

v1/v6的并发限制 由于需要维护全局状态,v1和v6在并发环境下可能遇到状态同步问题。RFC规范明确限制了单个节点每秒最多生成1000万个v1 UUID,这在现代硬件上可能成为瓶颈。

v7的并发优势 v7的设计更适合高并发环境:

  • 无全局状态竞争
  • 更高的生成频率上限
  • 更好的水平扩展性

实际应用中的性能调优建议

  1. 批量生成优化 对于需要大量UUID的场景,建议使用预分配缓冲区:
// 高性能UUID生成示例
const buffer = new Uint8Array(16 * 1000); // 预分配16KB缓冲区

function generateUUIDs(count) {
  const uuids = [];
  for (let i = 0; i < count; i++) {
    uuid.v7(null, buffer, i * 16); // 重用缓冲区
    uuids.push(uuid.stringify(buffer.subarray(i * 16, (i + 1) * 16)));
  }
  return uuids;
}
  1. 时间源优化 对于时间敏感的应用程序,考虑使用高性能时间源:
// 使用performance.now()获取更高精度时间
const highResTime = () => {
  if (typeof performance !== 'undefined') {
    return performance.now();
  }
  return Date.now();
};
  1. 缓存策略 对于不要求严格唯一性的场景,可以考虑时间戳缓存:
let lastUUID = null;
let lastTime = 0;

function getCachedUUID() {
  const now = Date.now();
  if (now === lastTime && lastUUID) {
    return lastUUID; // 相同毫秒内返回缓存值
  }
  lastTime = now;
  lastUUID = uuid.v7();
  return lastUUID;
}

时间戳UUID的性能选择应该基于具体的应用需求。v7版本在大多数现代应用场景中提供了最佳的性能表现,而v1和v6则更适合需要与传统系统兼容的场景。通过理解各版本的性能特征和优化策略,开发者可以做出更加明智的技术选择。

浏览器环境与React Native集成

在现代Web开发和移动应用开发中,UUID的生成需求无处不在。uuid.js库为浏览器环境和React Native提供了出色的支持,通过现代化的API设计和跨平台兼容性,确保开发者能够在不同环境中获得一致且可靠的UUID生成体验。

浏览器环境集成

在浏览器环境中,uuid.js充分利用了现代浏览器的Crypto API来生成高质量的随机数,这是生成安全UUID的基础。库会自动检测并优先使用原生crypto.getRandomValues()方法,确保生成的UUID具有足够的随机性和安全性。

基础使用示例
// ES6模块导入方式
import { v4 as uuidv4, v7 as uuidv7, validate } from 'uuid';

// 生成版本4 UUID(随机)
const randomUUID = uuidv4();
console.log('Random UUID:', randomUUID); // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'

// 生成版本7 UUID(时间戳)
const timeBasedUUID = uuidv7();
console.log('Time-based UUID:', timeBasedUUID);

// 验证UUID有效性
const isValid = validate('invalid-uuid');
console.log('Is valid UUID:', isValid); // ⇨ false
命名空间UUID生成
import { v5, DNS, URL } from 'uuid';

// 使用预定义DNS命名空间
const dnsUUID = v5('example.com', DNS);
console.log('DNS namespace UUID:', dnsUUID);

// 使用预定义URL命名空间  
const urlUUID = v5('https://example.com/page', URL);
console.log('URL namespace UUID:', urlUUID);

// 自定义命名空间
const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
const customUUID = v5('custom-data', MY_NAMESPACE);
console.log('Custom namespace UUID:', customUUID);
构建配置示例

对于现代前端项目,通常使用Webpack或Vite等构建工具。以下是Webpack配置示例:

// webpack.config.js
module.exports = {
  // ...其他配置
  resolve: {
    alias: {
      uuid: 'uuid/dist-browser' // 使用浏览器专用构建
    }
  }
};

React Native集成

React Native环境需要特殊处理,因为其JavaScript运行时与标准浏览器环境有所不同。uuid.js通过react-native-get-random-values包来提供兼容性支持。

安装和配置

mermaid

首先安装必要的依赖:

npm install uuid react-native-get-random-values
# 或
yarn add uuid react-native-get-random-values
入口文件配置

在React Native项目的入口文件(通常是index.js)中,必须首先导入随机数polyfill:

// 必须在所有其他导入之前
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';

// 现在可以安全使用uuid
const deviceId = uuidv4();
console.log('Device ID:', deviceId);
React Native组件示例
import React, { useState, useEffect } from 'react';
import { View, Text } from 'react-native';
import { v4 as uuidv4 } from 'uuid';

const SessionManager = () => {
  const [sessionId, setSessionId] = useState('');

  useEffect(() => {
    // 生成会话ID
    const newSessionId = uuidv4();
    setSessionId(newSessionId);
    
    // 存储到AsyncStorage或其他持久化方案
    AsyncStorage.setItem('sessionId', newSessionId);
  }, []);

  return (
    <View>
      <Text>Session ID: {sessionId}</Text>
    </View>
  );
};

性能优化策略

在不同环境中,UUID生成的性能特征有所不同。以下是优化建议:

环境推荐版本性能特点使用场景
浏览器v4/v7利用Crypto API,性能优秀通用随机ID生成
React Nativev4通过polyfill支持,稳定可靠移动应用唯一标识
需要排序v6/v7时间戳有序,便于索引数据库主键、日志追踪
批量生成优化
// 批量生成UUID的性能优化示例
function generateBatchUUIDs(count, version = 'v4') {
  const uuids = [];
  const generator = {
    v4: () => uuidv4(),
    v7: () => uuidv7()
  }[version];

  for (let i = 0; i < count; i++) {
    uuids.push(generator());
  }
  
  return uuids;
}

// 生成1000个UUID
const batchUUIDs = generateBatchUUIDs(1000, 'v4');

错误处理和兼容性

浏览器兼容性检测
function checkUUIDSupport() {
  try {
    // 测试Crypto API可用性
    if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
      throw new Error('Crypto API not supported');
    }
    
    // 测试uuid库功能
    const testUUID = uuidv4();
    if (!validate(testUUID)) {
      throw new Error('UUID validation failed');
    }
    
    return {
      supported: true,
      message: 'UUID generation fully supported'
    };
  } catch (error) {
    return {
      supported: false,
      message: error.message,
      fallback: 'Consider using a UUID polyfill or alternative ID generation'
    };
  }
}
React Native异常处理
import { Platform } from 'react-native';

const UUIDUtils = {
  generateId: () => {
    try {
      if (Platform.OS === 'web') {
        return uuidv4();
      } else {
        // React Native环境
        return uuidv4();
      }
    } catch (error) {
      console.error('UUID generation failed:', error);
      // 降级方案:使用时间戳+随机数
      return `fallback-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
    }
  }
};

实际应用场景

浏览器本地存储标识
// 生成用户设备指纹
function generateDeviceFingerprint() {
  const { v5, URL } = require('uuid');
  
  const hardwareInfo = {
    userAgent: navigator.userAgent,
    language: navigator.language,
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
    // 更多硬件信息...
  };
  
  return v5(JSON.stringify(hardwareInfo), URL);
}

// 使用示例
const deviceId = generateDeviceFingerprint();
localStorage.setItem('deviceId', deviceId);
React Native混合开发
// 在React Native与WebView通信中使用UUID
import { WebView } from 'react-native-webview';
import { v4 as uuidv4 } from 'uuid';

const App = () => {
  const [webViewKey, setWebViewKey] = useState(uuidv4());

  const refreshWebView = () => {
    // 通过生成新的key来强制刷新WebView
    setWebViewKey(uuidv4());
  };

  return (
    <WebView
      key={webViewKey}
      source={{ uri: 'https://example.com' }}
      onError={refreshWebView}
    />
  );
};

通过上述实践,开发者可以确保在浏览器和React Native环境中都能获得稳定、可靠的UUID生成能力,为应用程序提供唯一的标识符解决方案。

总结

uuid.js库为现代应用开发提供了全面而强大的UUID生成解决方案。通过理解不同版本UUID的特性和适用场景,开发者可以在数据库设计、分布式系统架构、浏览器应用和React Native移动开发中做出明智的技术选择。从时间戳UUID的性能优化到命名空间UUID的确定性生成,从浏览器环境的Crypto API利用到的React Native的polyfill集成,本文涵盖了uuid.js在实际项目中的关键应用场景和最佳实践,为构建高性能、可扩展的应用程序提供了坚实基础。

【免费下载链接】uuid Generate RFC-compliant UUIDs in JavaScript 【免费下载链接】uuid 项目地址: https://gitcode.com/gh_mirrors/uu/uuid

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

抵扣说明:

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

余额充值