Redis 基础

YangeIT大约 23 分钟数据库Redis常用指令数据类型NoSQL非关系型数据库缓存数据库

Redis 基础

课程内容

  • Redis 入门 🍐
  • Redis 数据类型 🍐
  • Redis 常用命令 🍐
  • 在 Java 中操作 Redis 🍐 🍐

1. 前言

1.1 什么是 Redis

问题

  1. Redis有什么特点?

Redis 是一个基于内存的 key-value 结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件,它是「Remote Dictionary Service」的首字母缩写,也就是「远程字典服务」。

image-20210927090555559
image-20210927090555559
image-20210927090604994
image-20210927090604994
image-20210927090612540
image-20210927090612540

1.2 使用 Redis 能做什么

  • 数据缓存
  • 消息队列
  • 注册中心
  • 发布订阅

2. Redis 入门

2.1 Redis 简介

问题

  1. Redis性能高吗?为什么高?有多高?

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker. 翻译为:Redis 是一个开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。

官网:https://redis.ioopen in new window

Redis 是用 C 语言开发的一个开源的高性能键值对(key-value)数据库,官方提供的数据是可以达到 100000+的 QPS(每秒内查询次数)。它存储的 value 类型比较丰富,也被称为结构化的 NoSql 数据库。

NoSql(Not Only SQL),不仅仅是 SQL,泛指非关系型数据库。NoSql 数据库并不是要取代关系型数据库,而是关系型数据库的补充。

关系型数据库(RDBMS):

  • Mysql
  • Oracle
  • DB2
  • SQLServer

非关系型数据库(NoSql):

  • Redis
  • Mongo db
  • MemCached

2.2 Redis 下载与安装

问题

  1. Redis只有运行在linux系统下吗?

2.2.1 Redis 下载

Redis 安装包分为 windows 版和 Linux 版:

下载后得到下面安装包:

image-20210927092053283
image-20210927092053283

点击下载 Redis 资料下载open in new window

2.2.2 Redis 安装

1)在 Linux 中安装 Redis

在 Linux 系统安装 Redis 步骤:

  1. 将 Redis 安装包上传到 Linux
  2. 解压安装包,命令:tar -zxvf redis-4.0.0.tar.gz -C /usr/local
  3. 安装 Redis 的依赖环境 gcc,命令:yum install gcc-c++
  4. 进入/usr/local/redis-4.0.0,进行编译,命令:make
  5. 进入 redis 的 src 目录进行安装,命令:make install

安装后重点文件说明:

  • /usr/local/redis-4.0.0/src/redis-server:Redis 服务启动脚本
  • /usr/local/redis-4.0.0/src/redis-cli:Redis 客户端脚本
  • /usr/local/redis-4.0.0/redis.conf:Redis 配置文件

linux安装redis gif动图 🎥

GIF_linux_redis_installconfig.gif
GIF_linux_redis_installconfig.gif

2)在 Windows 中安装 Redis 👈

Redis 的 Windows 版属于绿色软件,直接解压即可使用,解压后目录结构如下:

image-20210927093112281
image-20210927093112281

2.3 Redis 服务启动与停止 👈

1)Linux 系统中启动和停止 Redis

执行 Redis 服务启动脚本文件redis-server

image-20210927094452556
image-20210927094452556

通过启动日志可以看到,Redis 默认端口号为6379

Ctrl + C停止 Redis 服务

通过redis-cli可以连接到本地的 Redis 服务,默认情况下不需要认证即可连接成功。

退出客户端可以输入exit或者quit命令。

# 进入redis的src目录下
cd src
# 执行命令,观察端口号
./redis-server

2)Windows 系统中启动和停止 Redis 👈

Windows 系统中启动 Redis,直接双击 redis-server.exe 即可启动 Redis 服务,redis 服务默认端口号为 6379

image-20210927100421213
image-20210927100421213

Ctrl + C停止 Redis 服务

双击redis-cli.exe即可启动 Redis 客户端,默认连接的是本地的 Redis 服务,而且不需要认证即可连接成功。

image-20210927100319016
image-20210927100319016

退出客户端可以输入exit或者quit命令。

2.4 Redis 配置文件

前面我们已经启动了 Redis 服务,默认情况下 Redis 启动后是在前台运行,而且客户端不需要密码就可以连接到 Redis 服务。如果我们希望 Redis 服务启动后是在后台运行,同时希望客户端认证通过后才能连接到 Redis 服务,应该如果做呢?

此时就需要修改 Redis 的配置文件:

  • Linux 系统中 Redis 配置文件:REDIS_HOME/redis.conf
  • Windows 系统中 Redis 配置文件:REDIS_HOME/redis.windows.conf 👈

通过修改 Redis 配置文件可以进行如下配置:

1️⃣

​ 将配置文件中的daemonize配置项改为 yes,默认值为 no。

​ 注意:Windows 版的 Redis 不支持后台运行。

# 1.关闭redis服务 ctrl +c
# 2.修改redis 配置文件
vim redis-conf
# 3.按i 进入插入模式 修改daemonize为yes
# 4.按esc 输入:wq 保存
# 5.接下来重新启动redis即可(加载指定配置文件,启动redis)
src/redis-server ./redis.conf 

linux安装redis gif动图 🎥

GIF_linux_redis_uhunupconfig.gif
GIF_linux_redis_uhunupconfig.gif
2️⃣ 设置 Redis 服务密码

​ 将配置文件中的 # requirepass foobared 配置项取消注释,默认为注释状态。foobared 为密码,可以根据情况自己指定。

# 1.查询正在运行的redis 进程id pid
ps -ef | grep redis
# 2.杀除redis进程 
kill -9 进程id
# 3.修改redis 配置文件,将配置文件中的 # requirepass foobared 配置项取消注释,
# 其中foobared为密码  
# 4.按i 进入插入模式 
改为 requirepass 123456  #密码为:123456

# 4.按esc 输入:wq 保存
# 5.接下来重新启动redis即可(加载指定配置文件,启动redis)
src/redis-server ./redis.conf 

# --------------方式1:输入密码,连接redis测试一下--------------
src/redis-cli -h localhost -p 6379 # 回车
# 输入 auth 123456 即可操作
auth 123456 # 回车

# --------------方式2:输入密码,连接redis测试一下--------------
src/redis-cli -h localhost -p 6379 -a 123456 #回车 即可操作

3️⃣ 设置允许客户端远程连接 Redis 服务 ⚠️

​ Redis 服务默认只能客户端本地连接,不允许客户端远程连接。将配置文件中的 bind 127.0.0.1 配置项注释掉。

# 1.查询正在运行的redis 进程id pid
ps -ef | grep redis
# 2.杀除redis进程 
kill -9 进程id
# 3.修改redis 配置文件,将配置文件中的 bind 127.0.0.1注释,

# 3.1 按i 进入插入模式 将配置文件中的 bind 127.0.0.1注释,
# bind 127.0.0.1

# 4.按esc 输入:wq 保存
# 5.接下来重新启动redis即可(加载指定配置文件,启动redis)
src/redis-server ./redis.conf 

# 6.放开6379端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent
# 7 重载防火墙
firewall-cmd --reload
# 使用win下的redis-cli.exe 连接redis 指令如下(在win下执行)
./redis-cli.exe -h linux的ip地址  -p 6379  -a 123456

解释说明:

Redis 配置文件中 # 表示注释

  • Redis 配置文件中的配置项前面不能有空格,需要顶格写
  • daemonize:用来指定 redis 是否要用守护线程的方式启动,设置成 yes 时,代表开启守护进程模式。在该模式下,redis 会在后台运行
  • requirepass:设置 Redis 的连接密码
  • bind:如果指定了 bind,则说明只允许来自指定网卡的 Redis 请求。如果没有指定,就说明可以接受来自任意一个网卡的 Redis 请求。

注意:修改配置文件后需要重启 Redis 服务配置才能生效,并且启动 Redis 服务时需要显示的指定配置文件:

1)Linux 中启动 Redis 服务

# 进入Redis安装目录
cd /usr/local/redis-4.0.0
# 启动Redis服务,指定使用的配置文件
./src/redis-server ./redis.conf

2)Windows 中启动 Redis 服务 👈

image-20210927104929169
image-20210927104929169

由于 Redis 配置文件中开启了认证校验,即客户端连接时需要提供密码,此时客户端连接方式变为:

image-20210927105909600
image-20210927105909600

解释说明:

  1. -h:指定连接的 Redis 服务的 ip 地址
  2. -p:指定连接的 Redis 服务的端口号
  3. -a:指定连接的 Redis 服务的密码

2.5 RDM 可视化操作软件

Redis Desktop Manager(RDM),为您提供了一个易于使用的 GUI,方便操作和查看 Redis 缓存情况

RDM 官网下载地址open in new window

或者 点击下载 Redis 资料下载open in new window

2.5.1 连接 redis 数据库

VeryCapture_20220928174244
VeryCapture_20220928174244

3. Redis 数据类型

3.1 介绍

问题

  1. Redis分为几种数据类型?

Redis 存储的是 key-value 结构的数据,其中 key 是字符串类型,value 有 5 种常用的数据类型:

5种常用的数据类型

  1. 字符串(string):普通字符串,常用
  2. 哈希(hash):适合存储对象
  3. 列表(list):按照插入顺序排序,可以有重复元素
  4. 集合(set):无序集合,没有重复元素
  5. 有序集合(sorted set / zset):集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素

4. Redis 常用命令

在线Redis指令练习网站open in new window

4.1 字符串 string 操作命令

问题

  1. Redis 中字符串类型常用命令有哪些?

Redis 中字符串类型常用命令:

  • SET key value 设置指定 key 的值
  • GET key 获取指定 key 的值
  • SETEX key seconds value 设置指定 key 的值,并将 key 的过期时间设为 seconds 秒
  • SETNX key value 只有在 key 不存在时设置 key 的值

更多命令可以参考 Redis 中文网:https://www.redis.net.cnopen in new window

练习指令 ✏️ 🍐

# 存入一个字符串
set name xiaoming
# 获取name
get name

# 存入一个age 
set age 20 
set age 30
# 获得age  
get age  #30 覆盖了

# 练习 SETEX key seconds value 设置指定 key 的值,并将 key 的过期时间设为 seconds 秒
# 设置存10s 
setex city 10 beijing

# 等待10秒
get city #返回nil --->空

# 练习SETNX key value 只有在 key 不存在时设置 key 的值
setnx bookname haha 

setnx bookname heihei

get bookname # 返回haha

## 注意不要传中文,返回类似这种
"\xe5\x87\xa1\xe4\xba\xba\xe4\xbf\xae\xe4\xbb\x99\xe8\xae\xb0"
# 在redis 中存储中文,默认读取不到中文,而是以十六进制的方式储存

⚠️ 中文乱码的解决方式--了解即可open in new window

4.2 哈希 hash 操作命令

问题

  1. Redis 中哈希hash操作命令有哪些?

哈希hash操作命令

Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象,常用命令:

  • HSET key field value 将哈希表 key 中的字段 field 的值设为 value
  • HGET key field 获取存储在哈希表中指定字段的值
  • HDEL key field 删除存储在哈希表中的指定字段
  • HKEYS key 获取哈希表中所有字段
  • HVALS key 获取哈希表中所有值
  • HGETALL key 获取在哈希表中指定 key 的所有字段和值
image-20210927113014567
image-20210927113014567

练习指令 ✏️ 🍐

根据图解完成指令

# 往key 为001 存入 hash键值对 2对
hset 001 name zhangsan
hset 001 age  23
hset 002 name lisi
hset 002 age  16

# 练习 HGET key field 获取存储在哈希表中指定字段的值
# 获取002中的 name的值
hget 002 name

# 练习 HDEL key field 删除存储在哈希表中的指定字段
# 删除 002 中的name
hdel 002 name

# 练习HKEYS key 获取哈希表中所有字段
hkeys 002

# 练习HVALS key 获取哈希表中所有值
HVALS 002

# 练习 HGETALL key 获取在哈希表中指定 key 的所有字段和值

HGETALL 001


4.3 列表 list 操作命令

问题

  1. Redis 中列表 list 操作命令有哪些?

列表 list 操作命令

Redis 列表是简单的字符串列表,按照插入顺序排序,常用命令:

先插入的在尾部,后插入的在头部

  • LPUSH key value1 [value2] 将一个或多个值插入到列表头部
  • LRANGE key start stop 获取列表指定范围内的元素
  • RPOP key 移除并获取列表最后一个元素
  • LLEN key 获取列表长度
  • BRPOP key1 [key2 ] timeout 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超 时或发现可弹出元素为止
image-20210927113312384
image-20210927113312384

练习指令 ✏️ 🍐

根据图解完成指令

# LPUSH key value1 [value2] 将一个或多个值插入到列表头部
LPUSH list1 a b c d
LPUSH list2 1 2 3 4
LPUSH list3 9 8 7 6

# LRANGE key start stop 获取列表指定范围内的元素
LRANGE list1 0 -1 # 查所有
# a最先插入,所以在尾部

# RPOP key 移除并获取列表最后一个元素
RPOP list1 # 返回a   当然a没有了

# LLEN key 获取列表长度
LLEN list1  # 3


# BRPOP key1 [key2 ] timeout 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超 时或发现可弹出元素为止

BRPOP list1  10  

4.4 集合 set 操作命令

问题

  1. Redis 中set 操作命令有哪些?

set 操作命令

Redis set 是 string 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据,常用命令:

  • SADD key member1 [member2] 向集合添加一个或多个成员
  • SMEMBERS key 返回集合中的所有成员
  • SCARD key 获取集合的成员数
  • SINTER key1 [key2] 返回给定所有集合的交集
  • SUNION key1 [key2] 返回所有给定集合的并集
  • SDIFF key1 [key2] 返回给定所有集合的差集
  • SREM key member1 [member2] 移除集合中一个或多个成员
image-20210927113632472
image-20210927113632472

练习指令 ✏️ 🍐

根据图解完成指令


# SADD key member1 [member2] 向集合添加一个或多个成员
SADD set1 a b c
SADD set2 1 2 3

# SMEMBERS key 返回集合中的所有成员
SMEMBERS set1

# SCARD key 获取集合的成员数
SCARD  set1

# SINTER key1 [key2] 返回给定所有集合的交集

SINTER set1 set2 # a 交集是a


# SUNION key1 [key2] 返回所有给定集合的并集

SUNION set1 set2  # a b c 2 3

# SDIFF key1 [key2] 返回给定所有集合的差集

SDIFF set1 set2  #注意顺序 2者相减

# SREM key member1 [member2] 移除集合中一个或多个成员
SREM set1 a b # 删除元素

4.5 有序集合 sorted set 操作命令

问题

  1. Redis 中sorted set 操作命令有哪些?

Redis sorted set 有序集合是 string 类型元素的集合,且不允许重复的成员。每个元素都会关联一个 double 类型的分数(score) 。redis 正是通过来为集合中的成员进行。有序集合的成员是

sorted set 操作命令

  • ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的 分数
  • ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合中指定区间内的成员
  • ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment
  • ZREM key member [member ...] 移除有序集合中的一个或多个成员
image-20210927114003383
image-20210927114003383

练习指令 ✏️ 🍐

根据图解完成指令

# ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的 分数
zadd sset1  0.1 a  3.0 b 2.5 c
zadd sset2  9.9 p  8.8 w 2.0 q

# ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合中指定区间内的成员
ZRANGE sset1 0 -1 # 获得全部
ZRANGE sset1 0 -1  WITHSCORES # 分数也会显示

# ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment
ZINCRBY  sset1 20 b #意味着b的分值改变了
# 可以查询下
ZRANGE sset1 0 -1  WITHSCORES

# ZREM key member [member ...] 移除有序集合中的一个或多个成员
ZREM sset1 b #将b这个元素移除

4.6 通用命令

Redis 中的通用命令,主要是针对 key 进行操作的相关命令:

通用命令

  • KEYS pattern 查找所有符合给定模式( pattern)的 key
  • EXISTS key 检查给定 key 是否存在
  • TYPE key 返回 key 所储存的值的类型
  • TTL key 返回给定 key 的剩余生存时间(TTL, time to live),以秒为单位
  • DEL key 该命令用于在 key 存在是删除 key

练习指令 ✏️ 🍐

# KEYS pattern 查找所有符合给定模式( pattern)的 key
KEYS * #查询所有的key


# EXISTS key 检查给定 key 是否存在

EXISTS bookname 

# TYPE key 返回 key 所储存的值的类型

TYPE bookname

# TTL key 返回给定 key 的剩余生存时间(TTL, time to live),以秒为单位
TTL bookname # -1表示一直存在

# DEL key 该命令用于在 key 存在是删除 key
DEL  bookname
KEYS * #查询所有的key

警告

keys 命令的时间复杂度是 O(N),N 是 redis 库中的数据量,也就是说这个命令的执行时间是随着库中的数据量增多呈正比的,数据量越大,执行时间越长。所以尽管这个命令的速度很快,但如果是一个数据量很大的库,还是会造成性能问题的。

5. 在 Java 中操作 Redis 👈

5.1 介绍

问题

  1. Java操作redis有哪些技术?哪种最常用?

前面我们讲解了 Redis 的常用命令,这些命令是我们操作 Redis 的基础,那么我们在 java 程序中应该如何操作 Redis 呢?这就需要使用 Redis 的 Java 客户端,就如同我们使用 JDBC 操作 MySQL 数据库一样。

Redis 的 Java 客户端很多,官方推荐的有三种:

  • Jedis
  • Lettuce
  • Redisson

Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在 Spring Boot 项目中还提供了对应的 Starter,即 spring-boot-starter-data-redis

5.2 🚀 🚀

Jedis 是 Redis 的 Java 版本的客户端实现。

maven 坐标:

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.8.0</version>
</dependency>

使用 Jedis 操作 Redis 的步骤:

  1. 获取连接
  2. 执行操作
  3. 关闭连接

示例代码:

/**
 * 使用Jedis操作Redis
 */
public class JedisTest {
    @Test
    public void testRedis(){
        JedisShardInfo jedisShardInfo = new JedisShardInfo("127.0.0.1", 6379);
//        设置密码
        jedisShardInfo.setPassword("123456");
        //1 获取连接
        Jedis jedis = new Jedis(jedisShardInfo);

        //2 执行具体的操作
        jedis.set("school","itcast");
        // 从缓存中获得数据
        String value = jedis.get("school");
        System.out.println(value);

        //3 关闭连接
        jedis.close();
    }
}
点击查看完整代码
package com.yangeit;

import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.Tuple;

import java.util.List;
import java.util.Set;

/**
 * 使用Jedis操作Redis
 */
public class JedisTest {
    @Test
    public void testRedis(){
        JedisShardInfo jedisShardInfo = new JedisShardInfo("192.168.138.100", 6379);
//        设置密码
        jedisShardInfo.setPassword("123456");
        //1 获取连接
        Jedis jedis = new Jedis(jedisShardInfo);
// TODO: 字符串
        //2 执行具体的操作
        jedis.set("name","222222");
        // 从缓存中获得数据
        String value = jedis.get("name");
        System.out.println(value);

// TODO: hash
        jedis.hset("hset1","name","李四");
        String hget = jedis.hget("hset1", "name");
        System.out.println(hget);

// TODO: list列表
        jedis.lpush("list1","1","2","3","4");
        List<String> list1 = jedis.lrange("list1", 0, -1);
        System.out.println(list1);

// TODO: 集合set
      jedis.sadd("set1", "a", "a", "b", "c");
      Set<String> set1 = jedis.smembers("set1");
      System.out.println(set1);

// TODO: 有序集合set
        jedis.zadd("zset1",3.9,"aa");
        jedis.zadd("zset1",3.8,"bb");
        jedis.zadd("zset1",2.9,"cc");
        jedis.zadd("zset1",9.0,"gg");
//        Redis Zrevrange 命令返回有序集中,指定区间内的成员。其中成员的位置按分数值递减(从大到小)来排列。
        Set<String> zset1 = jedis.zrevrange("zset1", 0, -1);

        System.out.println(zset1);


        //3 关闭连接
        jedis.close();
    }
}

5.3 Spring Data Redis ❤️ 简单实用

问题

  1. RedisTemplate的作用是什么?

5.3.1 介绍

Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用 Spring Data Redis 来简化 Redis 操作。

网址:https://spring.io/projects/spring-data-redisopen in new window

image-20210927143741458
image-20210927143741458

maven 坐标:

<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-redis</artifactId>
	<version>2.4.8</version>
</dependency>

Spring Boot 提供了对应的 Starter,maven 坐标: 👈 👈

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Spring Data Redis 中提供了一个高度封装的类:RedisTemplate,针对 Jedis 客户端中大量 api 进行了归类封装,将同一类型操作封装为 operation 接口,具体分类如下:

Redis操作类:

  • ValueOperations:简单 K-V 操作
  • SetOperations:set 类型数据操作
  • ZSetOperations:zset 类型数据操作
  • HashOperations:针对 hash 类型的数据操作
  • ListOperations:针对 list 类型的数据操作

5.3.2 使用方式

5.3.2.1 环境搭建

第一步:创建 maven 项目 springdataredis_demo,配置 pom.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
        <relativePath/>
    </parent>
    <groupId>com.itheima</groupId>
    <artifactId>springdataredis_demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.4.5</version>
            </plugin>
        </plugins>
    </build>
</project>








 


















 
 
 
 
 










☆ 学习方法培养

  1. 晚自习第一节课,老师总结完毕之后,每个同学先必须梳理今日知识点 (md 笔记也行);整理好的可以发给组长,组长交给你班长,意在培养大家总结的能力)

  2. 晚自习第二节课开始练习(记住:程序员是代码堆起来的):

    1. 先要把今天的所有案例,按照书写顺序写一遍
  3. 离下晚自习还有 20 分钟时候:预习第二天的知识,预习的时候一定要注意:

    1. 预习不是学习,不要看第二天的视频,切记不要看第二天视频
    2. 预习第二天的笔记,把第二天笔记全部过一遍(没看懂的跳过),重点注意自己没看懂的知识点,打上标记,第二天着重听这一块