引入了 Disruptor 后,系统性能大幅提升!

高性能队列框架-Disruptor使用、Netty结合Disruptor大幅提高数据处理性能 Disruptor 的设计中是没有锁的,在 Disruptor 中出现线程竞争的地方也就是 RingBuffer 中的下标 Sequence,Disruptor 通过 CAS 操作来代替加锁,从而提升性能,CAS 的性能大约是加锁操作性能的 8 倍,使用 Netty 接收处理数据时,不要在工作线程上进行处理,降低 Netty 性能,可以使用异步机制,通过线程池来处理,异步处理的话,就是用 Disruptor 来作为任务队列即可。在美团内部,很多高并发场景借鉴了Disruptor的设计,减少竞争的强度。 阅读详情

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 

👉这是一个或许对你有用的开源项目

国产Star破10w的开源项目,前端包括管理后台、微信小程序,后端支持单体、微服务架构

RBAC权限、数据权限、SaaS多租户、商城、支付、工作流、大屏报表、ERP、CRM、AI大模型、IoT物联网等功能:

  • 多模块:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • 微服务:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

【国内首批】支持 JDK17/21+SpringBoot3、JDK8/11+Spring Boot2双版本 

来源:君哥聊技术


Disruptor 是一个很受欢迎的内存消息队列,它源于 LMAX 对并发、性能和非阻塞算法的研究。今天一起来学习一下这个消息队列。

简介

对于主流的分布式消息队列来说,一般会包含 Producer、Broker、Consumer、注册中心等模块。比如 RocketMQ 架构如下:

Disruptor 并不是分布式消息队列,它是一款内存消息队列,因此架构上跟分布式消息队列有很大差别。下面是一张 LMAX 使用 Disruptor 的案例图:

我们介绍一下 Disruptor 架构中的核心概念。

1.1 Ring Buffer

Ring Buffer 通常被认为是 Disruptor 的最主要的设计,但是从 3.0 版本开始,Ring Buffer 只负责存储和更新经过 Disruptor 的数据。在一些高级的使用场景,它甚至完全可以被用户替换。

1.2 Sequence

Disruptor 使用 Sequence 来识别特定组件的位置。每个 Consumer(也就是事件处理器)都像 Disruptor 一样持有一个 Sequence。并发相关的核心代码依赖 Sequence 的自增值,因此 Sequence 具有跟 AtomicLong 相似的特性,事实上唯一的不同就是不同的 Sequence 之间不存在伪共享问题。

伪共享:CPU 缓存是以缓存行为单位进行加载和存储,CPU 每次从主存中拉取数据时,会把相邻的数据也存入同一个缓存行。即使多个线程操作的是同一缓存行中不同的变量,只要有一个线程修改了缓存行中的某一个变量值,该缓存行就会被标记为无效,需要重新从主从中加载。在多线程环境下,频繁地重新加载缓存行,会严重影响了程序执行效率。

1.3 Sequencer

Sequencer 是 Disrupter 的真正核心,有单个生产者和多个生产者两种实现(SingleProducerSequencer 和 MultiProducerSequencer)。为了让数据在生产者和消费者之间快速、准确地传输,它们都实现了所有并发算法。

1.4 Sequence Barrier

Sequencer 生成一个 Sequence Barrier,它包含由 Sequencer 生成的 Sequence 和消费者拥有的 Sequence 的引用。Sequence Barrier 决定是否有事件给消费者处理。

1.5 Wait Strategy

消费者怎样等待事件的到来。

1.6 Event Processor

主要负责循环处理来自 Disruptor 事件,它拥有消费者 Sequence 的所有权。有一个单独的实现类 BatchEventProcessor,这个类拥有高效的事件循环处理能力并且处理完成后可以回调实现 EventHandler 接口的用户。

1.7 Event Handler

由用户来实现并且代表 Disruptor 消费者的接口。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

2 Disruptor 特性

2.1 多播事件

多播事件是 Disruptor 区别于其他队列的最大差异。其他队列都是一个事件消息只能被单个消费者消费,而 Disruptor 如果有多个消费者监听,则可以将所有事件消息发送给所有消费者。

在前面 LMAX 使用 Disruptor 的案例图中,有 JournalConsumer、ReplicationConsumer 和 ApplicationConsumer 三个消费者监听了 Disruptor,这三个消费者将收到来了 Disruptor 的所有消息。

2.2 消费者依赖关系图

为了支持并发处理在实际业务场景中的需要,有时消费者直接需要做协调。再回到前面 LMAX 使用 Disruptor 的案例,在 journalling 和 replication 这两个消费者处理完成之前,有必要阻止业务逻辑消费者开始处理。我们称这个特征为“gating”(或者更准确地说,该特征是“gating”的一种形式)。

首先,确保生产者数量不会超过消费者。这通过调用 RingBuffer.addGatingConsumers()来将相关消费者添加到 Disruptor。其次,消费者依赖关系的实现是通过构建一个 SequenceBarrier,SequenceBarrier 拥有需要在它前面完成处理逻辑的消费者的 Sequence。

就拿前面 LMAX 使用 Disruptor 的案例来说,ApplicationConsumer 的 SequenceBarrier 拥有 JournalConsumer 和 ReplicationConsumer 这 2 个消费者的 Sequence,所以 ApplicationConsumer 对 JournalConsumer 和 ReplicationConsumer 的依赖关系可以从 SequenceBarrier 到 Sequence 的连接中看到。

Sequencer 和下游消费者的关系也需要注意。Sequencer 的一个角色就是发布的事件消息不能超出 Ring Buffer。这就要求下游消费者的 Sequence 不能小于 Ring Buffer 的 Sequence,也不能小于 Ring Buffer 的大小。

上面图中,因为 ApplicationConsumer 的 Sequence 必须要保证小于等于 JournalConsumer 和 ReplicationConsumer 的 Sequence,因此 Sequencer 只需要关心 ApplicationConsumer 的 Sequence。

2.3 内存预分配

Disruptor 的目标是低延迟,因此减少或者去除内存分配是必要的。在基于 Java 的系统中,目标是减少 STW 次数。

为了支持这一点,用户可以在 Disruptor 中预分配事件所需的内存。在预分配内存时,用户提供的 EventFactory 将对 Ring Buffer 的所有元素进行调用。当生产者向 Disruptor 发送新的事件消息时,Disruptor 的 API 允许用户使用构造好的对象,他们可以调用对象的方法或者更新对象的字段。Disruptor 需要确保并发安全。

2.4 无锁并发

Disruptor 实现低延迟的另一个关键方法时使用无锁算法,通过使用内存屏障和 CAS 来实现内存可见性和正确性。Disruptor 唯一使用锁的地方就是在 BlockingWaitStrategy。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

3 调优选项

虽然大多数场景下 Disruptor 可以表现出优秀的性能,但是仍然有一些调优参数可以改进 Disruptor 的性能。

3.1 单个/多个生产者

Disruptor<LongEvent> disruptor = new Disruptor(
 factory,
 bufferSize,
 DaemonThreadFactory.INSTANCE,
 ProducerType.SINGLE, 
 new BlockingWaitStrategy() 
);

上面是 disruptor 的构造函数,ProducerType.SINGLE 表示创建单生产者的 Sequencer,ProducerType.MULTI  表示创建多生产者的 Sequencer。

在并发系统中提高系统性能的最好方式是遵循单写原则。下面是官方的一个 disruptor 吞吐量测试结果,测试环境是 i7 Sandy Bridge MacBook Air。

单生产者:

多生产者:

3.2 等待策略

  1. BlockingWaitStrategy

disruptor 的默认等待策略是 BlockingWaitStrategy,这种策略使用锁和唤醒锁的 Condition 变量。

  1. SleepingWaitStrategy

跟 BlockingWaitStrategy 策略类似,他是通过 LockSupport.parkNanos(1) 方法来实现等待,不需要给 Condition 变量发送信号来唤醒等待。

主要适用于对延时要求不高的场景,比如异步打印日志。

  1. YieldingWaitStrategy

YieldingWaitStrategy 策略使用 Busy spin‌(不释放 CPU 资源,通过循环检查条件直到条件满足为止)技术来等待 sequence 增长到一个合适的值。在循环内部会调用 Thread#yield() 方法允许其他排队线程去执行。

这种策略主要用于通过消耗 CPU 来实现低延迟的场景。当 EventHandler 数量消息逻辑 CPU 核数并且对延迟要求较高时,可以考虑这种等待策略。

  1. BusySpinWaitStrategy

BusySpinWaitStrategy 是性能最高的等待策略,它适用于低延迟系统,但是对部署环境要求很高。

这种等待策略的唯一适用场景是当 EventHandler 数量消息逻辑 CPU 核数并且超线程被禁用。

4 官方示例

下面是一个官方示例。这个例子比较简单,就是生产者向消费者发送一个 long 类型的值。

  1. 首先定义一个 Event。

public class LongEvent
{
    private long value;

    public void set(long value)
    {
        this.value = value;
    }

    @Override
    public String toString()
    {
        return "LongEvent{" + "value=" + value + '}';
    }
}
  1. 为了能让 Disruptor 预分配内存,这里定义一个 LongEventFactory。

public class LongEventFactory implements EventFactory<LongEvent>
{
    @Override
    public LongEvent newInstance()
    {
        return new LongEvent();
    }
}
  1. 创建一个消费者来处理事件

public class LongEventHandler implements EventHandler<LongEvent>
{
    @Override
    public void onEvent(LongEvent event, long sequence, boolean endOfBatch)
    {
        System.out.println("Event: " + event);
    }
}
  1. 编写发送事件消息的逻辑

import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.examples.longevent.LongEvent;
import com.lmax.disruptor.util.DaemonThreadFactory;
import java.nio.ByteBuffer;

publicclass LongEventMain
{
    public static void main(String[] args) throws Exception
    {
        int bufferSize = 1024; 

        Disruptor<LongEvent> disruptor = 
                new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE);

        disruptor.handleEventsWith((event, sequence, endOfBatch) ->
                System.out.println("Event: " + event)); 
        disruptor.start(); 


        RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer(); 
        ByteBuffer bb = ByteBuffer.allocate(8);
        for (long l = 0; true; l++)
        {
            bb.putLong(0, l);
            ringBuffer.publishEvent((event, sequence, buffer) -> event.set(buffer.getLong(0)), bb);
            Thread.sleep(1000);
        }
    }
}

5 总结

作为一款高性能的内存队列,Disruptor 有不少优秀的设计思想值得我们学习,比如内存预分配、无锁并发。同时它的使用非常简单,推荐大家使用。


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,“长按”或“扫描”下方二维码噢:

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
Disruptor在撮合引擎的实践|得物技术 Disruptor是基于事件异步驱动模型实现的,采用了RingBuffer数据结构,支持高并发、低延时、高吞吐量的高性能工作队列,它是由英国外汇交易公司LMAX开发的,研发的初衷是解决内存队列的延迟问题,不同于我们常用的分布式消息中间件RocketMQ、Kafaka,而Disruptor是单机的、本地内存队列,类似JDK的ArrayBlockingQueue等队列。 阅读详情

相关推荐

Spring Boot + Disruptor = 王炸组合?2大框架联手,性能提升几倍?

摘要: 本文介绍了如何将高性能并发框架Disruptor与Spring Boot结合,构建高效异步处理系统。通过创建消息事件模型、实现事件工厂、配置Disruptor实例及事件处理器,演示了二者集成的完整流程。该方案利用Disruptor的环形缓冲区技术显著提升吞吐量,同时保留Spring Boot的快速开发优势,适用于高并发场景。文中包含详细的代码示例和实现逻辑,为开发者提供可落地的性能优化方案。

java专栏 1622

引入Disruptor ,系统性能大幅提升!

对于主流的分布式消息队列来说,一般会包含 Producer、Broker、Consumer、注册中心等模块。比如 RocketMQ 架构如下:Disruptor 并不是分布式消息队列,它是一款内存消息队列,因此架构上跟分布式消息队列有很大差别。下面是一张 LMAX 使用 Disruptor 的案例图:我们介绍一下 Disruptor 架构中的核心概念。作为一款高性能的内存队列,Disruptor 有不少优秀的设计思想值得我们学习,比如内存预分配、无锁并发。同时它的使用非常简单,推荐大家使用。

m0_50180963的博客 1083

深入解析高并发框架Disruptor代码

Disruptor 是一个高性能的事件发布-订阅框架,最初由 LMAX 公司开发用于其在线交易系统,旨在解决高并发场景下的数据共享问题。该框架利用内存队列技术,以环形结构为基础,通过无锁的算法实现了数据的高速发布和消费。与传统基于锁和阻塞机制的队列实现相比,Disruptor 能够显著提升数据处理速度,降低延迟,特别适合构建低延迟的高性能应用系统。传统的并发模型基于线程和锁机制,通过创建多个线程来处理并发请求,并用锁来同步线程之间的操作以避免数据不一致和资源冲突。

weixin_29317963的博客 558

引入Disruptor内存消息队列,系统性能大幅提升!

摘要:Disruptor是一款高性能内存消息队列,源于LMAX对并发算法的研究。其核心架构包括RingBuffer(数据存储)、Sequence(位置标识)、Sequencer(并发控制核心)等组件。主要特性包括:多播事件(支持多个消费者)、消费者依赖关系管理、内存预分配和无锁并发设计。通过不同的ProducerType(单/多生产者)和WaitStrategy(阻塞/睡眠/Yielding/BusySpin等待策略)可进行性能调优。Disruptor通过减少内存分配和使用CAS操作实现低延迟,适用于对性能

weixin_51582215的博客 1018

产业园区如何高效对接企业技术需求与高校科研成果?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

解决PubMed卡在“正在检查浏览器”页面的完整排查指南

DNS解析是将域名转换为IP地址的基础网络服务,其稳定性和准确性直接影响网站访问。当DNS服务器响应缓慢或返回异常结果时,可能导致客户端与服务器建立连接时出现偏差,从而触发网站的安全验证机制,例如Cloudflare等安全服务提供的浏览器环境检查。这一机制旨在防御恶意流量,但偶尔也会误拦截正常访问。在生物医学信息检索领域,PubMed作为核心文献数据库,其稳定访问对科研工作流至关重要。针对因DNS或本地缓存问题导致的‘正在检查浏览器’页面卡顿,通过刷新DNS缓存、更换为Google Public DNS或C

weixin_29597551的博客 3639

引入Disruptor ,系统性能大幅提升

对于主流的分布式消息队列来说,一般会包含 Producer、Broker、Consumer、注册中心等模块。比如 RocketMQ 架构如下:Disruptor 并不是分布式消息队列,它是一款内存消息队列,因此架构上跟分布式消息队列有很大差别。下面是一张 LMAX 使用 Disruptor 的案例图:我们介绍一下 Disruptor 架构中的核心概念。作为一款高性能的内存队列,Disruptor 有不少优秀的设计思想值得我们学习,比如内存预分配、无锁并发。同时它的使用非常简单,推荐大家使用。

m0_73735578的博客 1028

软件工程导论考试通关秘籍:太原理工大学历年真题解析(附答案)

本文为太原理工大学《软件工程导论》考试提供高效备考指南,通过解析近六年真题,揭示高频考点如软件生命周期、UML建模和结构化设计等核心模块的命题规律。文章提供真题拆解、实战策略和避坑指南,帮助考生掌握图形转换题和简答题的应答技巧,助力考试通关。

weixin_29233333的博客 227

Disruptor二

其实Disruptor与其说是一个框架,不如说是一种设计思路,这个设计思路对于存在“并发、缓冲区、生产者—消费者模型、事务处理”这些元素的程序来说,Disruptor提出了一种大幅提升性能(TPS)的方案。 Disruptor是一个高性能的异步处理框架,或者可以认为是最快的消息框架(轻量的JMS),也可以认为是一个观察者模式的实现,或者事件监听模式的实现。 Disruptor术语说明 RingBuffer: 被看作Disruptor最主要的组件,然而从3.0开始RingBuffer仅仅负责存储和更新在

mahui_1980的专栏 211

在后端设计中,GDSLL,LEF,DEF,SDF,SPEF,SDC各代表什么意思?前端和中端流程中,SVF,SAIF又代表什么意思?

在后端设计中,GDSLL,LEF,DEF,SDF,SPEF,SDC区别?前端和中端流程中,SVF,SAIF代表什么意思?

weixin_43274923的博客 1万+

基于Ultralytic实现多路摄像头目标检测

基于Ultralytic实现多路摄像头目标检测前面的文章分享了单路摄像头画面的YOLO目标检测,这篇文章主要分享一下多路摄像头画面的实时YOLO目标检测。测试环境在Windows系统下进行。

qq_57674776的博客 941

支撑每秒数百万订单无压力,SpringBoot + Disruptor 太猛了!

事件工厂用于生成OrderEvent@Override事件处理器是实际处理事件的地方。@Override// 处理订单的具体业务逻辑// 模拟订单支付逻辑System.out.println("处理订单: " + orderEvent.getOrderId() + ", 用户: " + orderEvent.getUserId() + ", 金额: " + orderEvent.getPrice());// 假设订单处理通过后更新订单状态。

1191

QMT实盘避坑指南:从环境配置到策略部署的完整流程(含国金证券路径设置)

本文是一份详尽的QMT实盘交易避坑指南,重点解析了从环境配置到策略部署的完整流程。针对国金证券QMT平台,文章深入剖析了核心架构、精准路径配置、关键参数解析、交易操作实战及异常处理,并提供了策略部署、监控与日志构建的完整方案,旨在帮助具备Python基础的开发者规避常见陷阱,实现稳定可靠的实盘交易。

weixin_29309475的博客 592

高性能队列——Disruptor

Disruptor应用背景和介绍传统队列问题高性能的原理 应用背景和介绍 Disruptor 是英国外汇交易公司 LMAX 开发的一个高性能队列,研发的初衷是 解决内部的内存队列的延迟问题,而不是分布式队列。基于 Disruptor 开发的系 统单线程能支撑每秒 600 万订单,2010 年在 QCon 演讲后,获得了业界关注。 据目前资料显示:应用 Disruptor 的知名项目有如下的一些:...

深入Java世界:探索编程之美与技术深度 590

Android 白名单保活实战:主流厂商适配指南

本文详细解析了Android应用白名单保活的实战策略,重点针对华为、小米、OPPO、vivo等主流厂商的系统特性,提供了精准的后台设置页面跳转适配方案。文章从基础的前台服务实现讲起,深入讲解了白名单的判断、申请与厂商适配的核心代码与避坑指南,旨在帮助开发者合规、稳定地提升应用后台存活率。

motor的博客 1861

从战略到执行:业务领先模型 BLM 的第一把钥匙「差距分析」

业务领先模型「BLM」(Business Leadership Model),俗称“别乱摸”,起源于哈佛商学院的战略理论研究,是一套完整的战略规划方法论。 后来被 IBM 发扬光大,IBM 在转型关键时期完成了对 BLM 模型的导入和创新,从此这个模型成为 IBM 中高层用于战略制定与执行联接的方法与平台。 再到后来华为花巨资引入了 BLM 模型,经过多年的应用,将其演化成了公司战略规划和落地的主要方法与流程,也因此被中国科技企业所认识和接受。 BLM 模型可以解决哪些问题? 在企业内,

产品线负责人 2400

SpringBoot集成Disruptor

SpringBoot集成Disruptor

GSl0408的博客 626

亲测解决This application failed to start because no Qt platform plugin could be initialized.

这个问题是由于环境变量改变或者Qt的路径改变导致,解决办法是在环境变量里面重新添加Qt路径。

狂小虎/Anthony Dave的博客 KuangXiaoHu's Blogs 2920

电商秒杀系统:Disruptor实战优化案例

高并发场景下,数据结构的选型至关重要减少锁竞争是提高性能的关键批处理比单条处理效率高得多监控和指标收集必不可少在InsCode(快马)平台上部署这个项目非常简单,一键就能运行起来。平台内置了完整的开发环境,不需要自己配置各种依赖,特别适合快速验证这类性能优化方案。如果你也在做类似的性能优化,建议先在小规模场景下验证,确认效果后再逐步推广到生产环境。Disruptor虽然强大,但也要根据实际业务场景来合理使用。

CrystalwaveStag的博客 879

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

SpringBoot 项目使用 Disruptor 做内部消息队列

点击关注公众号,利用碎片时间学习一、背景工作中遇到项目使用Disruptor做消息队列,对你没看错,不是Kafka,也不是rabbitmq;Disruptor有个最大的优点就是快,还有一点它是开源的哦,下面做个简单的记录.二、Disruptor介绍Disruptor 是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与...

Java笔记虾 558

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

高性能队列Disruptor的初体验

Disruptor 是一个高性能、低延迟的无锁队列替代方案,最初由 LMAX 公司开发,专为处理高吞吐量和低延迟的消息传递系统而设计。它利用环形缓冲区(RingBuffer)和无锁的生产者-消费者模型,大幅提升并发性能。今天先初步了解Disruptor的简单用法,后续会继续介绍Disruptor的特性,为什么性能秒杀JDK提供的队列,以及相关原理分析。:用于协调生产者和消费者的进度,确保消费者不会读取尚未发布的数据。,用于跟踪当前生产和消费的位置。:一个消费者的输出作为另一个消费者的输入。

shemuel的技术笔记 1016

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

上一篇: 25k star,一款超美观强大的 Nginx 可视化管理神器!
下一篇: 很严重了,我劝大家极限搞钱吧。。。
公众号-芋道源码
博客等级 码龄10年 1631粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值