ElasticSearch

1.elasticsearch、Kibana概念,elasticsearch相关术语

       1.1 ElasticStack

              ElasticSearch:基于json的分布式搜索和分析引擎

                     搜索、聚合分析、大数据存储

                     分布式、高性能、高可用、可伸缩、易维护

                     支持文本搜索、结构化数据、非结构化数据、地址位置搜索等

              Logstash:动态数据收集管道,生态丰富。可进行采集、过滤、输出。ElasticSearch是官方首选输出方式,但并非唯一选择

              Kibana:数据可视化界面

                     查询、查看并与存储在ES索引的数据进行交互操作

                     执行高级的数据分析,并能以图表、表格和地图的形式查看数据

              Beats:轻量级的数据采集器

                     开源、轻量级、即插即用、可扩展

       1.2 ElasticSearch

              Restful

                     REST(Representational State Transfer) 表现层状态转化,如果一个架构符合REST原则,则称为RESTFUL架构风格

                     资源:网络上的一个实体

                     表现层(Representation):资源呈现出来的形式

                     状态转化(State Transfer):客户端向操作服务端,使服务端状态发生转化,这种转化是建立在表现层基础上的,故称之为表现层状态转化

                     REST原则:一个URL表示一个资源,通过HTTP协议中的4个动词GET、POST、PUT、DELETE来对应服务器端的4种操作.GET对应获取资源,POST对应添加或更新资源,PUT对应更新资源,DELETE对应删除资源。

              全文检索(Full Text Retrieval)

                     定义:计算机程序扫描文章中每一个词,给每个词建立一个索引,指明该词在文章出现的次数和位置。当用户查询数据时根据索引查询,类似于字典检索查字。

                     关键指标:以文本作为检索对象,从文章中找出含有指定词汇的文本。全面、快速和准确是衡量全文检索系统的关键指标。

                     特点:只处理文本,不处理语义;搜索时英文不区分大小写;结果列表有相关度排序

       1.3 ElasticSearch

              定义:简称ES,是基于Apache Lucene构建的开源搜索引擎(企业级)。使用java语言编写,提供简单易用的RESTFUL API,使用其开发相关搜索功能,避免了Lucene的复杂性

              应用场景

                     ElasticSearch以轻量级JSON作为数据存储格式,与MongoDB类似,但读写性能优于MongoDB.同时支持地理位置查询,方便地理位置和文本混合查询。以及进行统计、日志类数据存储和分析、可视化方面是引领者。

                     维基百科、github、stackoverflow、百度、腾讯、新浪、阿里等都使用了ES.

              安装

                     ElasticSearch访问端口是9200

                     安装之后生产环境 ElasticSearch目录下的data和logs对应数据存放目录和日志存放目录,务必修改

       1.3 Kibana

              定义:Kibana Navicat是针对Elasticsearch的开源分析及可视化平台。可针对ES索引中的数据查看、查询、交互;也可执行数据分析,并能以图标、表格、地图形式显示数据

              端口:默认5601

       1.4 ElasticSearch相关术语

              接近实时(NRT)(Near Real Time):接近实时搜索,从索引文档到出现结果延迟很低,接近1S内

              索引(index):1个索引拥有几分相似特征的文档的集合。由全小写字母组成。可对索引中的文档进行索引、搜索、更新、删除,都需要用到索引名

              映射(Mapping):相当于数据库的schema,用于约束字段的数据类型,每种数据类型都有其对应的使用场景。mapping定义了一个文档所包含的所有field信息,每个文档都有映射。但是绝大多数场景中,并不需要手动编写映射,ES实现了动态映射。

                     ElasticSearch常见数据类型:字符串类型、整数、浮点、逻辑、日期、范围、二进制、数组、对象、嵌套、地理坐标、IP、令牌计数

              文档(Document):1个文档是可被索引的最小单元,类似表中的1条记录,采用轻量级的数据交换格式JSON表示

                     文档类比关系数据库中的1条数据;每个文档都有唯一的ID,类比关系数据库主键ID;json对象由于field构成,field类比关系数据库的column

                     文档除了基础数据外,还包含元数据(metadata-关于文档的信息),用下划线开头的字段,是官方提供的

                     _index:文档所属索引名称,即文档存储地方

                     _type:文档所属类型名字,默认_doc

                     _id:文档唯一表示。写入时候可以指定此值,不指定,系统会自动生成唯一的UUID值

                     _score:得分,相关性

                     _source:文档原始JSON数据

              字段(field):相当于数据表的字段,可理解为JSON数据的键,是文档中基本单位,以键值对形式存在

              ES和DB关系:

2.ElasticSearch客户端操作索引、映射、文档

       通过Kibana的DEV Tools充当Elasticsearch客户端来操作ES

       2.1索引基本操作:

              创建索引: PUT /索引名

                     ES中索引状态:red(不可用)、yellow(有风险但可用)、green(健康)

                     创建索引默认为索引创建1个副本索引和1个分片索引

              查询索引: GET /索引名?v

              删除索引: DELETE /索引名

              删除所有索引:DELETE /*    *为通配符,代表所有索引

       2.2 映射操作

              只有text类型才会进行分词

              创建映射:

                     PUT /索引名

                     {

                            "mapping":{

                                   "properties":{

                                          "实际业务字段名":{

                                                 "type":"实际业务字段数据类型"

                                          },

                                         

                                          "实际业务字段名1":{

                                                 "type":"实际业务字段数据类型1"

                                          }

                                   }

                            }

                     }

                     示例:

                            PUT /products

                            {

                                   "mapping":{

                                          "properties":{

                                                 "title":{

                                                        "type":"keyword"

                                                 },

                                                 "price":{

                                                        "type":"double"

                                                 }

                                          }

                                   }

                            }

              查询某个索引的映射

                     语法:GET /索引名/_mapping  

                     示例:GET /products/_mapping

       2.3 文档基本操作

              添加文档:PUT /索引名/_doc/id

              查询文档:GET /索引名/_doc/id

              删除文档:DELETE /索引名/_doc/id

              更新文档:

                     第一种方式更新原有数据:

                            POST /索引名/_update/id

                            {

                            "doc":{

                                   "name":"xiaobai"

                            }

                            }

                     第二种方式 添加新的数据:

                            POST /索引名/_update/id

                            {

                            "name":"xiaohong",

                            "age":11,

                            "dept":"测试部门",

                            }

                     第三种方式 在原基础数据上更新

                            POST /索引名/_update/id

                            {

                                   "script":"ctx._source.age+=5"

                            }

              批量操作(非原子操作)

                     _bulk 批量操作

                     index  批量添加

                     delete 批量删除

                     update 批量更新

                     批量操作不会因为1个失败而全部失败

3.ElasticSearch高级查询、索引库原理、倒排索引、DSL高级检索

       检:根据查询条件查询文档

       索:对文档创建索引的过程

       3.1 检索方式 _search

              ES提供了2种检索方式:通过URL参数进行检索;通过DSL(Domain Specified Language)进行检索。官方推荐使用DSL,因为DSL是基于传递JSON作为请求体格式与ES进行交互,此方式更简洁强大

              使用语法

                     URL查询:GET /索引/类型/_search?参数

                            示例:

                            查询某索引下所有数据: GET/索引名/_search?q=*

                            查询所有并根据age升序:GET /索引名/_search?q=*&sort=age

                            查询所有并根据age降序:GET /索引名/_search?q=*&sort=age:desc

                            分页查询(ES默认每页10条):GET /索引名/_search?q=*&sort=age:desc&size=2&from=0

                            指定显示字段:GET /索引名/_search?q=*&_source=name,age

                     DSL查询(重点)

                            基本语法:: GET /索引/类型/_search {}

                            示例:

                            查询所有文档:GET /索引名/_search {"query":{"match_all":{}}}

                            排序(text不支持排序,keyword支持):GET /索引名/_search {"query":{"match_all":{}},"sort":[{"age":{"order":"desc"}},{"address":{"order":"desc"}}]}

                     DSL高级检索(重点),只列举一部分关键字,其余可至网页中查看

                            查询所有(match_all-关键字表示返回索引中的全部文档),示例:GET /索引名/_search {"query":{"match_all":{}}}

                            查询结果中返回指定条数(size),默认返回10条,示例:GET /索引名/_search {"query":{"match_all":{}},"size":1}  表示返回第1条文档

                            分页查询(from),from关键字指示起始返回位置,和size连用实现分页,示例:GET /索引名/_search {"query":{"match_all":{}},"size":2,from:1}

                            布尔查询(bool):

                                   must:相当于&&,多个条件必须同时满足

                                   should:相当于||,1个条件满足即可

                                   must_not:相当于!,不能满足任何1个条件

4.ElasticSearch中的分词器,IK分词器介绍

       4.1 Analysis和Analyzer

              Analysis:文本分析是将全文本转换为一系列单词的过程,也叫分词。Analysis是通过Analyzer来实现的。

                     分词就是将文档Analyzer分成一个个的Term(关键词查询),每一个Term都指向包含这个Term的文档

              Analyzer组成:  

                     StandAnalyzer标准分词器(ES默认分词器),中文进行单字分词,英文根据单词分词

                     分析器(Analyzer)由三部分构成:character filters(字符过滤器)、tokenizers(分词器)、token filters(Token过滤器)

                     character filters:文本分词之前,进行预处理。最常见的就是过滤html标签

                     tokenizers:英文分词根据空格将单词分开,中文分词较为复杂,采用机器学习算法来分词

                     Token Filters:将切分的单词进行加工。例如大小写转换、去掉停用词、加入同义词等

                     以上三者顺序:character filters->tokenizers->Token Filters

                     三者个数:character filters(0个或者多个),tokenizers,Token Filters (0个或者多个)

       4.2 内置分词器

              StandAnalylzer 默认分词器,英文按照单词切分,并小写处理,中文按照单字分词

              Simple Analyzer:按照单词切分(符号被过滤),小写处理

              标准分词器测试:POST /索引名 {"analyzer":"standard"}

              simple分词器测试:POST /索引名 {"analyzer":"simple"}

       4.3 中文分词器(IK分词器):ES中支持多种中文分词器,如smarkCN、IK。首选推荐IK分词器。

              安装IK:

                     IK分词器开源github:https://github.com/medcl/elasticsearch-analysis-ik。注意IK需要和ES版本一致

              IK分词器有2种粒度的拆分:

                     ik_smart:最粗粒度拆分。示例:POST /_analyze {"analyzer":"ik_smart","text":"中华人民共和国"}

                     ik_max_word:最细粒度拆分。示例:POST /_analyze {"analyzer":"ik_max_word","text":"中华人民共和国"}Client

              扩展词、停用词配置

                     IK支持自定义扩展词典和停用词典

                     扩展词典:某些词非关键词,但是希望被ES用作检索的关键词,可将这些词加入词典

                     停用词典:有些词为关键词,但是某些常见不希望这些词被检索到,将这些词放入停用词典

                     定义扩展字段修改IK分词器目录config文件夹下的IKAnalyzer.cfg.xml文件,通过enrey标签,指定扩展词典和停用词典的文件路径,然后在config目录下创建扩展词典和停用词典的文件(.dic),最后在congig文件夹中创建扩展词典和停用词典对应的文件,在其中添加对应的内容,最后重启ES即可。注意:词典编码必须为UTF-8,否则不生效。

5.过滤查询、聚合查询

       5.1 Filter Query 过滤查询

              准确说,ES中查询操作分2种,查询和过滤

              查询即上述提到的查询,默认会计算每个文档的得分,根据得分排序

              过滤只会筛选出符合的文档,并不计算得分,且它可以缓存文档。单从性能考虑,过滤比查询效率更快。

              过滤适合大范围筛选数据,查询适合精确匹配数据。一般应用时,先进行过滤,然后使用查询进行精确匹配

             

              过滤语法:GET /索引名/_search {"query":{"filter":{}}}。先执行filter后执行query。ES会缓存经常访问的过滤器,从而加快性能

             

              常见的过滤器模型:

                     term:过滤某字段关键字为某值的文档

                     terms:过滤某字段关键字不包含某几个值的文档

                     ranage:过滤某字段处于某范围的文档

                     exists:过滤存在指定字段的文档

                     ids:过滤含有指定字段的索引记录    

       5.2 聚合查询

              简介:Aggregation,是ES除搜索功能外,针对ES数据做统计分析的功能

              注意:text类型不支持聚合查询

              常见使用:

                     根据某字段分组:"aggs":{"分组名":{"terms":{"field":"分组的字段"}}}

                     求最大值:"aggs":{"自定义最大值字段名":{"max":{"field":"取最大值的字段名"}}}

                     求最小值:"aggs":{"自定义最小值字段名":{"min":{"field":"取最小值的字段名"}}}

                     求平均值:"aggs":{"自定义平均值字段名":{"avg":{"field":"取平均值的字段名"}}}

                     求和:"aggs":{"自定义求和字段名":{"sun":{"field":"取和的字段名"}}}

6.spring boot整合RestHighLevelClient(优先)

       6.1 RestHighLevelClient介绍

              JavaRest有两种模式:

                     Java Low Level Rest Client:ES官方的低级客户端,通过http与ES集群通信

                     Java High Level Rest Client: ES官方的高级客户端,基于低级客户端,也是通过http与ES集群通信,提供了更多的接口

                     注意:Client客户端版本尽量小于等于ES本体的版本,否则出现客户端的使用的API在ES中不支持

                     优先使用RestHighLevelClient,不建议使用spring-data-elasticsearch。主要原因是灵活性和更新速度,spring将elasticsearch过度封装,开发者很难和DSL查询语句进行关联;其次就是ES更新速度很快,但是spring-data-elasticsearch更新速度比较缓慢。

       6.2 引入依赖

              引入org.elasticsearch.elasticsearch,org.elasticsearch.client.elasticsearch-rest-client;org.elasticsearch.client.elasticsearch-rest-high-level-client 3个jar包

       6.3 ES配置

              创建索引

              sptingboot项目中application.yml配置文件中配置 elasticsearch的host和port

              实体类创建

              elasticsearch配置类创建,定义方法,注入RestHighLevelClient

       6.4 索引操作

              创建索引和映射表结构、获取表结构、删除索引库、判断索引是否存在

       6.5 文档操作

              增加文档、获取文档、更新文档、删除文档

       6.6 Bulk操作

              通常从mysql中查询大量数据导入es中

       6.7 DSL操作

              term(精确查询-和查询字段完全匹配)、terms(精确查询-和terms类似,区别在于terms允许指定多个匹配条件)、全文查询、通配符查询、模糊查询、排序查询、分页查询、

              范围查询、bool查询、queryString查询、查询结果过滤、高亮查询、聚合查询(max、min、sum、avg等)、查询集群状态、查询索引信息

7.springboot整合spring-data-elasticsearch

       7.1 简介

              springdata是用于简化数据库访问、非关系型数据库访问、索引库访问的开源框架。

              springdataelasticsearch是基于spring data api简化elasticsearch操作。提供2个对象操作文档,分别是ElasticsearcRepository接口和ElasticsearchRestTemplate,分别提供了对文档的基础操作和复杂操作

              优先使用RestHighLevelClient

       7.2 引入依赖、yml配置、实体类

              引入spring-boot-starter-data-elasticsearch;

              application.yml中配置es的URI

              定义实体类,使用@Document(indexName="自定义索引名")修饰,指定当前类对应ES中那个索引;使用@Id标记作为id主键的成员变量;使用@Field标记成员变量,标记为文档字段,并映射数据类型

       7.3 定义接口继承ElasticSearchRepository接口

              使用该接口即可进行简单的CRUD操作;同时也可自定义方法,并且spring data可根据方法名自动实现功能,前提是符合方法定义规定

       7.4 使用ElasticSearchRestTemplate进行高级查询

              term(精确查询-和查询字段完全匹配)、terms(精确查询-和terms类似,区别在于terms允许指定多个匹配条件)、全文查询、通配符查询、模糊查询、排序查询、分页查询、

              范围查询、bool查询、queryString查询、查询结果过滤、高亮查询、聚合查询(max、min、sum、avg等)

8.springboot整合JestClient

       8.1 JestClient介绍

              非官方提供的ES客户端,此客户端已不再维护,优先使用RestHighLevelClient

       8.2 引入依赖

              io.searchbox.jest;

       8.3 ES配置

              application.yml配置es连接属性;

              定义JestClientConfig类,注入JsetClient

       8.4 JestClient操作ElasticSearch

              常用操作和RestHighLevelClient类似

9.ES集群概念、节点故障恢复问题、路由计算、协调节点、倒排索引      

       9.1 ES集群

              由单个或多个ES节点组成,提供负载均衡以及ES搜索吞吐量等功能,避免单节点故障

              集群共同持有整个数据,一起提供索引和搜索功能,一个集群有唯一的名字,默认是elasticsearch。节点通过集群名字来加入集群

             

              节点Node:

                     es实例的java进程,启动时通过-Enode.name指定节点,每个节点都会存储集群的状态信息

                     集群状态包括:所有节点信息、所有索引及Mapping和Setting,分片路由信息

                     1个节点是1个集群的一部分,存储的数据参与集群的索引和搜索功能

              节点类别:

                     Data Node:保存分片数据的节点

                     Coordination Node:协调节点负责接收客户端请求并将请求转发到合适的节点,并负责汇总结果。默认情况下每个节点都有此职责

                     Hot&Warm Node:不同配置的Data Node组成,主要为了降低成本,Hot节点使用高配置,warm节点使用低配置

              分片Shard:ES可将索引划分成多份的能力,每一份即为分片。

                     创建索引可指定分片数量,每个分片也是功能晚上且独立的"索引",分片可放在集群中任何节点上。

                     分片针对索引,1个索引的数据由多个分片存储,每个分片又位于不同的节点上。好处在于提高了索引的物理存储,提高了索引的查询速度、吞吐量。

                     分片允许水平分隔/扩展内容容量;允许在分片上进行分布式/并行操作,进而提高性能/吞吐量

                     默认情况下,ES中每个索引有1个主分片和1个复制分片。

                     分片合理配置:分片数和节点数相关,分片数过少影响节点扩容,分片数过多影响查询性能。

              副本replicas:

                     网络/云环境中,某个分片可能中断运行或数据丢失,ES针对此问题,对每个分片提供了1个对应的副本分片,即复制分片,解决数据高可用问题

              分配:将分片分配给某节点,是由master节点完成的

       9.2 集群健康值检查

              健康值状态有以下3种

                     GREEN:所有主分片和副本分片均为active,集群可正常使用

                     YELLOW:至少1个副本分片不可用,但是所有主分片都是active,数据仍然可保证数据完整性

                     RED:至少1个主分片不可用,数据不完整,集群不可用

              健康值检查:

                     GET _cat/health?v

                     GET _cluster/health

       9.3 常用集群部署架构

              todo

       9.4 单节点集群

              集群内只有1个节点,创建索引,包含3个主分片和3个复制分片,位于同一个节点上。主分片都正常,但是副分片都是未启动,因为没有分配任何节点。主分片和副本分片位于同一个节点是没有意义的,因为一旦失去节点,数据也随之丢失。当前集群是yellow状态,可运行,但有丢失数据的风险

       9.5 单节点故障转移

              集群中只有1个节点运行,会有1个单点故障问题,没有冗余(只有1个节点,副本不会生效)。只需启动第二个节点即可防止数据丢失。如果是在同1台机器上启动多个节点,多个节点只需配置相同的

              cluster.name即可加入相同的集群。如果是在不同机器上启动节点,为了保证加入同一集群,需要配置1个可连接到的单播主机列表,防止节点无意中加入集群。

              启动第二个节点后,主片和副本会分配在不同的节点上。此时集群状态为:GREEN.

       9.6 新增节点到集群

              为正在增长的应用程序扩容,当启动第三个节点,集群会为了分散负载而对分片进行重新分配。会实现每个节点上2个分片,每个节点的资源被更少的分片共享,每个分片的性能将会得到提升。

              分片是1个功能完整的搜索引擎(底层是Lucene搜索引擎),拥有使用节点上所有资源的能力。上述6个分片最大可扩容到6个节点,每个节点存在1个分片。从而实现每个分片使用每个节点的所有资源

              创建索引需要确定主分片的数量,并且永远不可改变此数量,一旦数量变化,那么之前路由的值都会无效,文档再也找不到了

              向es中写入文档,是根据公式计算文档应存储至那个分区中,取文档也是根据相同公式,一旦分片数变更,文档自然就找不到。

              读操作(搜索数据和返回数据):可同时被主分片和副本分片处理,拥有越多分片数量,吞吐量越高。

            因此虽说主分片数量无法修改,但副分片数量可以在集群中动态调整,按需伸缩集群,原来是3个主分片和3个副分片,可将副分片从1变为2,则拥有3个主分片和6个副分片,意味着可将集群中节点

              数量扩展为9个,1个节点对应1个分片,相对原来3个节点,集群搜索性能可提升3倍数。

              如果节点不变,只是单纯添加副本,性能是不会有变化的,因为每个分片从节点上获取的资源变少,需要提升硬件资源来提高吞吐量。

              副本并非越多越好,因为副本越多,数据冗余越多,在大数据的情况下,对存储压力很大。

       9.7 集群节点故障

              假设集群有3个节点,有1个节点离开集群,那么此时集群还剩2个节点。

              如果离开的是主节点,集群为了保证必须有1个主节点运行的原则,所以注解点挂后会立马选举1个新的节点来作为主节点。

              如果离开的节点中包含主分片,此时检查集群状态为RED,并非所有主分片都正常工作。但其他节点上存在挂了的主分片的副本的话,新的主节点会将这些分片在其他节点上的副本提升为主分片,此时集群状态是yellow.提升主分片的过程是瞬间的,如果按下开关一般。此时状态非green,是因为一开始设置了每个主分片需要2个副分片,此时每个主分片只有1个副分片,所以集群非green.

              但不影响集群运行,如果想恢复为原有状态,原有主节点配置文件中有:discovery.send_hosts["第二个节点的ip加端口","第三个节点的ip加端口"]

       9.8 路由计算&分片控制(协调节点)

              路由计算

                     创建的文档如何确定在那个分片中,通过以下公式计算的出

                     shard = hash(routing)%number_of_primary_shards(主分片数量)

                     routing是是一个可变值,默认是文档id,也可设置成自定义值。得出结果后,就是文档所处的分片的位置

              分片控制(协调节点)

                     可发送请求到集群中的任一节点,每个节点都有能力处理任意请求(建立在每个节点的分片数据都一样的前提下),每个节点都知道集群中任一文档位置,所以可直接将请求转发到指定的节点上

       9.9 数据写流程

              新建、索引、删除文档等操作都是写操作,必须在主分片上完成才能复制到相应的副本分片

              客户端请求集群任意节点(协调节点)->协调节点将请求转换到指定节点->主分片保存数据——>副本分片保存数据后反馈->主分片反馈->客户端反馈

       9.10 数据读流程

              接收查询请求->轮询节点,选择节点为协调节点->协调节点计算数据所处分片及全部副本位置->通过轮询策略,将请求转发至其他节点->节点返回查询文档后,返回给客户端

       9.11 数据更新流程           

              客户端接收更新请求->任意节点接收请求(协调节点)->将请求转发至对应的节点->对应节点从主分片中获取数据进而修改数据(如果数据已被另一个进程修改,则此步骤会再次尝试,超过retry_on_conflict次后放弃)->主分片所处节点更新完毕后,新版本文档同步副本分片->副本分片返回成功后,主分片返回成功,协调节点返回客户端成功

       9.12 倒排索引

              ElasticSearch使用一种倒排索引的数据结构,适用于快速的全文检索

              正向索引(foward-index):搜索引擎将文件对应一个文件id,搜索时将id和关键字相对应,形成K-V对,然后对关键字进行统计计数,但是互联网搜索引擎中的文档是天文数字,此结构无法做到实时返回排名结果

              倒排索引(inverted-index):为了解决正向索引的问题,搜索引擎会将正向索引重新构建为倒排索引,即将id对应关键字的映射转换为关键字对应文件id的映射,每个关键字都对应一些文件Id,这些文件中都包含这个关键词

             

              倒排索引示例:将2个文档拆分成单独的词,创建1个不包含重复词条的排序列表,包含词汇、及词汇在每个文档中是否存在。

                                   将词条规范为标准模式,可以找到与用户的搜索词不完全一致,但具有足够的相关性。

                                   索引文本和查询字符串必须标准化为相同的格式

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值