01、Redis入门:数据类型、基本操作、SpringDataRedis

news2024/9/21 10:40:25

Redis快速入门

Redis的常见命令和客户端使用

1.初识Redis

Redis是一种键值型的NoSql数据库,这里有两个关键字:

  • 键值型

  • NoSql

其中键值型,是指Redis中存储的数据都是以key、value对的形式存储,而value的形式多种多样,可以是字符串、数值、甚至json:

image-20220502190959608

而NoSql则是相对于传统关系型数据库而言,有很大差异的一种数据库。

1.1.认识NoSQL

NoSql可以翻译做Not Only Sql(不仅仅是SQL),或者是No Sql(非Sql的)数据库。是相对于传统关系型数据库而言,有很大差异的一种特殊的数据库,因此也称之为非关系型数据库

1.1.1.结构化与非结构化

传统关系型数据库是结构化数据,每一张表都有严格的约束信息:字段名、字段数据类型、字段约束等等信息,插入的数据必须遵守这些约束:

而NoSql则对数据库格式没有严格约束,往往形式松散,自由。

可以是键值型:

也可以是文档型:

甚至可以是图格式:

1.1.2.关联和非关联

传统数据库的表与表之间往往存在关联,例如外键:

而非关系型数据库不存在关联关系,要维护关系要么靠代码中的业务逻辑,要么靠数据之间的耦合:

{
  id: 1,
  name: "张三",
  orders: [
    {
       id: 1,
       item: {
	 id: 10, title: "荣耀6", price: 4999
       }
    },
    {
       id: 2,
       item: {
	 id: 20, title: "小米11", price: 3999
       }
    }
  ]
}

此处要维护“张三”的订单与商品“荣耀”和“小米11”的关系,不得不冗余的将这两个商品保存在张三的订单文档中,不够优雅。还是建议用业务来维护关联关系。

1.1.3.查询方式

传统关系型数据库会基于Sql语句做查询,语法有统一标准;

而不同的非关系数据库查询语法差异极大,五花八门各种各样。

1.1.4.事务

传统关系型数据库能满足事务ACID的原则。

而非关系型数据库往往不支持事务,或者不能严格保证ACID的特性,只能实现基本的一致性。

1.1.5.总结

除了上述四点以外,在存储方式、扩展性、查询性能上关系型与非关系型也都有着显著差异,总结如下:

  • 存储方式
    • 关系型数据库基于磁盘进行存储,会有大量的磁盘IO,对性能有一定影响
    • 非关系型数据库,他们的操作更多的是依赖于内存来操作,内存的读写速度会非常快,性能自然会好一些
  • 扩展性
    • 关系型数据库集群模式一般是主从,主从数据一致,起到数据备份的作用,称为垂直扩展。
    • 非关系型数据库可以将数据拆分,存储在不同机器上,可以保存海量数据,解决内存大小有限的问题。称为水平扩展。
    • 关系型数据库因为表之间存在关联关系,如果做水平扩展会给数据查询带来很多麻烦

1.2.认识Redis

Redis诞生于2009年全称是Remote Dictionary Server 远程词典服务器,是一个基于内存的键值型NoSQL数据库。

特征

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

作者:Antirez

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

1.3.安装Redis

大多数企业都是基于Linux服务器来部署项目,而且Redis官方也没有提供Windows版本的安装包。因此课程中我们会基于Linux系统来安装Redis.

此处选择的Linux版本为CentOS 7.

1.3.0 Docker安装Redis

docker安装redis 6.2.7 并 远程连接_docker 安装redis6.2.7-CSDN博客

1.3.1.依赖库

Redis是基于C语言编写的,因此首先需要安装Redis所需要的gcc依赖:

yum install -y gcc tcl

1.3.2.上传安装包并解压

然后将课前资料提供的Redis安装包上传到虚拟机的任意目录:

例如,我放到了/usr/local/src 目录:

解压缩:

tar -zxvf redis-6.2.6.tar.gz

解压后:

image-20211211080339076

进入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的启动方式有很多种,例如:

  • 默认启动
  • 指定配置启动
  • 开机自启

1.3.4.默认启动

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

redis-server

如图:

这种启动属于前台启动,会阻塞整个会话窗口,窗口关闭或者按下CTRL + C则Redis停止。不推荐使用。

1.3.5.指定配置启动

如果要让Redis以后台方式启动,则必须修改Redis配置文件,就在我们之前解压的redis安装包下(/usr/local/src/redis-6.2.6),名字叫redis.conf:

image-20211211082225509

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

cp redis.conf redis.conf.bck

然后修改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:

# 进入redis安装目录 
cd /usr/local/src/redis-6.2.6
# 启动
redis-server redis.conf

停止服务:

# 利用redis-cli来执行 shutdown 命令,即可停止 Redis 服务,
# 因为之前配置了密码,因此需要通过 -u 来指定密码
redis-cli -u 123321 shutdown

1.3.6.开机自启

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

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

vi /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了:

# 启动
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.4.3.安装

在课前资料中可以找到Redis的图形化桌面客户端:

解压缩后,运行安装程序即可安装:

安装完成后,在安装目录下找到rdm.exe文件:

双击即可运行:

1.4.4.建立连接

点击左上角的连接到Redis服务器按钮:

在弹出的窗口中填写Redis服务信息:

点击确定后,在左侧菜单会出现这个链接:

点击即可建立连接了。

Redis默认有16个仓库,编号从0至15. 通过配置文件可以设置仓库数量,但是不超过16,并且不能自定义仓库名称。

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

# 选择 0号库
select 0

2.Redis常见命令

Redis是典型的key-value数据库,key一般是字符串,而value包含很多不同的数据类型:

Redis为了方便我们学习,将操作不同数据类型的命令也做了分组,在官网( https://redis.io/commands )可以查看到不同的命令:

不同类型的命令称为一个group,我们也可以通过help命令来查看各种不同group的命令:

接下来,我们就学习常见的五种基本数据类型的相关命令。

2.1.Redis通用命令

通用指令是部分数据类型的,都可以使用的指令,常见的有:

  • KEYS:查看符合模板的所有key
    • 不建议在生产环境设备上使用,因为Redis是单线程的,执行查询的时候会阻塞其他命令,当数据量很大的时候,使用KEYS进行模糊查询,效率很差
  • DEL:删除一个或者多个指定的key
    • 也可以删除多个key,DEL name age,会将name和age都删掉
  • EXISTS:判断key是否存在
    • EXISTS name,如果存在返回1,不存在返回0
  • EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除
    • EXPIRE name 20,给name设置20秒有效期,到期自动删除
  • TTL:查看一个KEY的剩余有效期,如果返回-2代表失效,如果返回-1代表永久
    • TTL name,查看name的剩余有效期,如果未设置有效期,则返回-1

2.2.String类型

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

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

  • string:普通字符串
  • int:整数类型,可以做自增、自减操作
  • float:浮点类型,可以做自增、自减操作

不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型的最大空间不能超过512m.

2.2.1.String的常见命令

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 jackset name jack nx效果一样
  • SETEX:添加一个String类型的键值对,并且指定有效期

    • setex name 10 jackset name jack ex 10效果一样

2.2.2.Key结构

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

例如,需要存储用户、商品信息到redis,有一个用户id是1,有一个商品id恰好也是1,此时如果使用id作为key,那就会冲突了,该怎么办?

我们可以通过给key添加前缀加以区分,不过这个前缀不是随便加的,有一定的规范:

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

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

这个格式并非固定,也可以根据自己的需求来删除或添加词条。这样以来,我们就可以把不同类型的数据区分开了。从而避免了key的冲突问题。

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

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

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

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

KEYVALUE
heima:user:1{“id”:1, “name”: “Jack”, “age”: 21}
heima:product:1{“id”:1, “name”: “小米11”, “price”: 4999}

并且,在Redis的桌面客户端中,还会以相同前缀作为层级结构,让数据看起来层次分明,关系清晰:

2.3.Hash类型

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

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

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

Hash的常见命令有:

  • HSET key field value:添加或者修改hash类型key的field的值

  • HGET key field:获取一个hash类型key的field的值

  • HMSET:批量添加多个hash类型key的field的值

    • 例如:hmset heima:user:1 name java age 12
  • HMGET:批量获取多个hash类型key的field的值

    • 例如:hmget heima:user:1 name age
  • HGETALL:获取一个hash类型的key中的所有的field和value

    • 例如:hgetall heima:user:1
  • HKEYS:获取一个hash类型的key中的所有的field

  • HVALS:获取一个hash类型的key中的所有的value

  • HINCRBY:让一个hash类型key的字段值自增并指定步长

    • 例如:hincrby heima:user:1 age 3
  • HSETNX:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行

2.4.List类型

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

特征也与LinkedList类似:

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

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

List的常见命令有:

  • LPUSH key element … :向列表左侧插入一个或多个元素
  • LPOP key:移除并返回列表左侧的第一个元素,没有则返回nil
  • RPUSH key element … :向列表右侧插入一个或多个元素
  • RPOP key:移除并返回列表右侧的第一个元素
  • LRANGE key star end:返回一段角标范围内的所有元素,包含区间边界
  • BLPOP和BRPOP:与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil
    • 比如:BLPOP user 10代表阻塞10s,如果10s内有元素,返回,如果没有10s后返回nil

总结来讲,LPUSH代表头插,RPUSH代表尾插

image-20240820133205110

2.5.Set类型

Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的HashMap。因为也是一个hash表,因此具备与HashSet类似的特征:

  • 无序

  • 元素不可重复

  • 查找快

  • 支持交集、并集、差集等功能

Set的常见命令有:

  • SADD key member … :向set中添加一个或多个元素
  • SREM key member … : 移除set中的指定元素
  • SCARD key: 返回set中元素的个数
  • SISMEMBER key member:判断一个元素是否存在于set中
  • SMEMBERS:获取set中的所有元素
  • SINTER key1 key2 … :求key1与key2的交集,比如下面就是B,C
  • SDIFF key1 key2 …:求key1与key2的差集,比如下面的,求出就是A
  • SUNION key1 key2 …:求key1与key2的并记,比如下面的,求出就是A,B,C,D

例如两个集合:s1和s2:

求交集:SINTER s1 s2

求s1与s2的不同:SDIFF s1 s2

练习:

  1. 将下列数据用Redis的Set集合来存储:
  • 张三的好友有:李四、王五、赵六

    • sadd zhangsan lisi wangwu zhaoliu
      
  • 李四的好友有:王五、麻子、二狗

    • sadd zhangsan lisi wangwu zhaoliu
      
  1. 利用Set的命令实现下列功能:
  • 计算张三的好友有几人

    • scard zhangsan
      
  • 计算张三和李四有哪些共同好友

    • sinter zhangsan lisi
      
  • 查询哪些人是张三的好友却不是李四的好友

    • sdiff zhangsan lisi
      
  • 查询张三和李四的好友总共有哪些人

    • sunion zhangsan lisi
      
  • 判断李四是否是张三的好友

    • sismember zhangsan lisi
      
  • 判断张三是否是李四的好友

    • sismember lisi zhangsan
      
  • 将李四从张三的好友列表中移除

    • srem zhangsan lisi
      

2.6.SortedSet类型

Redis的SortedSet是一个可排序的set集合,与Java中的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范围内的元素
  • ZDIFF、ZINTER、ZUNION:求差集、交集、并集

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

  • 升序获取sorted set 中的指定元素的排名:ZRANK key member

  • 降序获取sorted set 中的指定元素的排名:ZREVRANK key memeber

练习题:

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

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

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

并实现下列功能:

  • 删除Tom同学

    • zrem stu Tom
      
  • 获取Amy同学的分数

    • zscore stu Amy
      
  • 获取Rose同学的排名

    • 升序:zrank stu Rose
    • 降序:zrevrank stu Rose
      • 最好后面加个1,因为redis索引是从0开始的
  • 查询80分及以下有几个学生

    • zcount stu 0 80
      
  • 给Amy同学加2分

    •  zincrby stu 2 Amy
      
  • 查出成绩前3名的同学

    • zrevrange stu 0 2
      
  • 查出成绩80分及以下的所有同学

    •  zrangebyscore stu 0 80
      

3.Redis的Java客户端

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

其中Java客户端也包含很多:

image-20220609102817435

标记为*的就是推荐使用的java客户端,包括:

  • Jedis和Lettuce:这两个主要是提供了Redis命令对应的API,方便我们操作Redis,而SpringDataRedis又对这两种做了抽象和封装,因此我们后期会直接以SpringDataRedis来学习。
  • Redisson:是在Redis基础上实现了分布式的可伸缩的java数据结构,例如Map、Queue等,而且支持跨进程的同步机制:Lock、Semaphore等待,比较适合用来实现特殊的功能需求。

3.1.Jedis客户端

Jedis的官网地址: https://github.com/redis/jedis

3.1.1.快速入门

我们先来个快速入门:

1)引入依赖:

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

2)建立连接

新建一个单元测试类,内容如下:

private Jedis jedis;

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

3)测试:

@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() {
    // 插入hash数据
    jedis.hset("user:1", "name", "Jack");
    jedis.hset("user:1", "age", "21");

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

4)释放资源

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

3.1.2.连接池

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用Jedis连接池代替Jedis的直连方式。

package com.heima.jedis.util;

import redis.clients.jedis.*;

public class JedisConnectionFactory {

    private static JedisPool jedisPool;

    static {
        // 配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(8);
        poolConfig.setMaxIdle(8);
        poolConfig.setMinIdle(0);
        poolConfig.setMaxWaitMillis(1000);
        // 创建连接池对象,参数:连接池配置、服务端ip、服务端端口、超时时间、密码
        jedisPool = new JedisPool(poolConfig, "192.168.150.101", 6379, 1000, "123321");
    }

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

测试类:

@SpringBootTest
class RedisTestApplicationTests {

    private Jedis jedis = JedisConnectionFactory.getJedis();

    @Test
    void testString(){
        jedis.set("name","Kyle");
        String name = jedis.get("name");
        System.out.println("name = " + name);
    }

    @Test
    void testHash(){
        jedis.hset("reggie:user:1","name","Jack");
        jedis.hset("reggie:user:2","name","Rose");
        jedis.hset("reggie:user:3","name","Kyle");
        jedis.hset("reggie:user:1","age","21");
        jedis.hset("reggie:user:2","age","18");
        jedis.hset("reggie:user:3","age","18");
        Map<String, String> map = jedis.hgetAll("reggie:user:1");
        System.out.println(map);
    }

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

3.2.SpringDataRedis客户端

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对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封装到了不同的类型中:

3.2.1.快速入门

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

首先,新建一个maven项目,然后按照下面步骤执行:

1)引入依赖
<!--redis依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--common-pool-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
2)配置Redis
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

spring最新版版本配置文件

spring:
  data:
    redis:
      ## 单击模式配置
      # Redis服务器地址
      host: 192.168.0.103
      # Redis服务器端口号
      port: 6379
      # 使用的数据库索引,默认是0
      database: 0
      # 设置密码,如果无密码,需注释该行
      password: 123
      # 连接超时时间(毫秒)
      connect-timeout: 1000
      # 操作超时时间(毫秒)
      timeout: 1000
      # 客户端名称(不知道干嘛用的)
      client-name:
      # 驱动类型
      client-type: lettuce
      # 连接池配置
      lettuce:
        pool:
          # 最小空闲连接(默认0)
          min-idle: 1
          # 最大空闲连接(默认8)
          max-idle: 8
          # 最大连接数(默认8,使用负值表示没有限制)
          max-active: 16
          # 最大阻塞等待时间,单位毫秒(默认-1,负数表示没限制,永不超时)
          max-wait: 2000
      ssl:
        enabled: false
3)注入RedisTemplate

因为有了SpringBoot的自动装配,我们可以拿来就用:

@SpringBootTest
class RedisStringTests {

    @Autowired
    private RedisTemplate redisTemplate;
}
4)编写测试
@SpringBootTest
class RedisStringTests {

    @Autowired
    private RedisTemplate edisTemplate;

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

image-20240820145917399

3.2.2.自定义序列化

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

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

缺点:

  • 可读性差
  • 内存占用较大

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

引入依赖:

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

配置类:

@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 GenericJackso n2JsonRedisSerializer();
        // 设置Key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}

这里采用了JSON序列化来代替默认的JDK序列化方式。最终结果如图:

整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。

3.2.3.StringRedisTemplate

为了节省内存空间,我们可以不使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。

因为存入和读取时的序列化及反序列化都是我们自己实现的,SpringDataRedis就不会将class信息写入Redis了。

这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式。

省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用:

@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON序列化工具
private static final ObjectMapper mapper = new ObjectMapper();

@Test
void testSaveUser() throws JsonProcessingException {
    // 创建对象
    User user = new User("虎哥", 21);
    // 手动序列化
    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);
}

或者使用FastJson来进行序列化

// 创建对象
User user = new User("虎哥", 21,3);
// 手动序列化
String jsonString = JSON.toJSONString(user);
// 写入数据
stringRedisTemplate.opsForValue().set("user:200", jsonString);

// 获取数据
String jsonUser = stringRedisTemplate.opsForValue().get("user:200");
// 手动反序列化
User user1 = JSON.parseObject(jsonUser,User.class);

System.out.println("user1 = " + user1);

image-20240820155507303

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2055834.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

错误信息“缺少msvcr120.dll”或“找不到msvcr120.dll”应该如何修复?几种方法快速修复

由于这个msvcr120.dll文件与应用程序的运行密切相关&#xff0c;任何与之相关的问题都可能导致应用程序无法正常运行。错误信息如“缺少msvcr120.dll”或“找不到msvcr120.dll”&#xff0c;通常出现在软件安装不正确或系统更新后。接下俩就教大家几种方法快速修复msvcr120.dll…

7 周岁自闭症儿童可以去普校上学吗?

对于许多自闭症儿童的家长来说&#xff0c;孩子能否去普通学校上学是一个至关重要的问题。而星贝育园给出了充满希望的答案。 星贝育园向家长郑重承诺&#xff0c;4 周岁之前开始干预可以 100%摘帽&#xff0c;即消除自闭症症状。在这里&#xff0c;为自闭症儿童提供个性化教学…

Spring源码解析(34)之Spring事务回滚流程

一、前言 在上一个篇章我们主要介绍了Spring事务的运行流程&#xff0c;也带着一步步debug看了整个事务的运行流程&#xff0c;但是还是欠缺了Spring事务的回滚的流程。 在上篇也主要介绍了Spring事务的传播特性&#xff0c;这里还是要看一下Spring事务的传播特性&#xff0c;因…

思博伦测试每秒最大新建、并发、吞吐

详细方法查看本文资源链接 一、最大新建测试说明 1、新建测试的主要目标是测试被测设备&#xff08;DUT&#xff09;的处理器能力。在单位时间内能够建立的连接数越多&#xff0c;说明被测设备的处理器的能力越强。 2、由于在测试过程中&#xff0c;我们只关心成功的建立TCP…

流动会场:定义新一代灵活空间的全新选择—轻空间

在当今快节奏的世界里&#xff0c;活动和会议的需求正变得越来越多样化和复杂化。无论是公司年会、大型宴会、还是各类演出和会议&#xff0c;场地的选择不仅需要满足功能需求&#xff0c;更要灵活、易于部署。正是在这样的背景下&#xff0c;“流动会场”这一创新概念应运而生…

反向沙箱是什么?如何使用反向沙箱保障上网安全

反向沙箱是什么&#xff1f; 反向沙箱是深信达的一种沙箱技术&#xff0c;又称SPN&#xff08;Sandbox Proxy Network&#xff09;沙箱。主要用于解决企业在安全上网过程中的风险问题。它通过在企业内部部署一个隔离的沙盒环境&#xff0c;实现安全的互联网访问&#xff0c;从而…

注意力机制(课程笔记)

一&#xff1a; 针对的问题 解决在循环卷积网络RNN模型中存在的信息瓶颈问题。 信息瓶颈&#xff1a; 举的是机器翻译的例子。在RNN中&#xff0c;Decoder的第一个输出取决于Encoder中的上一个输出&#xff0c;然后Decoder的其余输出都取决于上一个Decoder输出&#xff08;也就…

使用Nexus3为containerd和docker配置镜像代理

1.Nexus3介绍&#xff1a; Nexus3&#xff08;Nexus Repository Manager3&#xff09;是一个用于存储、组织和管理软件组件&#xff08;如 JAR文件、npm包、Docker镜像等&#xff09;的仓库管理系统。它由Sonatype开发并维护。Nexus Repository Manger支持许多流行的包管理工具…

免费仿微信聊天工具盒子IM

盒子IM是一个仿微信实现的网页版聊天软件&#xff0c;不依赖任何第三方收费组件。后端采用springbootnetty实现&#xff0c;web端使用vue&#xff0c;移动端使用uniapp&#xff0c;支持私聊、群聊、离线消息、发送图片、文件、语音、emoji表情、视频聊天等功能。包含pc端和移动…

Redis 技术详解

一、Redis 基础 &#xff08;一&#xff09;为什么使用 Redis 速度快&#xff0c;因为数据存在内存中&#xff0c;类似于 HashMap&#xff0c;查找和操作的时间复杂度都是 O(1)。支持丰富数据类型&#xff0c;支持 string、list、set、Zset、hash 等。支持事务&#xff0c;操…

Go —— 反射

反射 反射是什么&#xff1f; 反射是运行时检查自身结构的机制反射是困惑的源泉。 反射特性与 interface 紧密相关。 接口 1. 类型 Go是静态类型语言&#xff0c;比如int、float32、[]byte&#xff0c;等等。每个变量都有一个静态类型&#xff0c;而且在编译时就确定了。…

自主智能体的未来:LangChain Agents如何实现复杂任务自动化

一、AI Agents 基础&#xff1a;ReAct 范式 在AI领域&#xff0c;智能体&#xff08;Agents&#xff09;指的是能够自主感知环境并采取行动以实现特定目标的系统。ReAct&#xff08;Reasoning and Acting&#xff09;范式是理解智能体的基础&#xff0c;它强调智能体在执行任务…

【YashanDB知识库】共享集群YAC换IP

【标题】共享集群YAC换IP 【需求分类】安装部署&#xff0c;配置变更 【关键字】安装部署&#xff0c;更换IP&#xff0c;运维&#xff0c;配置变更&#xff0c;高可用&#xff0c;YAC 【需求描述】客户需要将已经部署的YAC集群更换IP&#xff0c;从测试网段切换生产网段 【…

2024年AI艺术生成器精选榜单,抢先体验!

选择合适的AI艺术生成器对于设计项目的成功至关重要。无论是从设计线框到复杂的交互原型&#xff0c;合适的工具都能帮助顺利实现目标。本文将分享2024年最受欢迎的AI艺术生成器&#xff0c;让我们一起来看看&#xff01; 即时设计 在2024年好用的AI艺术生成器中&#xff0c;…

基于STM32开发的智能家居照明系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 系统初始化光线检测与自动调节手动控制与状态指示Wi-Fi通信与远程控制应用场景 家庭智能照明办公室自动化照明常见问题及解决方案 常见问题解决方案结论 1. 引言 智能家居照明系统通过集成光…

宠物空气净化器是智商税吗吗?哪款最好用?

在当今社会&#xff0c;随着生活节奏不断加快&#xff0c;许多人会感到孤独。因此养猫已成为许多家庭的生活方式之一。他们期待着家里有欢声笑语的出现&#xff0c;希望家里一推开门都是有猫咪等着自己&#xff0c;在自己无人诉说心事的时候&#xff0c;猫咪能给自己一份陪伴。…

图神经网络教程2——循环图神经网络-2

目录 计算下游输出 序列图数据的扩展 图长短期记忆网络 循环转换在RGNN应用于图分类时的作用 数据集 算法 结果和讨论 门控循环单元 优缺点 前文索引 本篇是GRNN的第二篇文章&#xff0c;点击此处可到达第一篇文章的位置。 计算下游输出 一旦我们以图中的每个顶点为…

【PyTorch】深度学习PyTorch加载数据

系列文章目录 【PyTorch】深度学习PyTorch环境配置及安装【详细清晰】 文章目录 系列文章目录前言一、Dataset与DataloaderDatasetDataloader 二、使用步骤Dataset类的使用2.读入数据 前言 pytorch的数据加载中关于如何操作数据主要涉及Dataset和DataLoader两个类&#xff0c…

桶射巡飞无人机技术详解

无人机&#xff08;Launcher-Deployed Loitering Munition, LDLM&#xff09;作为一种新型无人机系统&#xff0c;融合了远程发射、长时续航、精确打击与多任务执行能力&#xff0c;近年来在军事侦察、目标监视、精确打击以及民用领域如环境监测、应急救援等方面展现出巨大潜力…

Elasticsearch + Search UI 构建一个文件搜索引擎

目录 Elasticsearch使用优势App Search Search UI配置engine集中管理配置和提供实用工具函数配置和初始化一个基于Elasticsearch的搜索界面应用程序Search UI 基础用法 好书推荐 Elasticsearch 使用优势 使用ElasticSearch的主要好处在于其强大的全文搜索和实时分析能力。Elas…