NoSQL 之 Redis 配置与优化

文章目录

一、关系数据库与非关系数据库

1.1 关系型数据库

  • 关系型数据库是一个结构化的数据库,创建在关系模型(二维表格模型)基础上,一般面向于记录。
  • SQL 语句(标准数据查询语言)就是一种基于关系型数据库的语言,用于执行对关系型数据库中数据的检索和操作。
  • 主流的关系型数据库包括 Oracle、MySQL、SQL Server、Microsoft Access、DB2、PostgreSQL 等。

以上数据库在使用的时候必须先建库建表设计表结构,然后存储数据的时候按表结构去存,若数据与表结构不匹配就会存储失败。

1.2 非关系型数据库

  • NoSQL (NoSQL = Not Only SQL),意思是“不仅仅是 SQL ”,是非关系型数据库的总称。
  • 除了主流的关系型数据库外的数据库,都认为是非关系型。
  • 不需要预先建库建表定义数据集存储表结构,每条记录可以有不同的数据类型和字段个数(如QQ、微信等聊天APP中聊天的文字、图片、视频、音乐等)。
  • 主流的 NoSQL 数据库有 Redis、MongBD、Hbase、Memcached 等。

二、关系型数据库和非关系型数据库区别

2.1 数据存储方式不同

关系型和非关系型数据库的主要差异是数据存储的方式。关系型数据天然就是表格式的,因此存储在数据表的行和列中。数据表可以彼此关联协作存储,也很容易提取数据。
与其相反,非关系型数据不适合存储在数据表的行和列中,而是大块组合在一起。非关系型数据通常存储在数据集中,就像文档、键值对或者图结构。你的数据及其特性是选择数据存储和提取方式的首要影响因素。

数据库说明
关系型依赖于关系模型 E-R 图,同时以表格形式的方式存储数据
非关系型除了以表格形式存储之外,通常会以大块的形式组合在一起进行存储数据

2.2 扩展方式不同

SQL 和 NoSQL 数据库最大的差别 :可能是在扩展方式上,要支持日益增长的需求当然要扩展。
要支持更多并发量,SQL 数据库是纵向扩展,也就是说提高处理能力,使用速度更快速的计算机,这样处理相同的数据集就更快了。因为数据存储在关系表中,操作的性能瓶颈可能涉及很多个表,这都需要通过提高计算机性能来克服。虽然 SQL 数据库有很大扩展空间,但最终肯定会达到纵向扩展的上限。
而 NoSQL 数据库是横向扩展的。因为非关系型数据存储天然就是分布式的,NoSQL 数据库的扩展可以通过给资源池添加更多普通的数据库服务器 (节点) 来分担负载。

  1. 关系型数据库:纵向(天然表格式)
  2. 非关系型数据库:横向(天然分布式)

2.2.1 负载增加时,有两个解决方法

一个是购买更加强大的服务器来应对增加的负载,称为“纵向扩展”( scale up );二是添加更多的服务器,称为“横向扩展”( scale out )。横向扩展更常用,更具有成本效益。

横向扩展和复制的常用用途
  1. 读操作的负载均衡。

  2. 写操作的负载均衡。按信息角色分发,很少更新的表放在一个服务器,频繁更新的表分割到多个服务器上面;按地理区域分割,流量直接定向到最近的服务器。

  3. 热备份进行灾难避免。配置专门的 salve 作为热备份。

  4. 远程复制进行灾难避免。

  5. 制作备份。在完全不影响 master 的前提下执行备份。

  6. 生成报表。创建数据报表会降低服务器性能,影响较大,后台作业可以专门 salve 执行。

横向扩展只能扩展读操作,不能扩展写操作。分片( sharding) 的技术扩展写操作
  • 同步复制要求 master 必须等待所有 slave 的写操作完成。需要额外的同步机制来保证一致性,一般通过两阶段提交( two-phase commit )协议来实现。协议之所以慢,是因为需要 4 次消息传递,包括事务消息和准备请求的消息,master 的提交会被阻塞直到所有 slave 确认事务。异步复制只需要一条事务消息即可。
异步复制其实是牺牲一致性为代价换取性能。

有两个问题:

  1. master 出现故障,事务就会消失;
  2. slave 执行的查询可能返回旧数据。

简单拓扑和树形拓扑用于横向扩展,双主拓扑用于故障转移,环形拓扑和双主结构允许站点本地允许时还能将变更复制到其他站点。

级联复制,添加额外的 slave 作为中继 salve,通过管理一群 slave 来减轻 master 上的复制负载。普通 salve 需要将变更应用到数据库,但不写入二进制日志。relay 需要写入二进制日志,但不应用变更。realy 使用 blackhole 引擎,relay 会产生额外延迟。

过滤复制事件

1、master 上过滤事件,master 过滤器,控制哪些被写入二进制日志。无法使用 PITR 准确恢复数据库。 binlog-do-db、binlog-ignore-db ,多个数据库需要重复使用选项。

2、salve上过滤事件,slave 过滤器,控制哪些在 slave 上执行。所有变更通过网络传送,浪费带宽。可以过滤数据库,还可以过滤单个表以及使用通配符过滤一组表。replicate-do-db、replicate-ignore-db、replicate-do-table=dbname.tablename、replicate-ignore-table=dbname.tablename、replicate-wild-do-table、replicate-wild-ignore-table。

担心网络流量,可以在 master 保存完整二进制日志, relay 过滤,减少流量。

数据的一致性管理

mysql5.6 引入了全局事务标识符( GTID ),master 上提交的事务做个标记,等 slave 获取到这个事务时才在 slave 上执行查询。

级联部署一致性,,第一是利用全局事务标识符来提升 slave ,并反复轮询 slave 有没有处理这个事务;第二是利用函数 master-pos-wait 函数将 maeter 到 salve 路径上的 relay 都连接起来,保证所有变化都能传递到 salve。

2.2.2 对事务性的支持不同

若数据操作需要高事务性或者复杂数据查询需要控制执行计划,那么传统的 SQL 数据库从性能和稳定性方面考虑是最佳选择。SQL 数据库支持对事务( ACID )原子性细粒度控制,并且易于回滚事务。
虽然 NoSQL 数据库也可以使用事务操作,但稳定性方面没法和关系型数据库比较,所以它们真正闪亮的价值是在操作的扩展性和大数据量处理方面。

  1. 关系型:特别适合高事务性要求和需要控制执行计划的任务。
  2. 非关系型:此处会稍显弱势,其价值点在于高扩展性和大数据量处理方面

2.2.3 非关系型数据库产生背景

可用于应对Web2.0纯动态网站类型的三高问题。

  1. High performance————对数据库高并发读写需求
  2. HugeStorage ————对海量数据高效存储与访问需求
  3. High Scalability && High Availability————对数据库高可扩展性与高可用性需求
  • 关系型数据库和非关系型数据库都有各自的特点与应用场景,两者的紧密结合将会给Web2.0的数据库发展带来新的思路。

  • 让关系数据库关注在关系上,非关系型数据库关注在存储上。

  • 例,在读写分离的MySQL数据库环境中,可以把经常访问的数据存储在非关系型数据库中,提升访问速度。

    MySQL高热数据 ——> redis
    web ——> redis ——> MySQL
    CPU ——> 内存 / 缓存 ——> 磁盘
    

三、Redis 简介

Redis 是一个开源的、使用 C语言 编写的 NoSQL 数据库。(非关系型数据库)
Redis 基于内存运行并支持持久化(支持存储在磁盘),采用 key-value (键值对) 的存储形式,是目前分布式架构中不可或缺的一环。

3.1 Redis 服务器程序的单线程模型

Redis 服务器程序是单进程模型

Redis 服务在一台服务器上可以同时启动多个 Redis 进程,Redis 的实际处理速度则是完全依靠于主进程的执行效率。若在服务器上只运行一个 Redis 进程,当多个客户端同时访问时,服务器的处理能力是会有一定程度的下降;若在同一台服务器上开启多个 Redis 进程, Redis 在提高并发处理能力的同时会给服务器的 CPU 造成很大压力。即: 在实际生产环境当中,需要根据实际的需求来决定开启多少个 Redis 进程。

PS:建议可以先开 2 个进程

原因

  1. 备份
  2. 抗高并发的同时尽量不给 CPU 造成太大的压力
    若对高并发要求更高一些,可能会考虑在同一台服务器上开启多个进程。若CPU资源比较紧张,采用单进程即可。

单进程快速的原因

epoll 机制优势:

  1. epoll 没有最大并发连接的限制,上限是最大可以打开文件的数目,这个数字一般远大于 2048, 一般来说这个数目和系统内存关系很大 ,具体数目可以 cat /proc/sys/fs/file-max 察看。
  2. 效率提升, Epoll 最大的优点就在于它只管你“活跃”的连接 ,而跟连接总数无关,因此在实际的网络环境中, Epoll 的效率就会远远高于 select 和 poll 。
  3. 内存拷贝, Epoll 在这点上使用了“共享内存 ”,这个内存拷贝也省略了 I/O 多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪,能够通知程序进行相应的操作。

PS : 补充加深一点
使用 epoll(默认) + I/O 多路复用机制
首先,Redis 是跑在单进程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或输出都是阻塞的,所以 I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O 阻塞导致整个进程无法对其它客户提供服务,而 I/O 多路复用就是为了解决这个问题而出现的。

epoll 模型所实现的 I/O 多路复用可以定义

socket 1 —>
socket 2 —> I/O多路复用程序 --》文件事件分派器(从队列中获取,再分发给对应处理器)–》命令处理、请求、连接应答等处理器
socket 3 —>

多个 socket 会定义为一个 fd 文件描述符(每有一个新建、打开、修改等“事件”内核就会返回一个fd(可理解为索引)),在每个 fd 激活时,会进行内核中的回调函数

I/O 多路复用程序 会监听 socket 活跃的链接,然后调用该socket (而此 socket 文件句柄主要实现的是网络上的“ ip + port +协议所标识的网络中的‘进程’”)可以简单理解为虚拟接口(抽象层)
本质而言就是使用一个线程来追踪多个 socket( I/O流 )的状态,来管理多个 I/O 。

3.2 I/O 复用技术介绍

一个线程同时追踪、管理多个连接(原本默认情况下是一个线程对应一个连接)

回调: 预先定义具体的执行过程(定义一个方法) ,等待调用,在一个线程给执行时,可以根据“触发器”“钩子” 完成回调,回调的目的是提高处理性能 和 节省资源

3.3 Redis 具有的几个优点(Redis 特性(与其他 Nosql 的对比))

  1. 具有极高的数据读写速度:数据读取的速度最高可达到 110000 次/s,数据写入速度最高可达到 81000 次/s。
  2. 支持丰富的数据类型:支持 key-value、 Strings、Lists、 Hashes(散列值)、 Sets 及 Ordered Sets 等数据类型操作。
    ps:
    string 字符串(可以为整形、浮点和字符型,统称为元素)
    list 列表:(实现队列,元素不唯一,先入先出原则)
    set 集合:(各不相同的元素)
    hash hash 散列值:(hash的key必须是唯一的)
    set /ordered sets 集合/有序集合
  3. 支持数据的持久化:可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  4. 原子性:Redis 所有操作都是原子性的。
  5. 支持数据备份:即 master-salve 模式的数据备份。

丰富的特性 – Redis 还支持 publish(消息发布)/subscribe(订阅), 通知, 设置 key 有效期等等特性。

Redis作为基于内存运行的数据库,缓存是其最常应用的场景之一。除此之外,Redis常见应用场景:还包括获取最新 N个数据的操作、排行榜类应用、计数器应用、存储关系、实时分析系统、日志记录。

支持 key-value、 Strings、Lists、 Hashes(散列值)、 Sets 及Ordered Sets 等数据类型操作。

3.4 为什么 Redis 这么快?

  1. Redis 是一款纯内存结构,避免了磁盘 I/O 等耗时操作。

  2. Redis 命令处理的核心模块为单线程,减少了锁竞争,以及频繁创建线程和销毁线程的代价,减少了线程上下文切换的消耗。

  3. 采用了 I/O多路复用机制,大大提升了并发效率。

PS:在 Redis 6.0 中新增加的多线程也只是针对处理网络请求过程采用了多线性,而数据的读写命令,仍然是单线程处理的。

四、部署安装

4.1 Redis 安装部署

systemctl stop firewalld
systemctl enable firewalld
setenforce 0

yum install -y gcc gcc-c++ make

yum repolist

重新 yum 安装
yum install -y gcc*

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.2 把 redis-5.0.7.tar.gz 压缩包上传到 opt 目录下

tar zxvf redis-5.0.7.tar.gz -C /opt/

cd /opt/redis-5.0.7/

编译安装
make && make PREFIX=/usr/local/redis install

由于Redis源码包中直接提供了Makefile 文件,所以在解压完软件包后,不用先执行./configure 进行配置,可直接执行make与make install命令进行安装

在这里插入图片描述
在这里插入图片描述

4.3 执行软件包提供的 install_server.sh 脚本文件设置Redis服务所需要的相关配置文件

cd /opt/redis-5.0.7/utils 
./install_server.sh       
.......			———— 一直回车.
Please select the redis executable path [/usr/local/bin/redis-server] /usr/local/redis/bin/redis-server
需要手动修改为 /usr/local/redis/bin/redis-server    注意要一次性正确输入

Selected config:
Port               : 6379                               #默认侦听端口为6379
Config file        : /etc/redis/6379.conf               #配置文件路径
Log file           : /var/log/redis_6379.log            #日志文件路径
Data dir           : /var/lib/ redis/6379               #数据文件路径
Executable         : /usr/local/redis/bin/redis-server  #可执行文件路径
Cli Executable     : /usr/local/redis/bin/redis-cli     #客户端命令工具

在这里插入图片描述

4.4 把 Redis 的可执行程序文件放入路径环境变量的目录中以便于系统识别

ln -s /usr/local/redis/bin/* /usr/local/bin/

当install_server.sh 脚本运行完毕,Redis 服务就已经启动,默认侦听端口为6379
netstat -natp | grep redis

Redis服务控制
/etc/init.d/redis_6379 stop       #停止
/etc/init.d/redis_6379 start      #启动
/etc/init.d/redis_6379 restart    #重启
/etc/init.d/redis_6379 status     #状态

/etc/init.d/redis_6379 stop
/etc/init.d/redis_6379 start
/etc/init.d/redis_6379 restart
/etc/init.d/redis_6379 status

在这里插入图片描述

在这里插入图片描述

4.5 修改配置 /etc/redis/6379.conf 的参数

vim /etc/redis/6379.conf

bind 127.0.0.1 192.168.10.27			——70行,添加监听的主机地址
port 6379				——93行,Redis默认的监听端口
daemonize yes				——137行,启用守护进程
pidfile /var/run/redis_6379.pid			——159行,指定PID文件
loglevel notice				——167行,日志级别
logfile /var/log/redis_6379.log			——172行,指定日志文件

/etc/init.d/redis_6379 restart

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.6 Redis 命令工具

命令用途
redis-server用于启动 Redis 的工具
redis-benchmark用于检测 Redis 在本机的运行效率
redis-check-aof修复 AOF 持久化文件
redis-check-rdb修复 RDB 持久化文件
redis-cliRedis 命令行工具
rdb 和 aof是 redis 服务中持久化功能的两种形式 RDB AOF
redis-cli常用于登陆至 redis 数据库

在这里插入图片描述
在这里插入图片描述

4.7 redis-cli 命令行工具(远程登陆)

语法:
redis-cli -h host -p port -a password

-h : 指定远程主机
-p : 指定Redis 服务的端口号
-a : 指定密码,未设置数据库密码可以省略-a选项
若不添加任何选项表示,则使用127.0.0.1:6379 连接本机上的 Redis 数据库,

redis-cli -h 192.168.10.13 -p 6379

在这里插入图片描述

4.8 redis-benchmark 测试工具

  • redis-benchmark 是官方自带的 Redis 性能测试工具,可以有效的测试 Redis 服务的性能。

  • 基本的测试语法

    redis-benchmark [选项] [选项值]
    
指令用途
-h指定服务器主机名。
-p指定服务器端口。
-s指定服务器 socket(套接字)
-c指定并发连接数。
-n指定请求数。
-d以字节的形式指定 SET/GET 值的数据大小。
-k1=keep alive 0=reconnect
-rSET/GET/INCR 使用随机 key,SADD 使用随机值。
-P通过管道传输< numreq >请求。
-q强制退出 redis。 仅显示 query/sec 值。
–csv以 CSV 格式输出。
-l (小写的 L )生成循环,永久执行测试。
-t仅运行以逗号分隔的测试命令列表。
-I (大写的 i )Idle模式。仅打开 N 个 idle 连接并等待。
向IP地址为192.168.10.13、端口为6379 的Redis 服务器发送100个并发连接与100000 个请求测试性能
redis-benchmark -h 192.168.10.13 -p 6379 -c 100 -n 100000

测试存取大小为100字节的数据包的性能
redis-benchmark -h 192.168.10.13 -p 6379 -q -d 100

测试本机上Redis 服务在进行set与lpush操作时的性能
redis-benchmark -t set,lpush -n 100000 -q

测试本机上Redis 服务在进行set与lpush操作时的性能

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4.9 Redis数据库常用命令

4.9.1 set: 存放数据,命令格式为set key value

4.9.2 get: 获取数据,命令格式为get key

redis-cli -h 192.168.10.13 -p 6379

192.168.10.13:6379> set student Dart
OK
192.168.10.13:6379> get student
"Dart"

在这里插入图片描述

4.9.3 keys 命令可以取符合规则的键值列表,通常情况可以结合 * 、? 等选项来使用。

127.0.0.1:6379> set k1 1 
127.0.0.1:6379> set k2 2 
127.0.0.1:6379> set k3 3
127.0.0.1:6379> set v1 4
127.0.0.1:6379> set v50 3
127.0.0.1:6379> set v88 8

set k1 1
set k2 2
set k3 3
set v1 4
set v50 3
set v88 8


127.0.0.1:6379> KEYS *			—— *: 查看当前数据库中所有键
1) "v50"
2) "myset:__rand_int__"
3) "v1"
4) "counter:__rand_int__"
5) "v88"
6) "teacher"
7) "k2"
8) "mylist"
9) "k3"
10) "key:__rand_int__"
11) "k1"

127.0.0.1:6379> KEYS v*       ——查看当前数据库中以v开头的数据
1) "v50"
2) "v1"
3) "v22"

127.0.0.1:6379> KEYS v?       ——查看当前数据库中以v开头后面包含任意一位的数据
1) "v1"

127.0.0.1:6379> KEYS v??      ——查看当前数据库中以v开头v开头后面包含任意两位的数据
1) "v88"
2) "v50"

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.9.4 exists 命令可以判断键值是否存在

127.0.0.1:6379> exists teacher ——判断 stecher 键是否存在
(integer) 1 ——1表示 teacher 键是存在
127.0.0.1:6379> exists tea
(integer) 0 ——0表示 tea 键不存在

exists student
exists stu

在这里插入图片描述

4.9.5 del 命令可以删除当前数据库的指定 key

127.0.0.1:6379> keys *
127.0.0.1:6379> del v5
(integer) 0
127.0.0.1:6379> get v5
(nil)
127.0.0.1:6379> del v50
(integer) 1
127.0.0.1:6379> get v50
(nil)

在这里插入图片描述

4.9.6 type 命令可以获取 key 对应的 value 值类型

127.0.0.1:6379> type k1
string

在这里插入图片描述

4.9.7 rename 命令是对已有key进行重命名(覆盖)

命令格式:
rename 源key  目标key

使用rename命令进行重命名时,无论目标key是否存在都进行重命名,且源key的值会覆盖目标key的值。在实际使用过程中,建议先用 exists命令查看目标key是否存在,然后再决定是否执行rename命令,以避免覆盖重要数据。

127.0.0.1:6379> keys v*
1) "v1"
2) "v22"
127.0.0.1:6379> rename v22 v2
OK
127.0.0.1:6379> keys v*
1) "v1"
2) "v2"
127.0.0.1:6379> get v1
"4"
127.0.0.1:6379> get v2
"5"
127.0.0.1:6379> rename v1 v2
127.0.0.1:6379> get v1
(nil)
127.0.0.1:6379> get v2
"4"

在这里插入图片描述

4.9.8 renamenx

rename n 不进行修改 x进行修改

nx 组合: 先判断 命令的作用是对已有key进行重命名,并检测新名是否存在,如果目标key存在则不进行重命名。 (不覆盖)

命令格式
renamenx 源key  目标key

127.0.0.1 :6379> keys *
127.0.0.1:6379> get student
“Dart”
127.0.0.1:6379> get v2
“8”
127.0.0.1:6379> renamenx v2 student
(integer) 0
127.0.0.1:6379> keys *
127.0.0.1 :6379> get student
“Dart”
127.0.0.1:6379> get v2
“8”

在这里插入图片描述
在这里插入图片描述

4.9.9 dbsize命令的作用是查看当前数据库中key的数目

127.0.0.1:6379> dbsize
(integer) 9

在这里插入图片描述

4.9.10 使用config set requirepass your password 命令设置密码

127.0.0.1:6379> config set requirepass 123456

——使用 config get requirepass 命令查看密码(一旦设置密码,必须先验证通过密码,否则所有操作不可用)

127.0.0.1:6379> auth 123456			——认证密码

127.0.0.1:6379> config get requirepass

在这里插入图片描述

4.9.11 删除密码

127.0.0.1:6379> auth 123456
127.0.0.1:6379> config set requirepass ''
以上若不设置,就无法重启redis

在这里插入图片描述

4.10 Redis 多数据库常用命令(16个库 0~15 )

  • Redis 支持多数据库,Redis 默认情况下包含 16 个数据库,数据库名称是用数字 0-15 来依次命名的。 多数据库相互独立,互不干扰。

4.10.1 多数据库间切换

命令格式: select 序号

使用 redis-cli 连接Redis数据库后,默认使用的是序号为 0 的数据库。

192.168.10.13:6379> select 10        ——切换至序号为10的数据库

192.168.10.13:6379[10]> select 15    ——切换至序号为15的数据库

192.168.10.13:6379[15]> select 0     ——切换至序号为0的数据库

多数据库间移动数据
格式: move  键值  序号

192.168.10.13:6379> set k1 100
OK
192.168.10.13:6379> get k1
"100"
192.168.10.13:6379> select 1
OK
192.168.10.13:6379[1]> get k1
(nil)
192.168.10.13:6379[1]> select 0    ——切换至目标数据库0
OK
192.168.10.13:6379> get k1         ——查看目标数据是否存在
"100"
192.168.10.13:6379> move k1 1      ——将数据库0中k1移动到数据库1中
(integer) 1
192.168.10.13:6379> select 1       ——切换至目标数据库1
OK
192.168.10.13:6379[1]> get k1      ——查看被移动数据
"100"
192.168.10.13:6379[1]> select 0 
OK
192.168.10.13:6379> get k1         ——在数据库0中无法查看到k1的值
(nil)

在这里插入图片描述

在这里插入图片描述

4.10.2 清除数据库内数据

FLUSHDB :清空当前数据库数据
FLUSHALL :清空所有数据库的数据,慎用!
命令:
FLUSHDB
FLUSHALL

redis 远程数据备份 (全量、增量)
是以Shell 脚本的形式
redis_backup.sh
#!/bin/bash 
TIME=$
BCDIR=
redis_server=
post
psword

redis 缓存穿透 击穿 雪崩
redis 分布式锁()

nginx SSL 加秘密 
nginx 暴露一些接口之类的

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值