Redis(实操1)

 Redis可视化工具-安装Redis_Desktop_Manager

官网RESP.app (formerly Redis Desktop Manager) - GUI for Redis ® available on Windows, macOS, iPad and Linux.

下载完成后连接到redis服务(redis相当于一个服务端)

 注意:

1.检查防火墙是否关闭(systemctl stop firewalld.service)

查看防火墙运行情况

2.redis默认只允许本地访问,远程访问需要修改redis.conf

注释掉bind 127.0.0.1 -::1

关闭保护模式

重启redis服务(停掉后重启)

连接后双击可视化工具中的redis

​(出现默认的16库)

Java整合Redis_Jedis操作

手动缓存效率低,故利用java连接工具jedis操作redis。

创建maven项目redis-demo,引入jedis包

image-20210716133637202

 pom文件引入依赖

<dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
   <version>3.6.0</version>
</dependency>
<dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.12</version>
   <scope>test</scope>
</dependency>

test中创建包:

//jedis测试用例
public class JedisTest{
    Jedis jedis;


    //初始化jedis实例
    @Before
    public void init(){
        //创建redis连接
        jedis = new Jedis("192.168.202.100",6379);
    }

    //string操作
    @Test
    public void stringTest(){
        //设置一个key
        jedis.set("k1","k2");
        //获取key的值
        String k1 = jedis.get("k1");
        System.out.println(k1);
        //设置key过期时间为10
        jedis.setex("k2",10,"v2");
    }

    //list操作
    @Test
    public void listTest(){
        //添加元素lpush
        jedis.lpush("list1","v1","v2");
        jedis.rpush("list1","v3","v4");

        //获取所有元素
         List<String> list1 = jedis.lrange("list1",0,-1);
        //遍历元素
        for(String s : list1){
            System.out.println(s);
        }
    }


     //set操作
    @Test
    public void setTest(){
        //添加元素
        jedis.sadd("set1","v1","v2","v3","v3");
        //获取元素
        Set<String> set1 = jedis.smember("set1");
        //遍历所有元素
        for(String s : set1){
            System.out.println(s);
        }
    }
  

    //Hash操作
    @Test
    public void HashTest(){
       //设置hash    
        jedis.hset("user","age","26");
        jedis.hset("user","name","baizhan");

       //获取所有key的value的值
        List<String> user = jedis.hvals("user");
       //遍历所有元素
        for(String s : user){        
            System.out.println(s);
        }
    }

    //zset操作
     @Test
     public void zsetTest(){
        //添加元素
        jedis.zadd("zset",100,"Java");
        jedis.zadd("zset",200,"Python");
        jedis.zadd("zset",300,"C++");
        jedis.zadd("zset",400,"C");

        //获取所有值
        Set<String> zset = jedis.zrange("zset",0,-1);
        //遍历所有值
        for(String s : zset){
            System.out.println(s);
        }
     }



    //bitmaps数据类型
    @Test
    public void bitmapTest(){
        //给张三添加上班打卡记录
        jedis.setbit("zhangsan:2",0,"1");//第一天
        jedis.setbit("zhangsan:2",1,"1");
        jedis.setbit("zhangsan:2",2,"0");//第三天
        jedis.setbit("zhangsan:2",3,"1");

        //获取张三第3天的上班记录(是否迟到)
        Boolean getbit = jedis.getbit("zhangsan:2",2);
        //如果是1为true 0为false
        System.out.println(getbit);
    }

    //geo操作
    @Test
    public void geoTest(){
        //添加地理信息
        jedis.geoadd("china",130,30,"beijing");
        //获取地理信息
        List<GeoCoordinate> geopos = jedis.geopos("china","beijing");

        //遍历位置信息
        for(GeoCoordinate geopo : geopos){
            System.out.println(geopo.toString());
        }
    }

    //hyperLog操作
    @Test
    public void hyperLogTest(){
        //添加元素
        jedis.pfadd("book","uid1","uid2","uid3","uid2","uid2");
        //获取书籍数量
        long bookCount = jedis.pfcount("book");
        System.out.println(bookCount);
  
    }
   


    
    //关闭jedis实例
    @After
    public void close(){
        //关闭redis连接
        jedis.close();
    
    }





}

Java整合Redis_Spring-Data-Reids

简介

Spring-Data-Redis是spring大家族的一部分,通过简单的配置访问Redis服务,对Reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了Redis各种操作、异常处理及序列化,支持发布订阅。

RedisTemplate介绍

Spring封装了RedisTemplate对象来进行对Redis的各种操作,它支持所有的Redis原生的api。

注意:

  • K:模板中的Redis key的类型,模板中的Redis key的类型(通常为String)如:RedisTemplate<String, Object>。
  • V:模板中的Redis value的类型

RedisTemplate中定义了对5种数据结构操作

redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set

创建一个SpringBoot项目

1.配置文件(告诉其我们的redis服务在哪里)

#Redis服务器连接地址
spring.redis.host=192.168.202.100
#Redis服务器连接端口
spring.redis.port=6379
#连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
#连接池中的最大空闲连接
spring.redis.pool.max-idle=8
#连接池中的最小空闲连接
spring.redis.pool.min-idle=0
#连接超时时间(毫秒)
spring.redis.timeout=30000

2.通过测试类启动redis并操作redis服务

StringRedisTemplate与RedisTemplate

  • 两者的关系是StringRedisTemplate继承RedisTemplate。

  • 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。

  • SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。

    StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。

    RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。

修改String的序列化机制为json序列化

3.在测试类前创建config包修改序列话方式(json)

/**
 * 自定义序列化方式
 */
@Configuration
public class RedisConfig {
   @Bean
   public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
//创建一个redis
     RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

//添加序列化机制key,value,hashkey
     redisTemplate.setKeySerializer(new StringRedisSerializer());
     redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
     redisTemplate.setHashKeySerializer(new StringRedisSerializer());
     redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

//添加到工厂
     redisTemplate.setConnectionFactory(redisConnectionFactory);

     return redisTemplate;

   }
}

重新在测试类中运行

获取数据

4.通过该方式操作列表list

添加元素

弹出数据

5.针对hash操作

添加元素

获取元素

public Object hget(String key,String field){
    return redisTemplate.opsForHash().get(key,field);
   }

6.set操作:添加与获取

获取set集合的长度

7.zset操作:添加与获取

@Test
public void zsetTest(){
    //添加元素
    redisTemplate.opsForZset().add("z1","z1",67);
    redisTemplate.opsForZset().add("z1","z2",68); 
    redisTemplate.opsForZset().add("z1","z3",69);

    //获取元素
    redisTemplate.opsForZset().rangeByScore("z1",50,69);

    for(Object o : z1){
        System.out.println(o.toString());
    }
}

Redis构建web应用实践_网页缓存

创建SpringBoot项目

image-20211227152524811

1.修改版本

2.配置文件

########################################################
### 配置连接池数据库访问配置
########################################################
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.202.100:3306/zhonglian?characterEncoding=utf-8&&useSSL=false
spring.datasource.username=root
spring.datasource.password=5428

### Java Persistence Api --y
########################################################
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# Naming strategy
#[org.hibernate.cfg.ImprovedNamingStrategy  #org.hibernate.cfg.DefaultNamingStrategy]
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
# stripped before adding them to the entity manager)
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
########################################################
### 配置连接池数据库访问配置
########################################################
#Redis服务器连接地址
spring.redis.host=192.168.202.100
#Redis服务器连接端口
spring.redis.port=6379
#连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
#连接池中的最大空闲连接
spring.redis.pool.max-idle=8
#连接池中的最小空闲连接
spring.redis.pool.min-idle=0
#连接超时时间(毫秒)
spring.redis.timeout=30000
logging.pattern.console=%d{MM/dd HH:mm:ss.SSS} %clr(%-5level) ---  [%-15thread] %cyan(%-50logger{50}):%msg%n

3.打一个日志@SLf4j在文件中进行测试

查看项目是否启动成功

4.创建商品数据模型

@Data
@Entity
@Table(name = "goods")
public class GoodsEntity {


   //自增ID
   @Id
   @GeneratedValue(strategy=GenerationType.IDENTITY)//自增
   private Long id;
   // 商品名字
   private String goodsName;
   // 订单id
   private String orderId;
   // 商品数量
   private Integer goodsNum;
   // 商品价格
   private Double price;
  
}

5.商品业务层

@Repository
@Service
public class GoodsService {


  //商品
  @Autowired
  private GoodsRepository goodsRepository;


  /**
   * 根据id获取商品信息
   * @param 商品id
   * @return
   */
  public GoodsEntity getById(Long id){
    //从数据库中根据id查询商品信息
    Optional<GoodsEntity> optionGoodsEntity = goodsRepository.findById(id);
    if (optionGoodsEntity.isPresent()){
      return optionGoodsEntity.get();
     }else {
      return null;
     }
   }
}

6.编写控制层

/**
 * 商品控制层
 */
@RequestMapping("/goods")
@RestController
public class GoodsController {

  //商品业务层
  @Autowired
  private GoodsService goodsService;


  /**
   * 根据id查询商品信息
   * 10000并发 1414qps
   * @param id
   * @return
   */
  @GetMapping("/getById")
  public GoodsEntity getById(@PathVariable String id){
    return goodsService.getId(Long.valueOf(id));
   }


}

7.启动项目进行测试

8.数据库中成功出现创建的表后添加数据

9.打开浏览器进行测试(此时无缓存)

10.打开测压工具

添加线程组

添加http请求

添加聚合报告(查看没有缓存时的吞吐量)

11.业务层中添加缓存

查询缓存,判断缓存

添加依赖

@Repository
@Service
public class GoodsService {


   //商品
   @Autowired
   private GoodsRepository goodsRepository;
   @Autowired
   private StringRedisTemplate redisTemplate;


   /**
   * 根据id获取商品信息
   * @param id
   * @return
   */
   public GoodsEntity getById(Long id){
     // 从Redis中获取缓存
     String goodsString = stringRedisTemplate.opsForValue().get("goods:id:"+ id);
     // 判断是否有缓存
     if (StringUtils.isEmpty(goodsString)){
       //根据id查询商品信息
       Optional<GoodsEntity> optionalGoodsEntity = goodsRepository.getById(id);
        if(optionalGoodsEntity.isPresent()){
            GoodsEntity goosEntity = optionalGoodsEntity.get();
            //把对象转json字符串 {"id":1,"goodsName":"sdf"}
            String goodsEntityJson = JSON.toJSONString(goodsEntity);
            //添加缓存
            stringRedisTemplate.opsForValue().set("goods:"+id,goodsEntityJson);
        }
      
       return goodsEntity;
     }else {
      // 把json数据转为goods对象
       return JSON.parseObject(goodsString,GoodsEntity.class);
     }

     return null;
   }
}

12.在浏览器器中再次请求

再次查看缓存后的吞吐量

Redis配置文件

units单位

配置大小单位,开头定义基本度量单位,只支持bytes,大小写不敏感。

INCLUDES

Redis只有一个配置文件,如果多个人进行开发维护,那么就需要多个这样的配置文件,这时候多个配置文件就可以在此通过 include /path/to/local.conf 配置进来,而原本的 redis.conf 配置文件就作为一个总闸。

NETWORK(网卡)

参数:

  • bind:绑定redis服务器网卡IP,如果bind为空表示任何ip都可以访问,默认为127.0.0.1,即本地回环地址。这样的话,访问redis服务只能通过本机的客户端连接,而无法通过远程连接。如果bind选项为空的话,那会接受所有来自于可用网络接口的连接。
  • port:指定redis运行的端口,默认是6379。由于Redis是单线程模型,因此单机开多个Redis进程的时候会修改端口。
  • timeout:设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接。默认值为0,表示不关闭。
  • tcp-keepalive :单位是秒,表示将周期性的使用SO_KEEPALIVE检测客户端是否还处于健康状态,避免服务器一直阻塞,官方给出的建议值是300s,如果设置为0,则不会周期性的检测。

GENERAL

具体配置详解:

  • daemonize:设置为yes表示指定Redis以守护进程的方式启动(后台启动)。默认值为 no
  • pidfile:配置PID文件路径,当redis作为守护进程运行的时候,它会把 pid 默认写到 /var/redis/run/redis_6379.pid 文件里面
  • loglevel :定义日志级别。默认值为notice,有如下4种取值:

                debug(记录大量日志信息,适用于开发、测试阶段)

                verbose(较多日志信息)

                notice(适量日志信息,使用于生产环境)

                warning(仅有部分重要、关键信息才会被记录)

  • logfile :配置log文件地址,默认打印在命令行终端的窗口上
  • databases:设置数据库的数目。默认的数据库是DB 0 ,可以在每个连接上使用select 命令选择一个不同的数据库,dbid是一个介于0到databases - 1 之间的数值。默认值是 16,也就是说默认Redis有16个数据库。

SNAPSHOTTING

这里的配置主要用来做持久化操作。

参数:

save:这里是用来配置触发 Redis的持久化条件,也就是什么时候将内存中的数据保存到硬盘

save 900 1:表示900 秒内如果至少有 1 个 key 的值变化,则保存 save 300 10:表示300 秒内如果至少有 10 个 key 的值变化,则保存 save 60 10000:表示60 秒内如果至少有 10000 个 key 的值变化,则保存

REPLICATION

参数:

  • slave-serve-stale-data:默认值为yes。当一个 slave 与 master 失去联系,或者复制正在进行的时候,

slave 可能会有两种表现:

  1. 如果为 yes ,slave 仍然会应答客户端请求,但返回的数据可能是过时,或者数据可能是空的在第一次同步的时候

    1. 如果为 no ,在你执行除了 info he salveof 之外的其他命令时,slave 都将返回一个 "SYNC with master in progress" 的错误
  • slave-read-only:配置Redis的Slave实例是否接受写操作,即Slave是否为只读Redis。默认值为yes。
  • repl-diskless-sync:主从数据复制是否使用无硬盘复制功能。默认值为no。
  • repl-diskless-sync-delay:当启用无硬盘备份,服务器等待一段时间后才会通过套接字向从站传送RDB文件,这个等待时间是可配置的。
  • repl-disable-tcp-nodelay:同步之后是否禁用从站上的TCP_NODELAY 如果你选择yes,redis会使用较少量的TCP包和带宽向从站发送数据。

SECURITY

img

requirepass:设置redis连接密码。

比如: requirepass 123 表示redis的连接密码为123。

image-20210705174530462

CLIENTS

img

参数:

maxclients :设置客户端最大并发连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件。 描述符数-32(redis server自身会使用一些),如果设置 maxclients为0 。表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息

MEMORY MANAGEMENT

img

参数:

  • maxmemory:设置Redis的最大内存,如果设置为0 。表示不作限制。通常是配合下面介绍的maxmemory-policy参数一起使用。
  • maxmemory-policy :当内存使用达到maxmemory设置的最大值时,redis使用的内存清除策略。有以下几种可以选择:

    1)volatile-lru 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used )

    2)allkeys-lru 利用LRU算法移除任何key

    3)volatile-random 移除设置过过期时间的随机key

    4)allkeys-random 移除随机ke

    5)volatile-ttl 移除即将过期的key(minor TTL)

    6)noeviction noeviction 不移除任何key,只是返回一个写错误 ,默认选项

  • maxmemory-samples :LRU 和 minimal TTL 算法都不是精准的算法,但是相对精确的算法(为了节省内存)。随意你可以选择样本大小进行检,redis默认选择3个样本进行检测,你可以通过maxmemory-samples进行设置样本数。

APPEND ONLY MODE

img

参数:

  • appendonly:默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。但是redis如果中途宕机,会导致可能有几分钟的数据丢失,根据save来策略进行持久化,Append Only File是另一种持久化方式, 可以提供更好的持久化特性。Redis会把每次写入的数据在接收后都写入appendonly.aof文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认值为no。
  • appendfilename :aof文件名,默认是"appendonly.aof"
  • appendfsync:aof持久化策略的配置;no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快;always表示每次写入都执行fsync,以保证数据同步到磁盘;everysec表示每秒执行一次fsync,可能会导致丢失这1s数据

LUA SCRIPTING

img

参数:

lua-time-limit:一个lua脚本执行的最大时间,单位为ms。默认值为5000.

REDIS CLUSTER

img

参数:

  • cluster-enabled:集群开关,默认是不开启集群模式。
  • cluster-config-file:集群配置文件的名称。
  • cluster-node-timeout :可以配置值为15000。节点互连超时的阀值,集群节点超时毫秒数
  • cluster-slave-validity-factor :可以配置值为10。

redis其他功能-发布订阅

发送者发送消息,订阅者订阅消息。

Redis的发布与订阅

img

1.进入redis服务中创建一个订阅

2.第二个终端中再次订阅(当做客户端即消息的发送者)

3.第三个终端(相当于发布者)

4.打开第一个和第二个终端收到第三个终端发布的hello消息

Redis其他功能_慢查询

Redis命令执行的整个过程

image-20211214162827153

两点说明:

  1. 慢查询发生在第3阶段
  2. 客户端超时不一定慢查询,但慢查询是客户端超时的一个可能因素
  3. 慢查询日志是存放在Redis内存列表中。

获取慢查询日志

参数:

  1. 唯一标识ID
  2. 命令执行的时间戳
  3. 命令执行时长
  4. 执行的命名和参数

获取慢查询日志的长度

可以使用slowlog len命令获取慢查询日志的长度。

注意:

当前Redis中有121条慢查询日志。

配置慢查询的参数

  • 命令执行时长的指定阈值 slowlog-log-slower-than。

slowlog-log-slower-than的作用是指定命令执行时长的阈值,执行命令的时长超过这个阈值时就会被记录下来。

  • 存放慢查询日志的条数 slowlog-max-len。

slowlog-max-len的作用是指定慢查询日志最多存储的条数。实际上,Redis使用了一个列表存放慢查询日志,slowlog-max-len就是这个列表的最大长度。

查看慢日志配置

查看redis慢日志配置,登陆redis服务器,使用redis-cli客户端连接redis server

修改Redis配置文件

比如,把slowlog-log-slower-than设置为1000,slowlog-max-len设置为1200:

重启

使用config set命令动态修改

比如,还是把slowlog-log-slower-than设置为1000,slowlog-max-len设置为1200:

实践建议

slowlog-max-len配置建议
  • 线上建议调大慢查询列表,记录慢查询时Redis会对长命令做截断操作,并不会占用大量内存。
  • 增大慢查询列表可以减缓慢查询被剔除的可能,例如线上可设置为1000以上。
slowlog-log-slower-than配置建议
  • 默认值超过10毫秒判定为慢查询,需要根据Redis并发量调整该值
  • 由于Redis采用单线程响应命令,对于高流量的场景,如果命令执行时间在1毫秒以上,那么Redis最多可支撑OPS不到1000。因此对于高OPS场景的Redis建议设置为1毫秒

慢查询主要作用:定位系统中存在的慢操作

Redis其他功能_流水线pipeline

1次网络命令通信模型

经历了1次时间 = 1次网络时间 + 1次命令时间。

批量网络命令通信模型

经历了 n次时间 = n次网络时间 + n次命令时间

流水线

经历了 1次pipeline(n条命令) = 1次网络时间 + n次命令时间,这大大减少了网络时间的开销,这就是流水线。

注意:

在执行批量操作而没有使用pipeline功能,会将大量的时间耗费在每一次网络传输的过程上;而使用pipeline后,只需要经过一次网络传输,然后批量在redis端进行命令操作。这会大大提高了效率。

pipeline-Jedis实现

没有pipeline的测试

有pipeline的测试

查看测试结果的用时时间

pipeline主要作用:减少了网络时间的开销

Redis数据安全_持久化机制概述

内存的数据持久化的磁盘上,reids重启后可以从磁盘中恢复数据

持久化机制概述

对于Redis而言,持久化机制是指把内存中的数据存为硬盘文件, 这样当Redis重启或服务器故障时能根据持久化后的硬盘文件恢复数 据。

image-20211221145624459

Redis数据安全_RDB持久化机制

rdb实在一定时间内将内存数据以快照写入磁盘。(此时文件为经过压缩的二进制文件)

Redis数据安全_AOF持久化机制实战

rdb可能丢失数据

AOF是什么

以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来。

image-20211221155715791

AOF默认不开启

可以在redis.conf中配置文件名称,默认为appendonly.aof。

重启服务

 可以查看到appendonly.aof文件(以写命令的方式创建)

aof可以恢复数据

进入appendonly.aof文件删除flushall:

再次运行时redis会重新执行一次aof文件恢复数据

AOF同步频率设置

image-20210713152129373

参数:

  1. appendfsync always

始终同步,每次Redis的写入都会立刻记入日志,性能较差但数据完整性比较好。

  1. appendfsync everysec

每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。

  1. appendfsync no

redis不主动进行同步,把同步时机交给操作系统。

优势

  • 备份机制更稳健,丢失数据概率更低。
  • 可读的日志文本,通过操作AOF稳健,可以处理误操作。

劣势

  • 比起RDB占用更多的磁盘空间。
  • 恢复备份速度要慢。
  • 每次读写都同步的话,有一定的性能压力。

reids中aof持久化主要解决数据丢失问题

Redis数据安全_如何选用持久化方式

利用文件修复数据

综合使用AOF和RDB两种持久化机制

用AOF来保证数据不丢失,作为数据恢复的第一选择,用RDB来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,还可以使用RDB来进行快速的数据恢复。

image-20211221170529631

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值