Redis基础课程讲义

Redis基础

课程内容

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

1. 前言

1.1 什么是Redis

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

image-20210927090555559

image-20210927090604994

image-20210927090612540

1.2 使用Redis能做什么

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

image-20211211095723721

image-20211211095827068

2. Redis入门

2.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.io https://www.redis.net.cn/

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

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

关系型数据库(RDBMS):

  • Mysql
  • Oracle
  • DB2
  • SQLServer

非关系型数据库(NoSql):

  • Redis
  • Mongo db
  • MemCached

https://db-engines.com/ (数据库排行榜)

2.2 Redis下载与安装

2.2.1 Redis下载

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

下载后得到下面安装包:

image-20210927092053283

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配置文件

2)在Windows中安装Redis

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

image-20210927093112281

2.3 Redis服务启动与停止

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

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

image-20210927094452556

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

Ctrl + C停止Redis服务

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

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

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

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

image-20210927100421213

Ctrl + C停止Redis服务

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

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)设置Redis服务后台运行

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

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

2)设置Redis服务密码

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

3)设置允许客户端远程连接Redis服务

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

修改redis.conf配置文件的 69行
bind 0.0.0.0  

解释说明:

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

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

image-20210927105909600

解释说明:

-h:指定连接的Redis服务的ip地址

-p:指定连接的Redis服务的端口号

-a:指定连接的Redis服务的密码

补充:也可在redis-cli命令终端内部认证:

[root@192 redis-4.0.0]# src/redis-cli 
127.0.0.1:6379> KEYS *
# 当前用户没有被合法认证
(error) NOAUTH Authentication required.
# 通过auth命令认证
127.0.0.1:6379> AUTH laofang
OK
127.0.0.1:6379> KEYS *
(empty list or set)
127.0.0.1:6379> 

3. Redis数据类型

3.1 介绍

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

  • 字符串 string
  • 哈希 hash--->类型java中的HashMap
  • 列表 list--->类似java的ArrayList
  • 集合 set---->类型java中HashSet
  • 有序集合 sorted set / zset--->技能保证有序,有能保证不重复,集合了列表和集合的优势;

3.2 Redis 5种常用数据类型

image-20211211112743856

image-20210927111819871

解释说明:

字符串(string):普通字符串,常用

哈希(hash):适合存储对象

列表(list):按照插入顺序排序,可以有重复元素

集合(set):无序集合,没有重复元素

有序集合(sorted set / zset):集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素

4. Redis常用命令

4.1 字符串string操作命令

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

  • SET key value 设置指定key的值
  • GET key 获取指定key的值
  • SETEX key seconds value 设置指定key的值,并将 key 的过期时间设为 seconds 秒
    • 等价于:SET key value ex 10
  • SETNX key value 只有在 key 不存在时设置 key 的值 NOT EXIST
  • del key 删除指定的key

更多命令可以参考Redis中文网:https://www.redis.net.cn

操作流水:

# 保存string
127.0.0.1:6379> set name zhangsan
OK
# 查询
127.0.0.1:6379> get name
"zhangsan"
# 设置name2值为lisi,且存活5s,5秒后,内存销毁
setex key  second value # 此处的value是指key对应的value值
127.0.0.1:6379> setex name2 5  lisi
OK
# 如果一个key已经存在,要设置一个过期时间,使用
# 命令格式EXPIRE key seconds
127.0.0.1:6379> EXPIRE name 5
(integer) 1
# 也可通过set实现过期机制,ex 10表示存活10秒
127.0.0.1:6379> SET name3 wangwu ex 10
OK
# 保存键值对,如果key存在则不保存,不存在则保存
127.0.0.1:6379> SET name wangwu nx
(nil)
127.0.0.1:6379> get name
"lisi"
# 同样也可通过SETNX指令实现key存在则不保存,不存在则保存
127.0.0.1:6379> SETNX name wangwu
(integer) 0
127.0.0.1:6379> get name
"lisi"
# 查看所有的key
127.0.0.1:6379> KEYS *
1) "person"

4.2 哈希hash操作命令

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

  • HSET key field value 将哈希表 key 中的字段 field 的值设为 value
    • 注意点:可以一次性保存多个filed value
  • HGET key field 获取存储在哈希表中指定字段的值
  • HDEL key field 删除存储在哈希表中的指定字段
    • 可以一次性删除多个field
  • HKEYS key 获取哈希表中所有字段
  • HVALS key 获取哈希表中所有值
  • HGETALL key 获取在哈希表中指定 key 的所有字段和值

image-20210927113014567

Hash数据结构的应用场景:

​ 1.存储用户信息,eg: user:123456 --->{name:zhangsan age:18}

​ 2. 商品信息等

总之,只要符合一些列的feild 和value值多属性的,都可以保存,前提是:数据是热点数据;

操作流水:

# 一次性添加多个字段和值
127.0.0.1:6379> HSET person name zhangsan  age 18
127.0.0.1:6379> HGET person name
"zhangsan"
127.0.0.1:6379> HGET person age
"18"
127.0.0.1:6379> HDEL person age
127.0.0.1:6379> HVALS person
1) "zhangsan"

4.3 列表list操作命令

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

  • LPUSH key value1 [value2] 将一个或多个值插入到列表头部(列表左侧)
  • LRANGE key start stop 获取列表指定范围内的元素
  • RPOP key 移除并获取列表最后一个元素
  • LLEN key 获取列表长度
  • BRPOP key1 [key2 ] timeout 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超 时或发现可弹出元素为止,超时时间单位默认是秒
  • LREM key 个数 value值

image-20210927113312384

场景:

​ 1.电商项目中大广告位热点数据缓存;

​ 2.一些热点的队列数据等

操作流水:

# 添加元素
127.0.0.1:6379> LPUSH list1 zhangsan lisi wangwu zhaoliu
(integer) 4
# 查询元素,索引位从0开始
127.0.0.1:6379> LRANGE list1 0 3
# 右侧弹出元素(从右侧获取并删除一个元素)
127.0.0.1:6379> RPOP list
# 获取长度
127.0.0.1:6379> LLEN list1
(integer) 3
# 弹出右侧元素,如果不存在则阻塞等待指定时长
127.0.0.1:6379> BRPOP list1 10
1) "list1"
2) "lisi"
127.0.0.1:6379> BRPOP list1 10
1) "list1"
2) "wangwu"
127.0.0.1:6379> BRPOP list1 10
1) "list1"
127.0.0.1:6379> LPUSH names 11 22 33 44 11 22 55 66 11
(integer) 9
# 0 到-1表示查询所有list元素
127.0.0.1:6379> LRANGE names 0 -1
1) "11"
2) "66"
3) "55"
4) "22"
5) "11"
6) "44"
7) "33"
8) "22"
9) "11"
# 从表头删除元素,2表示删除2个,11表示删除的元素值
127.0.0.1:6379> LREM names 2 11
(integer) 2
127.0.0.1:6379> LRANGE names 0 -1
1) "66"

4.4 集合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

应用场景:

​ 1.需要去重的少量信息,比如:身份证信息、手机号码等作为黑名单|白名单;

​ 2.共同的好友查询,使用set的交集

​ eg: zhang:{11,22,33,44} lisi:{22,33,66,88}

​ zhangsan和lisi共同的好友:交集取22 33即可!

​ 扩展:推荐可能认识的人?

​ 如果zhangsan认识lisi,那么lisi可能认识 zhangsan与lisi的差集~

操作流水:

# 添加元素,自动去重
127.0.0.1:6379> SADD setnum 22 33 44 55 22 55
(integer) 4
# 查看所有元素
127.0.0.1:6379> SMEMBERS setnum
1) "22"
2) "33"
3) "44"
4) "55"
127.0.0.1:6379> SMEMBERS setnum2
1) "44"
2) "55"
127.0.0.1:6379> SADD setnum2 77 88 
(integer) 2
127.0.0.1:6379> SMEMBERS setnum2
1) "44"
2) "55"
3) "77"
4) "88"
# 并集
127.0.0.1:6379> SUNION setnum setnum2
1) "22"
# 删除元素
127.0.0.1:6379> SREM setnum 11 22 33
(integer) 2

4.5 有序集合sorted set操作命令

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

常用命令:

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

image-20210927114003383

应用场景:

​ 1.b站视频点击量排名

​ 2.新浪热点文章点击量、收藏量等排名

​ 3.班级学生考试成绩分数排名等

操作流水:

# zset集合添加元素
127.0.0.1:6379> ZADD zset1 80 zhangsan  20 lisi  90 wangwu 66 zhaoliu 100 tianqi
(integer) 5
# 有序集合底层也维护了元素的下标索引,默认的顺序根据分数升序排序
127.0.0.1:6379> ZRANGE zset1 0 -1
1) "lisi"
2) "zhaoliu"
3) "zhangsan"
4) "wangwu"
5) "tianqi"
# 查询时包含元素的分数
127.0.0.1:6379> ZRANGE zset1 0 -1 WITHSCORES
 1) "lisi"
 2) "20"
 3) "zhaoliu"
 4) "66"
 5) "zhangsan"
 6) "80"
 7) "wangwu"
 8) "90"
 9) "tianqi"
10) "100"
# 给指定元素增加执行的分数
127.0.0.1:6379> ZINCRBY zset1 40 lisi
"60"
127.0.0.1:6379> 
# 删除指定元素
127.0.0.1:6379> ZREM zset1 zhaoliu
(integer) 1
# 如何实现根据分数范围查询指定的元素呢?
# 特点:根据分数查询,查询的结果包含边界值
127.0.0.1:6379> ZRANGEBYSCORE zset1 90 100 withscores
1) "wangwu"
2) "90"
3) "tianqi"
4) "100"

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

操作流水:

# 获取redis中所有key
127.0.0.1:6379> KEYS *
1) "person"
2) "zset1"
3) "setnum2"
4) "names"
5) "setnum"
# 获取以setnum开头的key
127.0.0.1:6379> KEYS setnum*
1) "setnum2"
2) "setnum"
# 检查指定的key是否存在,不存在则返回0
127.0.0.1:6379> EXISTS person
(integer) 1
127.0.0.1:6379> EXISTS person2
(integer) 0
# 获取key的类型
127.0.0.1:6379> TYPE person
hash
127.0.0.1:6379> TYPE setnum
set
127.0.0.1:6379> TYPE zset1
zset
# 设置存储周期
127.0.0.1:6379> SET name zhangsan ex 20
OK
# 检查指定key剩余存活周期,time to live
127.0.0.1:6379> TTL name
(integer) 11
# 负数表示过期
127.0.0.1:6379> TTL name
(integer) -2
127.0.0.1:6379> get name
(nil)
# 删除任意key
127.0.0.1:6379> DEL setnum
(integer) 1
127.0.0.1:6379> SMEMBERS setnum
(empty list or set)
127.0.0.1:6379> 
# 如何切换数据分片? select 分片索引位,从0~15
127.0.0.1:6379> SELECT 1
OK
# 清空操作,清除所有redis实例下的0~15数据分片的key,开发慎用
127.0.0.1:6379> FLUSHALL
OK
# 如果仅仅情况当前分片下的数据,比如分片0,则使用
127.0.0.1:6379> FLUSHDB
OK
127.0.0.1:6379> KEYS *
(empty list or set)

5. 在Java中操作Redis

5.1 介绍

前面我们讲解了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

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

maven坐标:

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

使用 Jedis 操作 Redis 的步骤:

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

示例代码:

package com.itheima.test;

import org.junit.Test;
import redis.clients.jedis.Jedis;
import java.util.Set;

/**
 * 使用Jedis操作Redis
 */
public class JedisTest {

    @Test
    public void testRedis(){
        //1 获取连接
        Jedis jedis = new Jedis("localhost",6379);
        
        //2 执行具体的操作
        jedis.set("username","xiaoming");

        String value = jedis.get("username");
        System.out.println(value);

        //jedis.del("username");

        jedis.hset("myhash","addr","bj");
        String hValue = jedis.hget("myhash", "addr");
        System.out.println(hValue);

        Set<String> keys = jedis.keys("*");
        for (String key : keys) {
            System.out.println(key);
        }

        //3 关闭连接
        jedis.close();
    }
}
package com.itheima.test;

import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisTest {
    /**
     * JDBC: java代码操作mysql数据库的工具
     * Jedis: java代码操作redis数据库的工具
     */
    @Test
    public void testJedis(){
        // 创建jedis对象
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        //jedis.auth("密码");
        // 存放数据信息
        //String result = jedis.set("name", "刘岩");
        //System.out.println(result);
        // 获取数据信息
        String name = jedis.get("name");
        System.out.println(name);

        // 关闭
        jedis.close();
    }

    @Test
    public void testJedisPoll(){
        // 连接池配置信息
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(30); // 最大连接数
        config.setMaxIdle(10); // 最大空闲数
        config.setMaxWaitMillis(3000); // 最大等待时间
        // 连接池对象
        JedisPool jedisPool = new JedisPool(config, "127.0.0.1", 6379);
        // 从连接池中获取连接
        Jedis jedis = jedisPool.getResource();
        // 存放数据信息
        //String result = jedis.set("name", "刘岩");
        //System.out.println(result);
        // 获取数据信息
        String name = jedis.get("name");
        System.out.println(name);

        // 关闭/归还
        jedis.close();
    }
}

5.3 Spring Data Redis

5.3.1 介绍

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

网址:https://spring.io/projects/spring-data-redis

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接口,具体分类如下:

  • 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>

第二步:编写启动类

package com.itheima;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class,args);
    }

}

第三步:配置application.yml

spring:
  application:
    name: springdataredis_demo
  #Redis相关配置
  redis:
    host: localhost
    port: 6379
    #password: 123456
    database: 0 #操作的是0号数据库

解释说明:

spring.redis.database:指定使用Redis的哪个数据库,Redis服务启动后默认有16个数据库,编号分别是从0到15。

可以通过修改Redis配置文件来指定数据库的数量。

第四步:提供配置类

package com.itheima.config;

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Redis配置类
 */
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {

        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();

        //默认的Key序列化器为:JdkSerializationRedisSerializer
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());

        redisTemplate.setConnectionFactory(connectionFactory);

        return redisTemplate;
    }

}

解释说明:

当前配置类不是必须的,因为 Spring Boot 框架会自动装配 RedisTemplate 对象,但是默认的key序列化器为JdkSerializationRedisSerializer,导致我们存到Redis中后的数据和原始数据有差别

第五步:提供测试类

package com.itheima.test;

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringDataRedisTest {

    @Autowired
    private RedisTemplate redisTemplate;
    
}
5.3.2.2 操作字符串类型数据
/**
 * 操作String类型数据
*/
@Test
public void testString(){
    //存值
    redisTemplate.opsForValue().set("city123","beijing");

    //取值
    String value = (String) redisTemplate.opsForValue().get("city123");
    System.out.println(value);

    //存值,同时设置过期时间
    redisTemplate.opsForValue().set("key1","value1",10l, TimeUnit.SECONDS);

    //存值,如果存在则不执行任何操作
    Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("city1234", "nanjing");
    System.out.println(aBoolean);
}
5.3.2.3 操作哈希类型数据
/**
 * 操作Hash类型数据
*/
@Test
public void testHash(){
    HashOperations hashOperations = redisTemplate.opsForHash();

    //存值
    hashOperations.put("002","name","xiaoming");
    hashOperations.put("002","age","20");
    hashOperations.put("002","address","bj");

    //取值
    String age = (String) hashOperations.get("002", "age");
    System.out.println(age);

    //获得hash结构中的所有字段
    Set keys = hashOperations.keys("002");
    for (Object key : keys) {
        System.out.println(key);
    }

    //获得hash结构中的所有值
    List values = hashOperations.values("002");
    for (Object value : values) {
        System.out.println(value);
    }
}
5.3.2.4 操作列表类型数据
/**
 * 操作List类型的数据
*/
@Test
public void testList(){
    ListOperations listOperations = redisTemplate.opsForList();

    //存值
    listOperations.leftPush("mylist","a");
    listOperations.leftPushAll("mylist","b","c","d");

    //取值
    List<String> mylist = listOperations.range("mylist", 0, -1);
    for (String value : mylist) {
        System.out.println(value);
    }

    //获得列表长度 llen
    Long size = listOperations.size("mylist");
    int lSize = size.intValue();
    for (int i = 0; i < lSize; i++) {
        //出队列
        String element = (String) listOperations.rightPop("mylist");
        System.out.println(element);
    }
}
5.3.2.5 操作集合类型数据
/**
 * 操作Set类型的数据
*/
@Test
public void testSet(){
    SetOperations setOperations = redisTemplate.opsForSet();

    //存值
    setOperations.add("myset","a","b","c","a");

    //取值
    Set<String> myset = setOperations.members("myset");
    for (String o : myset) {
        System.out.println(o);
    }

    //删除成员
    setOperations.remove("myset","a","b");

    //取值
    myset = setOperations.members("myset");
    for (String o : myset) {
        System.out.println(o);
    }

}
5.3.2.6 操作有序集合类型数据
/**
 * 操作ZSet类型的数据
*/
@Test
public void testZset(){
    ZSetOperations zSetOperations = redisTemplate.opsForZSet();

    //存值
    zSetOperations.add("myZset","a",10.0);
    zSetOperations.add("myZset","b",11.0);
    zSetOperations.add("myZset","c",12.0);
    zSetOperations.add("myZset","a",13.0);

    //取值
    Set<String> myZset = zSetOperations.range("myZset", 0, -1);
    for (String s : myZset) {
        System.out.println(s);
    }

    //修改分数
    zSetOperations.incrementScore("myZset","b",20.0);

    //取值
    myZset = zSetOperations.range("myZset", 0, -1);
    for (String s : myZset) {
        System.out.println(s);
    }

    //删除成员
    zSetOperations.remove("myZset","a","b");

    //取值
    myZset = zSetOperations.range("myZset", 0, -1);
    for (String s : myZset) {
        System.out.println(s);
    }
}
5.3.2.7 通用操作
/**
 * 通用操作,针对不同的数据类型都可以操作
*/
@Test
public void testCommon(){
    //获取Redis中所有的key
    Set<String> keys = redisTemplate.keys("*");
    for (String key : keys) {
        System.out.println(key);
    }

    //判断某个key是否存在
    Boolean itcast = redisTemplate.hasKey("itcast");
    System.out.println(itcast);

    //删除指定key
    redisTemplate.delete("myZset");

    //获取指定key对应的value的数据类型
    DataType dataType = redisTemplate.type("myset");
    System.out.println(dataType.name());

}
5.3.2.8 整合连接池

pom引入依赖:

<!-- redis创建连接池,默认不会创建连接池 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

配置连接池:

# 配置redis环境
spring:
  redis:
    # 默认连接本地localhost,如果仅仅连接本地redis服务,则可不写
    host: 192.168.200.128
    # 默认端口是6379,则省略不写
    port: 6379
    # 设置密码,如果服务器没有设置redis密码,则可省列不写
    password: laofang
    # redis实例中分为16分片库,索引位从0~15,默认操纵的是0
    database: 0
    lettuce:
      pool:
        max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 8 # 连接池中的最大空闲连接
        min-idle: 1  # 连接池中的最小空闲连接
    timeout: PT10S # 连接超时时间
   时间配置表达式示例:
     *    "PT20.345S" -- parses as "20.345 seconds"
     *    "PT15M"     -- parses as "15 minutes" (where a minute is 60 seconds)
     *    "PT10H"     -- parses as "10 hours" (where an hour is 3600 seconds)
     *    "P2D"       -- parses as "2 days" (where a day is 24 hours or 86400 seconds)
     *    "P2DT3H4M"  -- parses as "2 days, 3 hours and 4 minutes"
     *    "P-6H3M"    -- parses as "-6 hours and +3 minutes"
     *    "-P6H3M"    -- parses as "-6 hours and -3 minutes"
     *    "-P-6H+3M"  -- parses as "+6 hours and -3 minutes"

6.持久化-扩展

redis将数据存放在内存中,当redis关闭时,内存释放,数据丢失.
持久化: 将内存中的数据存放到硬盘上,这个过程叫做持久化.
  类比mysql:
	update user set name=''lisi" where id=12;
      保存数据的方式:
      	1.备份命令(sql),如果服务宕机重启,则重新执行下这个sql即可恢复数据;
      	2.备份数据本身 user name lisi id 12
-------------------------------------------------
redis的持久化方案:
	RDB(Redis database)-redis: 
		特征:
			RDB在持久化时,直接将内存中的数据持久化到硬盘(dump.rdb文件中)
              		备份文件中保存的是数据本身;
		默认情况下开启,使用RDB持久化.
        持久化时机: 手动触发
	   save:会阻塞当年操作主线程的调用,说白了,就是在进行rdb的时候,其他客户端操作被阻塞挂起;
            bgsave:background save:后台保存,不阻塞正常客户端的调用
            redis-cli shutdown
            ctrl + c
        配置文件:
	   save 900 1  : 表示如果900秒内至少1个key发生变化(新增、修改和删除),则重写rdb持久化
            save 300 10 : 表示如果每300秒内至少10个key发生变化(新增、修改和删除),则重写rdb持久化;
            save 60 10000 : 表示如果每60秒内至少10000个key发生变化(新增、修改和删除),则重写rdb持久化
            save "" : 关闭RDB持久化
       	缺点:
			可能导致数据丢失
       	优点:
			持久化效率高,持久化的是内存中的数据
			数据库宕机后,数据恢复的效率要更高;
	AOF(Append Only File):
		特征:
			AOF在持久化时,持久化的是,执行过的每一条命令,将每一条命令以日志的形式持久化到硬盘文件中(appendonly.aof).
              		说白了,aof记录的是操纵redis的指令流水(将来恢复数据时,只需重发指令即可);
            AOF持久化默认关闭
        开启AOF持久化:
			修改配置文件:
				appendonly yes
		持久化时机:
			# appendfsync always  总是,每执行一条命令就持久化一次
					说白了,就是redis客户端执行写操作一次,那么就发生一次磁盘io,开销非常高
                    		      如果项目强制要求数据零丢失,那么只能开启always
			命令执行一次,io就发生一次,效率低,但是绝对安全;
           		  appendfsync everysec  每秒持久化一次
           		  					有数据丢失的风险的
            						效率上比always,开发中一般使用这种模式
           	       # appendfsync no      由操作系统自动调度刷磁盘(性能是最好)
              						有数据丢失的风险的;
		缺点:
			执行效率低,会持久化每一条命令,会影响redis的性能
			相比较与rdb持久化方式,使用aop恢复数据的效率低;
              优点:
			不会导致数据丢失,可以对数据进行恢复;
posted @   忘了鱼尾纱的猫  阅读(15)  评论(0编辑  收藏  举报
相关博文:
·  Day01
·  Day03.JDBC
·  Redis
·  Redis
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
  1. 1 刘哈哈与大先生 刘心&大鹏
  2. 2 我们打着光脚在风车下跑,手上的狗尾巴草摇啊摇 等一下就回家 / -艾兜
  3. 3 哎呦 毛不易
  4. 4 夜、萤火虫和你 AniFace
我们打着光脚在风车下跑,手上的狗尾巴草摇啊摇 - 等一下就回家 / -艾兜
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词:等一下就回家/艾兜

作曲:等一下就回家/艾兜

混音:裴济逸

编曲:HYPER MUSIC

风是从哪儿来手上的狗尾巴草摇的更剧烈

稻穗也晃起来我紧握着你的手把它拍成照片

我们俩转 就像大风车

早该逃离这我转转 把云卷散了

下个地方 风筝睡醒了

乘着它走吧 飘飘 等着大风车

像在画一幅油画

陶醉你的笑容

就沿着风车走吧

不用 猜忌 下个地点

让我忘记时间to the midnight

the sun came out 把所有染成金色的

风风风让它吹过来

至少年轻我还记得

oh 找一个地方落下

躺在谷仓里

和你讲着小话

什么风都吹不倒它

它就像是活的

知道哪是它的家

风是从哪儿来手上的狗尾巴草摇的更剧烈

稻穗也晃起来我紧握着你的手把它拍成照片

我们俩转 就像大风车

早该逃离这我转转 把云卷散了

下个地方 风筝睡醒了

乘着它走吧 飘飘 等着大风车

像在画一幅油画

陶醉你的笑容

就沿着风车走吧

不用 猜忌 下个地点

我们打着光脚在那风车下跑

等一下就回家怎么才到半山腰

就让那些烦恼都随风去吧

随着稻香飘过的地方耶哎呦喂

喜欢那时候风言风语

总是习惯悲中带着笑

喜欢被无视的童言无忌

被风车带走不在

风是从哪儿来手上的狗尾巴草摇的更剧烈

稻穗也晃起来我紧握着你的手把它拍成照片

我们俩转 就像大风车

早该逃离这我转转 把云卷散了

下个地方 风筝睡醒了

乘着它走吧 飘飘 等着大风车

像在画一幅油画

陶醉你的笑容

就沿着风车走吧

不用 猜忌 下个地点

点击右上角即可分享
微信分享提示