Redis学习笔记①基础篇_Redis快速入门

2023-11-16


若文章内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系博主删除。



  • 写该系列博客的目的旨在学习巩固知识,方便个人在线阅览。
  • 博客的内容主要来自黑马程序员官方免费公开提供的资料里的文档笔记中的 PPT

嘛,都可以看看。这个 2022 版本的有些地方讲的确实简略。

但我是懒得去看 2019 年的老视频了,不过看看别的博主记录的博客倒也是不错的选择的。


0.系列文章目录



在这里插入图片描述


  • 学习目标
    • 知道 NoSQLSQL 的差别
    • 熟悉 Redis 的常用 5 种数据结构
    • 熟悉 Redis 的常用命令
    • 熟练使用 JedisSpringDataRedis

1.初识 Redis


1.1.认识 NoSQL


1.1.1.简单介绍


  • 概念NoSQLNot-Only SQL( 泛指非关系型的数据库),一般作为关系型数据库的补充。
  • 作用:应对基于海量用户和海量数据前提下的数据处理问题。
  • 特征:可扩容,可伸缩;大数据量下高性能;灵活的数据模型;高可用
  • 常见 NoSQL 数据库Redis、memcache、HBase、MongoDB

1.1.2.NoSQL 与 SQL


SQL(发音为字母 S-Q-L 或 sequel)是结构化查询语言Structured Query Language)的缩写。

SQL 是一种专门用来与数据库通信的语言。


  • SQLStructured Query Language

在这里插入图片描述

  • NoSQLNot-Only SQL

在这里插入图片描述


  • NoSQL 与 SQL 的对比表

在这里插入图片描述


1.2.认识 Redis


Redis 诞生于2009年全称是 Remote Dictionary Server,即远程词典服务器

Redis 是用 C 语言开发的一个开源的高性能键值对(key-value)数据库。

Redis 是一个基于内存的键值型 NoSQL 数据库


特征

  • 键值(key-value)型,value 支持多种不同数据结构,功能丰富
  • 单线程,每个命令具备原子性
  • 低延迟,速度快(基于内存、IO 多路复用、良好的编码)
  • 支持数据持久化
  • 支持主从集群、分片集群
  • 支持多语言客户端

1.3.安装 Redis


大多数企业都是基于 Linux 服务器来部署项目,而且 Redis 官方也没有提供 Windows 版本的安装包。

因此此次课程中我们会基于 Linux 系统来安装 Redis。此处选择的 Linux 版本为 CentOS 7

Redis 的官方网址https://redis.io/


1.3.1.安装 Redis 依赖


  • Redis 是基于 C 语言编写的,因此首先需要安装 Redis 所需要的 gcc 依赖
yum install -y gcc tcl

1.3.2.上传安装包并解压


  • 将课前资料提供的 Redis 安装包(redis-6.2.6.tar.gz) 上传到虚拟机的任意目录,之后进行解压操作

我这里是解压到了 /usr/local/src 目录

tar -xzf redis-6.2.6.tar.gz -C /usr/local/src
  • 进入 redis 目录之后就运行编译命令
cd redis-6.2.6/
make && make install

如果没有出错,应该就安装成功了。

默认的安装路径是在 /usr/local/bin 目录下

在这里插入图片描述

该目录默认配置到环境变量,因此可以在任意目录下运行这些命令。

  • redis-cli:是 redis 提供的 命令行客户端
  • redis-server:是 redis服务端启动脚本
  • redis-sentinel:是 redis哨兵启动脚本

1.3.3.Redis 默认启动


Redis 的启动方式有很多种,例如:默认启动、指定配置启动、开机自启。


安装完成后,在任意目录输入 redis-server 命令即可启动 Redis

redis-server

1.3.4.Redis 指定配置启动


如果要让 Redis 以 后台方式 启动,则必须修改 Redis 配置文件

这个就在我们之前解压的 redis 的安装包下(/usr/local/src/redis-6.2.6),名字叫 redis.conf

 cd /usr/local/src/redis-6.2.6/

在这里插入图片描述

我们先将这个配置文件备份一份

cp redis.conf redis.conf.bck

然后修改 redis.conf 文件中的一些配置(vim redis.conf

# 允许访问的地址,默认是 127.0.0.1,会导致只能在本地访问。
# 修改为 0.0.0.0 则可以在任意 IP 访问,生产环境不要设置为 0.0.0.0
bind 0.0.0.0 

# 守护进程,修改为 yes 后即可后台运行
daemonize yes 

# 密码,设置后访问 Redis 必须输入密码
requirepass 123321

Redis 的其它常见配置

# 监听的端口
port 6379

# 工作目录,默认是当前目录,也就是运行 redis-server 时的命令,日志、持久化等文件会保存在这个目录
dir .

# 数据库数量,设置为 1,代表只使用 1 个库,默认有 16 个库,编号 0~15
databases 1

# 设置 redis 能够使用的最大内存
maxmemory 512mb

# 日志文件,默认为空,不记录日志,可以指定日志文件名
logfile "redis.log"

redis.conf 中的信息是非常多的,可能不太在该文件里容易找到上述字段。

在 vim 下,可以先按住 ESC 键,之后再使用指令 / 你想要搜索的字段 查找上述字段。

配置完成之后就可以启动 redis 了(此时是按照配置文件来运行的)

redis-server /usr/local/src/redis-6.2.6/redis.conf

可以使用如下命令查看 redis 服务是否正常运行

ps -ef | grep redis

关闭 redis 服务的话,则是可以使如下命令

kill -9 查找到的服务的进程id

在这里插入图片描述


1.3.5.Redis 开机自启


我们也可以通过配置来实现开机自启。


首先,新建一个系统服务文件

vim /etc/systemd/system/redis.service

内容如下

[Unit]
Description=redis-server
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /usr/local/src/redis-6.2.6/redis.conf
PrivateTmp=true

[Install]
WantedBy=multi-user.target

然后重载系统服务

systemctl daemon-reload

现在,我们可以用下面这组命令来操作 redis 了(在进行下面的操作前请先使用 kill -9 终止之前的 redis 进程)

# 启动
systemctl start redis

# 停止
systemctl stop redis

# 重启
systemctl restart redis

# 查看状态
systemctl status redis

执行下面的命令,可以让 redis 开机自启

systemctl enable redis

1.4.Redis 客户端


安装完成 Redis,我们就可以操作 Redis,实现数据的 CRUD 了。

这需要用到 Redis 客户端,包括:命令行客户端、图形化桌面客户端、编程客户端


1.4.1.Redis 命令行客户端


Redis 安装完成后就自带了命令行客户端:redis-cli,使用方式如下:

redis-cli [options] [commonds]

其中常见的 options 有:

  • -h 127.0.0.1:指定要连接的 Redis 节点的 IP 地址,默认是 127.0.0.1 (即本机)
  • -p 6379:指定要连接的 Redis 节点的端口,默认是 6379
  • -a 123321:指定 Redis 的访问密码

其中的 commonds 就是 Redis 的操作命令,例如:

  • ping:与 Redis 服务端做心跳测试,服务端正常会返回 pong

不指定 commond 时,会进入 redis-cli 的交互控制台

在这里插入图片描述


1.4.2.图形化桌面客户端


GitHub 上的大神编写了 Redis 的图形化桌面客户端,地址:https://github.com/uglide/RedisDesktopManager

不过该仓库提供的是 RedisDesktopManager 的源码,并未提供 windows 安装包。

在下面这个仓库可以找到安装包:https://github.com/lework/RedisDesktopManager-Windows/releases

在这里插入图片描述


  1. 安装

在课前资料中可以找到 Redis 的图形化桌面客户端 rdm-2021.9.zip

解压缩后,运行安装程序即可安装(在 Windows 系统上操作,安装过程非常简单)

安装完成后,在安装目录下找到 rdm.exe 文件,再双击该文件即可运行

在这里插入图片描述


  1. 连接

点击左上角的 连接到 Redis 服务器 按钮,再在弹出的窗口中填写 Redis 服务信息

在点击”确定”按钮后,在左侧菜单会出现一个链接,点击链接即可建立连接了。

在这里插入图片描述


Redis 默认有 16 个仓库,编号从 0 至 15。

通过配置文件可以设置仓库数量,但是不超过 16,并且不能自定义仓库名称。

如果是基于 redis-cli 连接 Redis 服务,可以通过 select 命令来选择数据库。

# 选择 0号库
select 0

2.Redis 的常用命令


2.1.Redis 的数据结构


Redis 是一个 key-value 的数据库,key 一般是 String 类型,不过 value 的类型多种多样

在这里插入图片描述

Redis 的 key-value 的种类是非常多的,远远不止上面的几种类型。

Redis 为了方便我们学习,将操作不同数据类型的命令也做了分组

我们在官网( https://redis.io/commands )上可以查看到不同的命令

我们也可以在 Redis 的客户端使用 help 命令来查看相关信息(当然,官网的信息更详细)

在这里插入图片描述


2.2.Redis 的常用命令


通用指令是对任何数据类型都可以适用的指令。


常见的指令有:

  • KEYS:查看符合模板的所有 key(不建议在生产环境的设备上使用
  • DEL:删除一个指定的 key
  • EXISTS:判断 key 是否存在
  • EXPIRE:给一个 key 设置有效期(默认单位是秒),有效期到期时该 key 会被自动删除
  • TTL:查看一个 key 的剩余有效期(-1 代表永久有效,-2 代表 key 已经被删除)
  • 通过 help [command] 可以查看一个命令的具体用法,例如:
    在这里插入图片描述
    help @generic
    help @string
    help @hash
    ... ...
    

set name 123
set name1 1231
set name2 1232

get name
keys *
keys name
keys *name*
del name
exists name 
exists name1
exists name1 name2
expire age 10

ttl age

2.3.String 类型


String 类型,也就是字符串类型,是 Redis 中最简单的存储类型。

其 value 是字符串。不过根据字符串的格式不同,又可以分为 3 类:

  • string:普通字符串
  • int:整数类型,可以做自增、自减操作
  • float:浮点类型,可以做自增、自减操作
  • 不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。
  • 字符串类型的最大空间不能超过 512m。
KEY VALUE
msg Hello World
num 10
score 92.5

String 的常见命令有:

  • SET添加或者修改已经存在的一个 String 类型的键值对。

  • GET:根据 key 获取 String 类型的 value

  • MSET:批量添加多个 String 类型的键值对

  • MGET:根据多个 key 获取多个 String 类型的 value

  • INCR:让一个整型的 key 自增 1

  • INCRBY:让一个整型的 key 自增并指定步长

    例如:incrby num 2 让 num 值自增 2

  • INCRBYFLOAT:让一个浮点类型的数字自增并指定步长

  • SETNX:添加一个 String 类型的键值对,前提是这个 key 不存在,否则不执行

    setnx name WangWu 效果等同于 set name WangWu nx

  • SETEX:添加一个 String 类型的键值对,并且指定有效期

    setex name 10 Jack 效果等同于 set name Jack ex 10


例1

mset test1 JoJo test2 Dio testNum 111

mget test1 testNum
incr testNum

incrby testNum 3
incrby testNum -5
set score 1.1

incrbyfloat score 0.5

get score
setnx score 1.1

setnx score2 1.2

mget score score2

思考:Redis 没有类似 MySQL 中的 Table 的概念,我们该如何区分不同类型的 key 呢?

例如这种需要 存储用户、商品信息到 redis,有一个用户 id 是 1,有一个商品 id 恰好也是 的情况。


Redis 的 key 允许有多个单词形成层级结构,多个单词之间用 : 隔开,格式如下:

项目名:业务名:类型:id

这个格式并非固定,也可以根据自己的需求来删除或添加词条。

例如我们的项目名称叫 heima,有 user 和 product 两种不同类型的数据,我们可以这样定义 key:

  • user 相关的 key:heima:user:1
  • product 相关的 key:heima:product:1

如果 Value 是一个 Java 对象,例如一个 User 对象,则可以将对象序列化JSON 字符串后存储

KEY VALUE
heima:user:1 {"id":1, "name":"Jack", "age":21}
heima:product:1 {"id":1, "name":"小米15", "price":4399}

例2

set heima:user:1 '{"id":1, "name":"Jack", "age": 21}'
set heima:user:2 '{"id":2, "name":"Rose", "age": 18}'
set heima:product:1 '{"id":1, "name":"小米11", "price": 4999}'
set heima:product:2 '{"id":2, "name":"荣耀6", "price": 2999}'

此时使用 keys * 查找所有键,发现并没有什么区别

但是使用我们之前下载过的图形化界面 RedisDesktopManager 就可以发现这种内容的键的特殊之处了

在这里插入图片描述


小结

  • String 类型的三种格式:字符串、int、float

  • Redis 的 key 的格式:[项目名]:[业务名]:[类型]:[id](仅供参考)


2.4.Hash 类型


Hash 类型,也叫散列,其 value 是一个无序字典,类似于 Java 中的 HashMap 结构。

String 结构是将对象序列化为 JSON 字符串后存储,当需要修改对象某个字段时很不方便。

Hash 结构可以将对象中的每个字段独立存储,可以针对单个字段做 CRUD

KEY VALUE
field value
heima:user:1 name Jack
age 21
heima:user:2 name Rose
age 18

Hash 的常见命令有:

  • HSET key field value添加或者修改 hash 类型 key 的 field 的值
  • HGET key field:获取一个 hash 类型 key 的 field 的值
  • HMSET:批量添加多个 hash 类型 key 的 field 的值
  • HMGET:批量获取多个 hash 类型 key 的 field 的值
  • HGETALL:获取一个 hash 类型的 key 中的所有的 field 和 value
  • HKEYS:获取一个 hash 类型的 key 中的所有的 field
  • HVALS:获取一个 hash 类型的 key 中的所有的 value
  • HINCRBY:让一个 hash 类型 key 的字段值自增并指定步长
  • HSETNX:添加一个 hash 类型的 key 的 field 值,前提是这个 field 不存在,否则不执行

hset heima:user:3 name Lucy
hset heima:user:3 age 22

hset heima:user:3 age 33
hmset heima:user:4 name LiMei age 20 gender man
 
hmget heima:user:4 name age gender
 
hgetall heima:user:4
hkeys heima:user:4

hvals heima:user:4
hincrby heima:user:4 age 2
hsetnx heima:user:3 gender woman

2.5.List 类型


Redis 中的 List 类型与 Java 中的 LinkedList 类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索

特征也与 LinkedList 类似:

  • 有序
  • 元素可以重复
  • 插入和删除快
  • 查询速度一般

常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。


List 的常见命令有:

  • LPUSH key element ... :向列表左侧插入一个或多个元素
  • LPOP key移除返回列表左侧的第一个元素,没有则返回 nil
  • RPUSH key element ...:向列表右侧插入一个或多个元素
  • RPOP key移除返回列表右侧的第一个元素
  • LRANGE key star end:返回一段角标范围内的所有元素
  • BLPOPBRPOP:与 LPOPRPOP 类似,只不过在没有元素时 等待 指定时间,而不是直接返回 nil

在这里插入图片描述


lpush users 1 2 3

rpush users 4 5 6
lpop users 1

rpop users 1
lrange users 1 2

在这里插入图片描述


思考

  • 如何利用 List 结构模拟一个栈(先进后出)?
    • 入口和出口在同一边
  • 如何利用 List 结构模拟一个队列(先进先出)?
    • 入口和出口在不同边
  • 如何利用 List 结构模拟一个阻塞队列?
    • 入口和出口在不同边
    • 出队时采用 BLPOPBRPOP

2.6.Set 类型


Redis 的 Set 结构与 Java 中的 HashSet 类似,可以看做是一个 value 为 null 的 HashMap。

因为也是一个 hash 表,因此具备与 HashSet 类似的特征

  • 无序
  • 元素不可重复
  • 查找快
  • 支持 交集并集差集 等功能

String 的常见命令有

  • SADD key member ...:向 set 中添加一个或多个元素
  • SREM key member ...:移除 set 中的指定元素
  • SCARD key: 返回 set 中元素的个数
  • SISMEMBER key member:判断一个元素是否存在于 set 中
  • SMEMBERS:获取 set 中的所有元素
  • SINTER key1 key2 ...:求 key1 与 key2 的交集
  • SDIFF key1 key2 ...:求 key1 与 key2 的差集
  • SUNION key1 key2 ...:求 key1 和 key2 的并集

sadd s1 a b c

smembers s1

srem s1 a

scard s1

Set 命令练习

将下列数据用 Redis 的 Set 集合来存储

  • 张三(zs)的好友有:李四、王五、赵六:sadd zs LiSi WangWu ZhaoLiu
  • 李四(ls)的好友有:王五、麻子、二狗:sadd ls WangWu MaZi ErGou

利用 Set 的命令实现下列功能

  • 计算张三的好友有几人:scard zs
  • 计算张三和李四有哪些共同好友:sinter zs ls
  • 查询哪些人是张三的好友却不是李四的好友:sdiff zs ls,输出的结果是 ZhaoLiuLiSi
  • 查询张三和李四的好友总共有哪些人:sunion zs ls
  • 判断李四是否是张三的好友:sismember zs LiSi
  • 判断张三是否是李四的好友:sismember ls ZhangSan
  • 将李四从张三的好友列表中移除:srem zs LiSi

2.7 .SortedSet 类型


Redis 的 SortedSet 是一个可排序的 set 集合,与 Java 中的 TreeSet 有些类似,但底层数据结构却差别很大。

TreeSet 的底层是基于 红黑树 来实现的。

SortedSet 中的每一个元素都带有一个 score 属性,可以基于 score 属性对元素排序,底层的实现是一个 跳表(SkipList)+ hash 表

SortedSet 具备下列特性:

  • 可排序
  • 元素不重复
  • 查询速度快

因为 SortedSet 的可排序特性,经常被用来实现排行榜这样的功能。


SortedSet 的常见命令有:

  • ZADD key score member:添加一个或多个元素到 sorted set ,如果已经存在则更新其 score 值
  • ZREM key member:删除 sorted set 中的一个指定元素
  • ZSCORE key member:获取 sorted set 中的指定元素的 score 值
  • ZRANK key member:获取 sorted set 中的指定元素的排名
  • ZCARD key:获取 sorted set中的元素个数
  • ZCOUNT key min max:统计 score 值在给定范围内的所有元素的个数(闭区间)
  • ZINCRBY key increment member:让 sorted set 中的指定元素自增,步长为指定的 increment 值
  • ZRANGE key min max:按照 score 排序后,获取指定排名范围内的元素(闭区间)
  • ZRANGEBYSCORE key min max:按照 score 排序后,获取指定 score 范围内的元素
  • ZDIFFZINTERZUNION:求差集、交集、并集

注意所有的排名默认都是升序,如果要降序则在命令的 Z 后面添加 REV 即可


SortedSet 命令练习

将班级的下列学生得分存入 Redis 的 SortedSet 中

  • Jack 85, Lucy 89, Rose 82, Tom 95, Jerry 78, Amy 92, Miles 76

    ZADD stus 85 Jack 89 Lucy 82 Rose 95 Tom 78 Jerrry 92 Amy 76 Miles
    

    在这里插入图片描述

并实现下列功能

  • 删除 Tom 同学:ZREM stus Tom
  • 获取 Amy 同学的分数:zscore stus Amy
  • 获取 Rose 同学的排名:zrank stus Rose(升序)、zrevrank stus Rose(降序)
  • 查询 80 分以下有几个学生:zcount stus 0 80
  • 给 Amy 同学加 2 分:zincrby stus 2 Amy
  • 查出成绩前 3 名的同学:zrevrange stus 0 2
  • 查出成绩 80 分以下的所有同学:zrangebyscore stus 0 80

3.Redis 的 Java 客户端


3.1.客户端对比


在 Redis 官网中提供了各种语言的客户端,地址:https://redis.io/clients


在这里插入图片描述


在这里插入图片描述


3.1.Jedis


3.2.Jedis 入门


Jedis 使用的基本步骤

  1. 引入依赖
  2. 创建 Jedis 对象,建立连接
  3. 使用 Jedis,方法名与 Redis 命令一致

  • 项目结构我这里使用的是 Idea 软件,用 Maven 方式创建的项目

在这里插入图片描述


  • 导入依赖pom.xml
<!-- Jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.7.0</version>
</dependency>

<!-- 单元测试 -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.7.0</version>
    <scope>test</scope>
</dependency>

  • 具体代码src/test/java/JedisTest.java
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;

import java.util.Map;

public class JedisTest {
    // 创建 Jedis 对象
    private Jedis jedis;

    @BeforeEach
    void setUp() {
        // 建立连接
        jedis = new Jedis("192.168.2.12", 6379);
        // 设置密码
        jedis.auth("123321");
        // 选择库
        jedis.select(0);
    }

    @AfterEach
    void tearDown() {
        if (jedis != null) {
            jedis.close();
        }
    }

    @Test
    void testString() {
        // 存入数据
        String result = jedis.set("name", "虎哥");
        System.out.println("result = " + result);

        // 获取数据
        String name = jedis.get("name");
        System.out.println("name = " + name);
    }

    @Test
    void testHash() {
        jedis.hset("user:1","name","Jack");
        jedis.hset("user:1","age","22");

        Map<String, String> map = jedis.hgetAll("user:1");
        System.out.println(map);
    }
}

3.2.Jedis 连接池


Jedis 本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗。

因此我们推荐大家使用 Jedis 连接池代替 Jedis 的直连方式。


src/main/java/com/heima/jedis/util/JedisConnectionFactory.java

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisConnectionFactory {
    private static final JedisPool jedisPool;

    static {
        // 配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();

        poolConfig.setMaxTotal(8);
        poolConfig.setMaxIdle(8);
        poolConfig.setMaxIdle(0);
        poolConfig.setMaxWaitMillis(1000);

        //创建连接池对象
        jedisPool = new JedisPool(
                poolConfig, "192.168.150.101", 6379, 1000, "123321"
        );
    }

    public static Jedis getJedis() {
        return jedisPool.getResource();
    }
}

此时,我们便可以使用 Jedis 连接池来代替 Jedis 的直连方式了。

src/test/java/JedisTest.java

@BeforeEach
void setUp() {
    // 建立连接
    jedis = JedisConnectionFactory.getJedis();
    // ... ...
}

3.3.SpringDataRedis


3.3.1.简单介绍


SpringDataSpring 中数据操作的模块,包含对各种数据库的集成,其中对 Redis 的集成模块就叫做 SpringDataRedis

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

  • 提供了对不同 Redis 客户端的整合(Lettuce 和 Jedis)
  • 提供了 RedisTemplate 统一 API 来操作 Redis
  • 支持 Redis 的发布订阅模型
  • 支持 Redis 哨兵和 Redis 集群
  • 支持基于 Lettuce 的响应式编程
  • 支持基于 JDK、JSON、字符串、Spring 对象的数据序列化及反序列化
  • 支持基于 Redis 的 JDKCollection 实现

SpringDataRedis 中提供了 RedisTemplate 工具类,其中封装了各种对 Redis 的操作。

并且将不同数据类型的操作 API 封装到了不同的类型中

API 返回值类型 说明
redisTemplate.opsForValue() ValueOperations 操作 String 类型数据
redisTemplate.opsForHash() HashOperations 操作 Hash 类型数据
redisTemplate.opsForList() ListOperations 操作 List 类型数据
redisTemplate.opsForSet() SetOperations 操作 Set 类型数据
redisTemplate.opsForZSet() ZSetOperations 操作 SortedSet 类型数据
redisTemplate 通用的命令

3.3.2.RedisTemplate 快速入门


SpringBoot 已经提供了对 SpringDataRedis 的支持,使用非常简单。

  1. 引入 spring-boot-starter-data-redis 依赖
  2. application.yml 配置 Redis 信息
  3. 注入 RedisTemplate

我这里使用的是 Idea 软件,用 Spring Initializr 创建方式创建的项目,SpringBoot 的版本是 2.5.7

  • 项目结构

  1. 引入依赖pom.xml

    <!-- Redis 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
    <!-- 连接池依赖 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
    </dependency>
    
  2. 配置文件src/main/resources/application.yaml

    spring:
      redis:
        host: 192.168.150.101
        port: 6379
        password: 123321
        lettuce:
          pool:
            max-active: 8     # 最大连接
            max-idle: 8       # 最大空闲连接
            min-idle: 0       # 最小空闲连接
            max-wait: 100ms   # 连接等待时间
    
  3. 注入 RedisTemplatesrc/test/java/com/heima/RedisDemoApplicationTests.java

    @Autowired
    private RedisTemplate redisTemplate;
    
  4. 编写测试src/test/java/com/heima/RedisDemoApplicationTests.java

    @SpringBootTest
    class RedisDemoApplicationTests {
        @Autowired
        private RedisTemplate redisTemplate;
    
        @Test
        void testString() {
            // 写入一条 String 数据
            redisTemplate.opsForValue().set("name", "虎哥");
    
            // 获取 String 数据
            Object name = redisTemplate.opsForValue().get("name");
            System.out.println("name = " + name);
        }
    }
    

3.3.3.RedisSerializer


RedisTemplate 可以接收任意 Object 作为值写入 Redis。

但是 RedisTemplate 在写入前,会把 Object 序列化为字节形式,默认是采用 JDK 序列化,得到的结果是这样的:

在这里插入图片描述

这样会带来两个缺点:可读性差、内存占用较大。


我们可以自定义 RedisTemplate 的序列化方式,代码如下

src/main/java/com/heima/redis/config/RedisConfig.java

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
        // 创建 RedisTemplate 对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建 JSON 序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置 Key 的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置 Value 的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}

此外,还需要在 pom.xml 文件里加入一个新的依赖坐标

<!-- Jackson 依赖 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

此时,我们可以在 src/main/java/com/heima/redis/pojo 目录下创建一个新的 User.java 文件

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String name;
    private Integer age;
}

当然,既然使用到了 Lombok 插件,自然又要导入新的依赖坐标

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

最后,我们可以编写一个单元测试类

src/test/java/com/heima/tests/RedisTest_1.java我自己又在 test 目录下创建了一个 tests 目录

@SpringBootTest
public class RedisTest_1 {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Test
    void testSaveUser() {
        // 写入数据
        redisTemplate.opsForValue().set("user:100", new User("虎哥", 33));

        // 获取数据
        User user = (User) redisTemplate.opsForValue().get("user:100");
        System.out.println("User 对象:" + user);
    }
}

运行测试类中的 testSaveUser() 之后的结果就是这样

在这里插入图片描述

为了在反序列化时知道对象的类型,JSON 序列化器会将类的 class 类型写入 json 结果中,存入 Redis,会带来额外的内存开销。


3.3.4.StringRedisTemplate


为了节省内存空间,我们并不会使用 JSON 序列化器来处理 value,而是统一使用 String 序列化器。

String 序列化器要求只能存储 String 类型的 key 和 value。

当需要存储 Java 对象时,手动完成对象的序列化和反序列化。

在这里插入图片描述


Spring 默认提供了一个 StringRedisTemplate 类,它的 key 和 value 的序列化方式默认就是 String 方式。

省去了我们自定义 RedisTemplate 的过程

src/test/java/com/heima/tests/RedisStringTests.java

@SpringBootTest(classes = RedisDemoApplication.class)
class RedisStringTests {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /* StringRedisTemplate 操作 String 类型 */
    @Test
    void testString() {
        // 写入一条 String 数据
        stringRedisTemplate.opsForValue().set("name", "雾山五行");
        // 获取 String 数据
        Object name = stringRedisTemplate.opsForValue().get("name");
        System.out.println("name = " + name);
    }

    /* StringRedisTemplate 操作 Object 类型 */
    private static final ObjectMapper mapper = new ObjectMapper();

    @Test
    void testSaveUser() throws JsonProcessingException {
        // 之前 redisTemplate 会帮我们自动序列化,现在需要我们自己手动序列化了

        // 创建对象
        User user = new User("吉良吉影", 33);
        // [手动-序列化]
        String json = mapper.writeValueAsString(user);
        // 写入数据
        stringRedisTemplate.opsForValue().set("user:200", json);
        // 获取数据
        String jsonUser = stringRedisTemplate.opsForValue().get("user:200");
        // [手动-反序列化]
        User user1 = mapper.readValue(jsonUser, User.class);
        System.out.println("user1 = " + user1);
    }
    
    /* StringRedisTemplate 操作 Hash 类型 */
    @Test
    void testHash() {
        stringRedisTemplate.opsForHash().put("user:400", "name", "虎哥");
        stringRedisTemplate.opsForHash().put("user:400", "age", "21");
        
        Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:400");
        System.out.println("entries = " + entries);
    }
}

  • RedisTemplate 的两种序列化实践方案
    • 方案一
      • 自定义 RedisTemplate
      • 修改 RedisTemplate 的序列化器为 GenericJackson2JsonRedisSerialize
    • 方案二
      • 使用 StringRedisTemplate
      • 写入 Redis 手动把对象序列化为 JSON
      • 读取 Redis 手动把读取到的 JSON 反序列化为对象

当然诸位若对 SpringDataRedis 感兴趣的话也可以看看我之前写的博客【瑞吉外卖⑩】Linux 粗略学习 & Redis 粗略学习


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis学习笔记①基础篇_Redis快速入门 的相关文章

  • 使用 JDBC 获取 Oracle 11g 的最后插入 ID

    我是使用 Oracle 的新手 所以我将放弃之前已经回答过的内容这个问题 https stackoverflow com questions 3131064 get id of last inserted record in oracle
  • 获取文件的锁

    我想在对特定文件开始 threo read 时获取文件上的锁定 以便其他应用程序无法读取已锁定的文件并希望在线程终止时释放锁定文件 您可以获得一个FileLock https docs oracle com javase 8 docs ap
  • Reactive Spring 不支持 HttpServletRequest 作为 REST 端点中的参数?

    我创建了一个 RestController 如下所示 RestController public class GreetingController RequestMapping value greetings method RequestM
  • FileNotFoundException - Struts2 文件上传

    Strange FileNotFoundException使用Struts2上传文件时 这是 JSP 的一部分
  • 为什么Iterator接口没有add方法

    In IteratorSun 添加了remove 方法来删 除集合中最后访问的元素 为什么没有add方法来向集合中添加新元素 它可能对集合或迭代器产生什么样的副作用 好的 我们开始吧 设计常见问题解答中明确给出了答案 为什么不提供 Iter
  • 从休眠乐观锁定异常中恢复

    我有一个这样的方法 Transactional propagation Propagation REQUIRES NEW public void doSomeWork Entity entity dao loadEntity do some
  • Eclipse - 安装新的 JRE (Java SE 8 1.8.0)

    我正在尝试安装 Java 8 到目前为止我所做的 安装最新版本的 Eclipse 下载并安装 Java SE 运行时环境 8http www oracle com technetwork java javase downloads jre8
  • 用于缓存的 Servlet 过滤器

    我正在创建一个用于缓存的 servlet 过滤器 这个想法是将响应主体缓存到memcached 响应正文由以下方式生成 结果是一个字符串 response getWriter print result 我的问题是 由于响应正文将不加修改地放
  • 如何从日期中删除毫秒、秒、分钟和小时[重复]

    这个问题在这里已经有答案了 我遇到了一个问题 我想比较两个日期 然而 我只想比较年 月 日 这就是我能想到的 private Date trim Date date Calendar calendar Calendar getInstanc
  • 在 Clojure 中解压缩 zlib 流

    我有一个二进制文件 其内容由zlib compress在Python上 有没有一种简单的方法可以在Clojure中打开和解压缩它 import zlib import json with open data json zlib wb as
  • 如何停止执行的 Jar 文件

    这感觉像是一个愚蠢的问题 但我似乎无法弄清楚 当我在 Windows 上运行 jar 文件时 它不会出现在任务管理器进程中 我怎样才能终止它 我已经尝试过 TASKKILL 但它对我也不起作用 On Linux ps ef grep jav
  • IntelliJ 组织导入

    IntelliJ 是否具有类似于 Eclipse 中的组织导入功能 我拥有的是一个 Java 文件 其中多个类缺少导入 例子 package com test public class Foo public Map map public J
  • 使用Java绘制维恩图

    我正在尝试根据给定的布尔方程绘制维恩图 例如 a AND b AND c我想在 Android 手机上执行此操作 因此我需要找到一种使用 Java 来执行此操作的方法 我找到了一个完美的小部件 它可以完成我在这方面寻找的一切布尔代数计算器
  • 禁用 Android 菜单组

    我尝试使用以下代码禁用菜单组 但它不起作用 菜单项仍然启用 你能告诉我出了什么问题吗 资源 菜单 menu xml menu menu
  • 如何处理 StaleElementReferenceException

    我正在为鼠标悬停工作 我想通过使用 for 循环单击每个链接来测试所有链接的工作条件 在我的程序中 迭代进行一次 而对于下一次迭代 它不起作用并显示 StaleElementReferenceException 如果需要 请修改代码 pub
  • 替换文件中的字符串

    我正在寻找一种方法来替换文件中的字符串而不将整个文件读入内存 通常我会使用 Reader 和 Writer 即如下所示 public static void replace String oldstring String newstring
  • Java 的 PriorityQueue 与最小堆有何不同?

    他们为什么命名PriorityQueue如果你不能插入优先级 它看起来与堆非常相似 有什么区别吗 如果没有区别那为什么叫它PriorityQueue而不是堆 默认的PriorityQueue是用Min Heap实现的 即栈顶元素是堆中最小的
  • 记录类名、方法名和行号的性能影响

    我正在我的 java 应用程序中实现日志记录 以便我可以调试应用程序投入生产后可能出现的潜在问题 考虑到在这种情况下 人们不会奢侈地使用 IDE 开发工具 以调试模式运行事物或单步执行完整代码 因此在每条消息中记录类名 方法名和行号将非常有
  • 将对象从手机共享到 Android Wear

    我创建了一个应用程序 在此应用程序中 您拥有包含 2 个字符串 姓名和年龄 和一个位图 头像 的对象 所有内容都保存到 sqlite 数据库中 现在我希望可以在我的智能手表上访问这些对象 所以我想实现的是你可以去启动 启动应用程序并向左和向
  • 即使调整大小,如何获得屏幕的精确中间位置

    好的 这个问题有两部分 当我做一个JFrame 并在其上画一些东西 即使我将宽度设置为 400 并使其在一个项目击中它时 当然 允许项目宽度 它会反弹回来 但由于某种原因 它总是偏离屏幕约 10 个像素 有没有办法解决这个问题 或者我只需要

随机推荐

  • GameMode问题

    GameMode问题 1 缘由 初始化了两个关卡 一个登录关卡 一个内容关卡 配置了两个GameMode 分别在关卡中设置好了GameMode 通过调用OpenLevel实现关卡跳转 如下图 然 运行过程中 关卡完成了跳转 进入内容关卡后G
  • MusicGen一键音乐风格迁移

    想象一下 您可以随心所欲地创作轻快的乡村曲风 缠绵的蓝调 史诗般的管弦乐 视频BGM创作之路上 再也不会有任何阻碍 01 什么是MusicGen Meta MusicGen建立在强大的Transformer模型的基础上 追随ChatGPT等
  • Pcshare远控源码偏重分析(一)

    0x00背景 PcShare是一款功能强大的远程管理软件 可以在内网 外网任意位置随意管理需要的远程主机 该软件是由国内安全爱好者无可非议开发 在当时这款远控在大家应该比较熟悉了 VC编译器调出来的的小体积全功能木马 相比Delphi的灰鸽
  • Linux权限

    一 Linux权限的概念 Linux下有两种用户 超级用户 root 普通用户 超级用户 可以再linux系统下做任何事情 不受限制 普通用户 在linux下做有限的事情 超级用户的命令提示符是 普通用户的命令提示符是 1 1 用户间的切换
  • 最优清零方案python(蓝桥杯)

    1 问题描述 给定一个长度为 N 的数列 A1 A2 AN 现在小蓝想通过若干次操作将 这个数列中每个数字清零 每次操作小蓝可以选择以下两种之一 选择一个大于 0 的整数 将它减去 1 选择连续 K 个大于 0 的整数 将它们各减去 1 小
  • 【SSM】DispatcherServlet详解

    功能 SpringMVC的核心就是DispatcherServlet DispatcherServlet实质也是一个HttpServlet DispatcherSevlet负责将请求分发 所有的请求都有经过它来统一分发 大致看下Spring
  • Maven引入本地jar包的使用方法

    关于下载配置Maven的过程我这里就不多说了 网上可以自行查询 我简述一下关于jar如果直接下载到本地之后 怎么整合到自己的maven工程呢 方式挺多的 下面列举四种方式 1 上传到maven中心仓库 https oss sonatype
  • 显示web服务器登陆,web服务器登陆界面

    web服务器登陆界面 内容精选 换一换 云解析服务支持为域名快速添加网站解析 通过该功能可以简化解析记录的配置 包含如下两种场景 网站解析至IP地址 为域名的主域名和子域名分别添加一条A类型记录集网站解析至另一域名 为域名的主域名和子域名分
  • tensorRT 分类模型构建与推理

    tensorRT分类模型构建与推理示例代码classifier cpp tensorRT include 编译用的头文件 include
  • 第三方钩子 MouseKeyHook 监控鼠标键盘事件

    public partial class Form4 Form private static IKeyboardMouseEvents m GlobalHook public Form4 InitializeComponent privat
  • 大数据实训报告_重磅|数据酷客?大数据精准营销综合实训软件平台隆重发布...

    北京大数据研究院博雅大数据学院第二套大数据专业综合实训产品 数据酷客 大数据精准营销综合实训软件平台隆重发布 大数据精准营销综合实训软件平台 平台介绍 首先 通过对海量结构化数据和非结构化文本数据的深度分析和挖掘 构建全方位的客户标签体系
  • MATLAB打开后一直在初始化,或者初始化很慢问题

    问题描述 遇到MATLAB启动较慢 进入主界面后 一直停留在 正在初始化 的状态 浪费很多时间 这种问题大多是因为MATLAB软件在启动时寻找本机的许可证或者是设置了 LM LICENSE FILE 的环境变量 这个变量告诉 MATLAB
  • 软件工程毕业设计选题java_软件工程毕业设计选题

    2020 01 24 东哥毕设 1122 1 分管理员和用户 国资处 三个角色 国资处这个角色一定要有 管理员 1 对用户进行增删改查 2 对设备信息管理 基本信息里面需要包括设备存放地址这个字段 这里必须有 一个状态字段 管理员添加了设备
  • 价值创造链路及经营计划

    价值创造过程最主要的环节是建立链接 北京万柳书院在网上热议 其背后是人与人的大量链接 近期热议的湖南卫视春晚亦如是 这种链接为价值的设计 沟通 传递创造条件 企业以客户为中心设计产品 往大了说是企业的生存根本 往小了说则是经营技巧 产品就是
  • TCP协议(三次握手)

    TCP Transmission Control Protocol 协议的全称是传输控制协议 它负责为不同终端系统的应用进程之间提供面向连接的通信服务 即TCP协议能够对自己提供的连接实施控制 它是一种可靠的传输层协议 一 TCP协议简介
  • 西门子PPI通讯协议

    过硬件和软件侦听的方法 分析PLC内部固有的PPI通讯协议 然后上位机采用VB编程 遵循PPI通讯协议 读写PLC数据 实现人机操作任务 这种通讯方法 与一般的自由通讯协议相比 省略了PLC的通讯程序编写 只需编写上位机的通讯程序资源S7
  • 磁环相关的计算公式

    磁环相关的计算公式 公式来源 收集于各大网站 公式仅供参考 如有错误或不全的 欢迎留言指出 通过查磁环手册或咨询供应商可知的固有量 磁环外径 D 单位mm 磁环内径 d 单位mm 磁环高度 h 单位mm 磁环芯材磁导率 u 可推导的量 导磁
  • Java 获取两个List的交集和差集,以及应用场景

    背景介绍 在实际项目中 特别是一些管理后台类的项目 会遇到底层数据是按照一对多关系的数据表存储的管理界面 列表页是一对多关系中一对应的数据列表 二级的详情页中是一对多关系中多对应的多条数据展示 通常二级页面是能够增 删 改数据的编辑页面 在
  • 使用 pymysql 操作MySQL数据库

    安装PyMySQL PyMySQL是一个Python编写的MySQL驱动程序 让我们可以用Python语言操作MySQL数据库 首先 使用pip安装PyMySQL pip install PyMySQL 使用PyMySQL 简单使用 如果有
  • Redis学习笔记①基础篇_Redis快速入门

    若文章内容或图片失效 请留言反馈 部分素材来自网络 若不小心影响到您的利益 请联系博主删除 资料链接 https pan baidu com s 1189u6u4icQYHg 9 7ovWmA 提取码 eh11 在线视频 https www