Redis基础学习——由浅而深

[前言]关系数据库与非关系型数据库

关系型数据库

  • 一个结构化的数据库,创建在关系模型基础上
  • 一般面向于记录
  • 包括:Oracle、MySQL、SQL Server、Microsoft Access、DB2等非关系型数据库

非关系型数据库

  • 除了主流的关系型数据库外的数据库,都认为是非关系型·
  • 包括:Redis、MongBD、Hbase、CouhDB等

非关系型数据库产生背景

  • High performance———对数据库高并发读写需求
  • Huge Storage———对海量数据高效存储与访问需求
  • High Scalability && High Availability———对数据库高可扩展性与高可用性需求

一、Redis概述

  • REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
  • Redis是一个开源的使用ANSI C语言编写、遵守BSD协议。
  • 支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
  • 它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

Rdis简介

Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。

Redis 与其他 key - value 缓存产品有以下三个特点:

  • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。
  • Redis基于内存运行并支持持久化采用key-value(键值对)的存储形式

Redis配置文件

配置参数(/etclredis/6379.conf为主配置文件)

参数描述
bind监听的主机地址
port端口
daemonize yes启用守护进程
pidfile指定PID文件
loglevel notice日志级别notice是通告级别,日志有8个警告级别
logfile指定日志文件

Redis 优势

  • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  • 原子 性– Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
  • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

Redis多数据库概念

  • Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机(单实例)才有,如果是集群就没有数据库的概念。
  • Redis是一个字典结构的存储服务器,而实际上一个Redis实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中。这与我们熟知的在一个关系数据库实例中可以创建多个数据库类似,所以可以将其中的每个字典都理解成一个独立的数据库。
  • 每个数据库对外都是一个从O开始的递增数字命名,Redis默认支持16个数据库(可以通过配置文件支持更多,无上限),可以通过配置databases来修改这一数字。
  • 客户端与Redis建立连接后会自动选择0号数据库,不过可以随时使用SELECT命令更换数据库,如要选择1号数据库:select 1

注意:
♦ Redis不支持自定义数据库的名字,每个数据库都以编号命名,开发者必须自己记录哪些数据库存储了哪些数据。另外Redis也不支持为每个数据库设置不同的访问密码,所以一个客户端要么可以访问全部数据库,要么连一个数据库也没有权限访问。最重要的一点是多个数据库之间并不是完全隔离的,比如FLUSHALL命令可以清空一个Redis实例中所有数据库中的数据。
◆ 综上所述,这些数据库更像是一种命名空间,而不适宜存储不同应用程序的数据。

多数据库的作用场景:

  • 可以使用0号数据库存储某个应用生产环境中的数据,使用1号数据库存储测试环境中的数据,但不适宜使用0号数据库存储A应用的数据而使用1号数据库B应用的数据,不同的应用应该使用不同的Redis实例存储数据。
  • 由于Redis非常轻量级,一个空Redis实例占用的内存只有1M左右,所以不用担心多个Redis实例会额外占用很多内存。

二、安装redis

1.下载redis源码包

[root@localhost ~]# wget https://download.redis.io/releases/redis-5.0.10.tar.gz  ##下载软件包
[root@localhost ~]# ls  ##查看源码包
redis-5.0.10.tar.gz 

2.编译安装redis

[root@localhost ~]# yum -y install gcc-c++ gcc make   ##安装编译环境
[root@localhost ~]# tar zxvf redis-5.0.10.tar.gz -C /opt
[root@localhost ~]# cd /opt/redis-5.0.10/
[root@localhost redis-5.0.10]# ls   ##查看没有configure脚本,redis不需要./configure,已经对其进行封装化了
00-RELEASENOTES  COPYING  Makefile   redis.conf       runtest-moduleapi  src
BUGS             deps     MANIFESTO  runtest          runtest-sentinel   tests
CONTRIBUTING     INSTALL  README.md  runtest-cluster  sentinel.conf      utils
[root@localhost redis-5.0.10]# make
[root@localhost redis-5.0.10]# make PREFIX=/usr/local/redis install  ##安装是需要指定安装路径

3.执行配置文件脚本install_server.sh,自动生成相关配置文件

[root@localhost redis-5.0.10]# cd /usr/local/redis/
[root@localhost redis]# ls
bin
[root@localhost redis]#  cd bin/
[root@localhost bin]# ls   ##在bin目录下有一些连接终端
redis-benchmark  redis-check-aof  redis-check-rdb  redis-cli  redis-sentinel  redis-server
[root@localhost bin]# cd /opt/redis-5.0.10/  ##源码目录下有个utils工具目录
[root@localhost redis-5.0.10]# cd utils/
[root@localhost utils]# ls   ##utils目录下install_server.sh给redis配置各种配置文件的脚本
build-static-symbols.tcl  generate-command-help.rb  install_server.sh  
 ……省略部分
[root@localhost utils]# ./install_server.sh   ##执行脚本
……省略部分
Please select the redis port for this instance: [6379]   ##直接回车,默认端口6379
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf]   ##配置文件存放位置
Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log]    ##日志文件存放位置
Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379]  ##实例的数据文件位置
Selected default - /var/lib/redis/6379
Please select the redis executable path []  /usr/local/redis/bin/redis-server  ##扩展路径,需要自己手动设置
Is this ok? Then press ENTER to go on or Ctrl-C to abort.   ##这里直接回车确认
……省略部分
[root@localhost utils]# cd /etc/redis   
[root@localhost redis]# ls    ##执行完成后可以查看到配置文件了
6379.conf
[root@localhost redis]# netstat -anupt |grep redis   ##执行完脚本,redis自动开启
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      6412/redis-server 1 

4.优化命令调用

[root@localhost redis]# ln -s /usr/local/redis/bin/* /usr/local/bin/

5.测试关闭/启动脚本(/etc/init.d/redis_6379),安装是自动生成的脚本

[root@localhost ~]# /etc/init.d/redis_6379 stop     ##关闭redis
Stopping ...
Redis stopped
[root@localhost ~]# netstat -anupt |grep redis   ##端口关闭了
[root@localhost ~]# 
[root@localhost ~]# /etc/init.d/redis_6379 start##开启redis
Starting Redis server...
[root@localhost ~]# netstat -anupt |grep redis   ##启动成功
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      6691/redis-server 1 

6.设置service系统服务管理

[root@localhost init.d]# cp -p /etc/init.d/redis_6379 /etc/init.d/redis_6379bak
[root@localhost init.d]# mv /etc/init.d/redis_6379 /etc/init.d/redis
[root@localhost init.d]# vi redis
#Configurations injected by install_server below....
#chkconfig: 2345 90 25   ##插入这条声明
……省略部分
[root@localhost init.d]# chkconfig --add redis
[root@localhost init.d]# chkconfig --list redis
Note: This output shows SysV services only and does not include native
……省略部分
redis          	0:off	1:off	2:on	3:on	4:on	5:on	6:off
[root@localhost ~]# service redis stop   ##关闭redis
Stopping ...
Redis stopped
[root@localhost ~]# netstat -anupt |grep redis
[root@localhost ~]# service redis start   ## 开启redis
Starting Redis server...
[root@localhost ~]# netstat -anupt |grep redis   ##成功开启
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      42014/redis-server  

7.本地进入redis服务器

[root@localhost ~]# redis-cli -p 6379   ##本地进入不需要指定主机,可以直接登入
127.0.0.1:6379> 

8.远程进入redis服务器,需要修改监听地址

[root@localhost ~]# redis-cli -h 192.168.10.10 -p 6379   ##这时候指定主机还无法进入redis客户端,需要修改配置,指定监听地址,redis-cli是客户端登入命令
Could not connect to Redis at 192.168.10.10:6379: Connection refused
not connected> 
[root@localhost ~]# vim /etc/redis/6379.conf   ##修改配置文件
'70行//'  bind 127.0.0.1 192.168.10.10    ##在后面追加监听地址192.168.10.10
[root@localhost ~]# service redis restart    ##重启服务
[root@localhost ~]#  redis-cli -h 192.168.10.10 -p 6379   ##修改完配置后可以直接进入了
192.168.10.10:6379> 

三、了解redis的数据结构类型

Redis支持五种数据类型:

  1. String: 字符串
  2. Hash: 散列
  3. List: 列表
  4. Set: 集合
  5. Sorted Set: 有序集合

1.String(字符串)

  • string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
  • string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
  • string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
[root@localhost ~]# redis-cli --raw   ##加上--raw选项可以识别中文
127.0.0.1:6379> set A 你好
OK
127.0.0.1:6379> get A
你好
127.0.0.1:6379> type A
string

在以上实例中我们使用了 Redis 的 SET 和 GET 命令
注意:一个键最大能存储 512MB。

2.Hash(哈希)

  • Redis hash 是一个键值(key=>value)对集合。
  • Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

哈希类型的数据引用了类和对象的概念,哈希类型数据中的键相当于一个对象,一个对象可以拥有多个属性,一个哈希类型的键值对(K-V)可以抽象的看做关系型数据库中的库

127.0.0.1:6379> hmset test word1 "hello" word2 "world"   ##设置键(对象)test,属性1的值为“hello”,属性2的值为“world”
OK
127.0.0.1:6379> HMGET test word1
hello
127.0.0.1:6379> HMGET test word2
world
127.0.0.1:6379> HMGET test word1 word2
hello
world
127.0.0.1:6379> del test
1

127.0.0.1:6379> HMSET name id1 "张三"     ##设置哈希键name,给字段id1赋值“张三”
OK
127.0.0.1:6379> HMSET name id2 "李四"
OK
127.0.0.1:6379> HMGET name id1    ##获取哈希键name中字段id1的值
张三
127.0.0.1:6379> HMGET name id2
李四
127.0.0.1:6379> HMGET name id1 id2
张三
李四
127.0.0.1:6379> del name  ##删除哈希数据类型键值,同样用del
1

实例中我们使用了 Redis HMSET, HMGET 命令,HMSET 设置了两个 field=>value 对, HGET 获取对应 field 对应的 value。
每个 hash 可以存储 232 -1 键值对(40多亿)。

3.List(列表)

  • Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
  • List数据类型的数值是可以重复的
  • 列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。
    在这里插入图片描述
127.0.0.1:6379> lpush name "张三"     ##给列表name中添加值
1
127.0.0.1:6379> lpush name "李四"
2
127.0.0.1:6379> lpush name "王五"
3
127.0.0.1:6379> lpush name "赵柳"
4
127.0.0.1:6379> lpush name "孙七"
5
127.0.0.1:6379> LRANGE name 0 1    ##查看name列表0-1的值
孙七
赵柳
127.0.0.1:6379> LRANGE name 2 3
王五
李四
127.0.0.1:6379> LRANGE name 4 4
张三
127.0.0.1:6379> LRANGE name 3 3
李四
127.0.0.1:6379> del name
1

List类型数据以类似索引的方式存储,最后加入的值得索引为0,最早插入值得索引号为列表值得总数减1

4.Set(无序集合)

  • Redis 的 Set 是 string 类型的无序集合。
  • 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
  • 集合类型的数据具有唯一性,不能重复

sadd 命令作用:

  • 添加一个 string 元素到 key 对应的 set 集合中,成功返回 1,如果元素已经在集合中返回 0。
  • 格式:sadd key member
127.0.0.1:6379> sadd name "章子怡"    ##给name集合添加元素
1
127.0.0.1:6379> sadd name "路易斯"
1
127.0.0.1:6379> sadd name "王麻子"
1
127.0.0.1:6379> sadd name "章子怡"
0
127.0.0.1:6379> sadd name "王麻子"
0
127.0.0.1:6379> SMEMBERS name   ##查看集合内所有元素
王麻子
路易斯
章子怡
127.0.0.1:6379> del name
1

注意:以上实例中 "章子怡"添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。
集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个成员)。

5.zset(sorted set:有序集合)

  • Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
  • 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的降序排序。
  • zset的成员是唯一的,但分数(score)却可以重复。
  • 可以根据score值精确查找,比无序集合更加人性化

zadd 命令的作用

  • 添加元素到集合,元素在集合中存在则更新对应score
  • 格式:zadd key score member
###### 
192.168.10.10:6379> zadd colour 0 red 0 yellow 1 black 2 white   ## 设置有序集合colour,插入4个元素
(integer) 4
192.168.10.10:6379> zrangebyscore colour 0 10   ## 有序集合类型中的元素以score值的大小进行排序,
1) "red"
2) "yellow"
3) "black"
4) "white"
192.168.10.10:6379> zrangebyscore colour 0 0    ## 可以根据score值精确查找数据
1) "red"
2) "yellow"
192.168.10.10:6379> ZRANGEBYSCORE colour 2 2
1) "white"
192.168.10.10:6379> zadd colour 1.5 green   ##插入一个score为1.5的值
(integer) 1
192.168.10.10:6379> zrangebyscore colour 0 10    ## 新插入的值按score排列
1) "red"
2) "yellow"
3) "black"
4) "green"
5) "white"




127.0.0.1:6379> ZADD score 60 "小明"
1
127.0.0.1:6379> ZADD score 76 "小王"
1
127.0.0.1:6379> ZADD score 85 "小志"
1
127.0.0.1:6379> ZADD score 96 "小李"
1
127.0.0.1:6379> ZRANGEBYSCORE score 0 100
小明
小王
小志
小李

各个数据类型应用场景:

类型简介特性场景
String(字符串)二进制安全可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M
Hash(字典)键值对集合,即编程语言中的Map类型适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去)存储、读取、修改用户属性
List(列表)链表(双向链表)增删快,提供了操作某一段元素的API1. 最新消息排行等功能(比如朋友圈的时间线)
2. 消息队列
Set(集合)哈希表实现,元素不重复1、添加、删除,查找的复杂度都是O(1)
2、为集合提供了求交集、并集、差集等操作
1、共同好友
2、利用唯一性,统计访问网站的所有独立ip
3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐
ZSet(有序集合)将Set中的元素增加一个权重参数score,元素按score有序排列数据插入集合时,已经进行天然排序1、排行榜
2、带权重的消息队列

四、了解Redis 事务

  1. Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:
    ◆ 批量操作在发送 EXEC 命令前被放入队列缓存。
    ◆ 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
    ◆ 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

  2. 一个事务从开始到执行会经历以下三个阶段:
    ◆ 开始事务。
    ◆ 命令入队。
    ◆ 执行事务。

  3. Redis 事务命令

相关命令用途描述
MULTI标记一个事务块的开始。
EXEC执行所有事务块内的命令。
DISCARD取消事务,放弃执行事务块内的所有命令。

事务示范

[root@promote ~]# redis-cli -h 192.168.10.10 -p 6379
192.168.10.10:6379> MULTI   ##开始事务
OK
192.168.10.10:6379> set A 123
QUEUED
192.168.10.10:6379> set B 456
QUEUED
192.168.10.10:6379> set C 789
QUEUED
192.168.10.10:6379> DISCARD  ##中断事务
OK
192.168.10.10:6379> keys *   ##A、C、B三个键并没有被设置,事务具有原子性
1) "key:__rand_int__"
2) "counter:__rand_int__"
3) "handsome-boy"
4) "*"
5) "myset:__rand_int__"
6) "mylist"
192.168.10.10:6379> MULTI  ##开始事务
OK
192.168.10.10:6379> set A 123
QUEUED
192.168.10.10:6379> set B 456
QUEUED
192.168.10.10:6379> set C 789
QUEUED
192.168.10.10:6379> EXEC   ##提交事务
1) OK
2) OK
3) OK
192.168.10.10:6379> keys *   ##查看,事务执行成功,产生了A、B、C三个键
1) "counter:__rand_int__"
2) "key:__rand_int__"
3) "B"
4) "handsome-boy"
5) "myset:__rand_int__"
6) "*"
7) "C"
8) "mylist"
9) "A"

五、演示redis的基础命令用法

[root@localhost ~]#  redis-cli -h 192.168.10.10 -p 6379  
192.168.10.10:6379> 
192.168.10.10:6379> help    ##列出帮助信息
redis-cli 5.0.10
To get help about Redis commands type:
      "help @<group>" to get a list of commands in <group>
      "help <command>" for help on <command>
……省略部分
192.168.10.10:6379> help @list      ##列出主列表信息
  BLPOP key [key ...] timeout
  summary: Remove and get the first element in a list, or block until one is available
  since: 2.0.0
……省略部分
192.168.10.10:6379> help set      ##查看set的帮助信息,set的用法
  SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
  summary: Set the string value of a key
  since: 1.0.0
  group: string
192.168.10.10:6379> set teacher ltp   ##设置键值对,键是teacher、值是ltp
OK
192.168.10.10:6379> set handsome-boy ltp
OK
192.168.10.10:6379> keys *   ##可以查看所有键的信息
1) "handsome-boy"
2) "teacher"
192.168.10.10:6379> set tea good
OK
192.168.10.10:6379> keys t??     ##这里的?可以充当一个任意字符
1) "tea"
192.168.10.10:6379> get handsome-boy   ##可以使用get来获取key(键)的值
"ltp"
192.168.10.10:6379> EXISTS handsome-boy    ##可以查看某个可以是否存在,用exists命令,支持Tab键补全
(integer) 1    
192.168.10.10:6379> exist aaa    ##查看是否存在key,返回101代表存在、0代表不存在
(integer) 0
192.168.10.10:6379> keys *    ##查看所有的key
1) "handsome-boy"
2) "teacher"
3) "tea"
192.168.10.10:6379> del tea   ##使用del删除key
(integer) 1
192.168.10.10:6379> keys *   ##再次查看,tea这个键已经被删除了
1) "handsome-boy"
2) "teacher"
192.168.10.10:6379> type teacher    使用type命令来查看键对应值的类型
string
192.168.10.10:6379> rename teacher tea    ##rename可以对key进行更名
OK
192.168.10.10:6379> keys *   ##更名成功
1) "handsome-boy"
2) "tea"
192.168.10.10:6379> get tea   ##更名不影响它的值
"ltp"

192.168.10.10:6379> select 1   ## 选择库2
OK
192.168.10.10:6379[1]> keys *   ## 库之间互相隔离
(empty list or set)
192.168.10.10:6379> exit   ##退出

六、可以利用redis-benchmark测试工具进行压测

常用选项:
-h:指定监听主机地址
-p:指定端口
-c:指定并发请求,如并发100个
-n:指定一共发多少个请求
-p:强制退出redis
-d:发送的字节数

[root@localhost ~]# redis-benchmark -h 192.168.10.10 -p 6379 -c 100 -n 100000  
                                 ##利用redis-benchmark 命令进行压力测试
……省略部分
====== SET ======   ##set设置命令的能力测试
  100000 requests completed in 0.57 seconds
  100 parallel clients
  3 bytes payload
  keep alive: 1

====== GET ======   ##get获取值得能力测试
  100000 requests completed in 0.56 seconds    ##十万个包花了0.56秒,真实环境更低
  100 parallel clients
  3 bytes payload
  keep alive: 1
……省略部分
[root@localhost ~]# redis-benchmark -h 192.168.10.10 -p 6379 -q -d 100
……省略部分
SET: 175438.59 requests per second   ##可以测试set和get测试值
GET: 186567.16 requests per second
……省略部分

七、Redis数据库key管理

192.168.10.10:6379[1]> select 0
OK
192.168.10.10:6379> keys *
1) "colour"
192.168.10.10:6379> rename colour col   ## 修改键名
OK
192.168.10.10:6379> keys *
1) "col"
########################## PEXPIRE 设置超时时间########################

192.168.10.10:6379> PEXPIRE col 3000   ## 设置key的超时时间,以毫秒为单位
(integer) 1
192.168.10.10:6379> keys *  ## 立即查看,clo还在
1) "col"
192.168.10.10:6379> keys *   ## 3秒后再次查看,clo超时,自动消失
(empty list or set)
######################### PTTL 查看key的剩余超时时间####################

192.168.10.10:6379> set name zhangshan
OK
192.168.10.10:6379> keys *   ## 再建一个key用于测试
1) "name"
192.168.10.10:6379> PEXPIRE name 500000
(integer) 1
192.168.10.10:6379> PTTL name
(integer) 493981
192.168.10.10:6379> PTTL name
(integer) 492326
192.168.10.10:6379> PTTL name
(integer) 488399
192.168.10.10:6379> PTTL name
(integer) 480297
############################ PERSIST 取消超时时间,-1为永不超时################

192.168.10.10:6379> PERSIST name
(integer) 1
192.168.10.10:6379> PTTL name    
(integer) -1
########################### mset 多键创建,mget 多键查询#######################
192.168.10.10:6379> mset colour read score 80 sex boy
OK
192.168.10.10:6379> keys *
1) "sex"
2) "colour"
3) "score"
192.168.10.10:6379> mget colour score sex
1) "read"
2) "80"
3) "boy"




  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值