Redis的简单使用 (实现Session持久化)

🎉🎉🎉点进来你就是我的人了
博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!

欢迎志同道合的朋友一起加油喔🤺🤺🤺


目录

一、Redis数据类型的使用

1. 字符串(String)

2. 字典类型(哈希 Hashes)

3. 列表(Lists)

4. 集合(Sets)

5. 有序集合(Sorted sets)

二、SpringBoot连接Redis操作

三、Spring Session持久化

1. 引进sping session的依赖 , 配置相应的session存储方式(redis) 实现持久化

2. Spring Session的工作原理

四、序列化和反序列化  (知识点补充)

为什么要序列化?



Redis是一个开源的、内存中的数据结构存储系统,可以用作数据库、缓存和消息代理。它支持多种数据类型,包括字符串、哈希、列表、集合和有序集合。

一、Redis数据类型的使用

1. 字符串(String)

字符串是Redis最基本的数据类型,你可以理解它为与Memcached类似的功能,它是二进制安全的。也就是说,Redis的字符串可以包含任何数据,比如jpg图片或者序列化的对象。一个Redis字符串类型的值最大能存储512MB。由于其简单且灵活,字符串类型在Redis中有很多用途,如:

  • 缓存:你可以将数据库查询的结果、用户会话、网页内容等存储为字符串,从而实现缓存功能。

  • 计数器:Redis的字符串可以存储64位的整数和双精度浮点数,并支持自增或自减操作,所以你可以用字符串实现计数器。

  • 分布式锁:你可以用SET key value [EX seconds] [PX milliseconds] [NX|XX]命令实现分布式锁。

以下是一些基本的字符串操作和示例:

  • SET key value:设置键的字符串值。
SET mykey "Hello"
  • GET key:获取键的值。
GET mykey
  • DEL key:删除键。
DEL mykey
  • INCR key:将键的整数值增一。
INCR mycounter
  • DECR key:将键的整数值减一。
DECR mycounter
  • APPEND key value:如果键已经存在并且是一个字符串,APPEND 命令将指定的 value 追加到原值的末尾。
APPEND mykey " World"

2. 字典类型(哈希 Hashes)

Redis的哈希(Hash)类型是字符串字段和字符串值之间的映射,因此它们是适合存储对象的理想数据类型。每个哈希可以存储2^32-1个键值对(超过40亿个)

哈希在Redis中常见的应用场景包括:

  • 存储对象:哈希类型非常适合存储对象,因为它们可以存储与对象相关的多个字段和值。

  • 缓存:哈希可以作为缓存的一种数据结构,例如存储一些数据库查询的结果。

  • 计数器:哈希字段的值可以增加或减少,可以用来实现多个计数器。

以下是一些基本的哈希操作和示例:

  • HSET key field value:为哈希表 key 中的指定字段设置值。
  • HSET key field value:为哈希表 key 中的指定字段设置值。
HSET myhash field1 "Hello"
HGET myhash field1

将一个对象存入Redis哈希中的方法是将对象的每个字段作为键值对存储到哈希中。例如,如果你有一个表示人的对象,它有 name, age, 和 city 三个字段,你可以这样存储它:

HSET person name "Bob" age "30" city "New York"
  • 在这个例子中,person 是哈希的名字,name, age, city 是字段名,而 Bob, 30, New York 则是它们对应的值。
  • 需要注意的是,Redis 4.0.0 版本之后,HSET 命令支持同时设置多个字段。如果你的Redis版本较旧,可能需要分别执行多次 HSET 命令来存储每个字段。

获取存储的对象也同样简单,你可以使用 HGETALL 命令:

HGETALL person

这将返回哈希中所有的字段和值:

1) "name"
2) "Bob"
3) "age"
4) "30"
5) "city"
6) "New York"

3. 列表(Lists)

Redis的列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素至列表的头部(左边)或者尾部(右边)。一个列表最多可以包含 232 - 1 元素 (4294967295,每个列表超过40亿个元素)。列表中的元素可以重复,并且列表是双向的,这意味着元素可以从列表的两端推入或弹出。这种数据类型适合用于各种不同的场景,如:

  • 消息队列:Redis列表的push、pop操作使得它非常适合作为消息队列使用。例如,应用程序可以将要处理的任务推入列表中,然后工作线程可以从列表中取出并处理任务。

  • 时间线或者新闻feed:如果你想追踪最新的几件事情或者记录日志,Redis的列表类型很适合。可以将新的元素推入列表,然后仅保留最新的N个元素。

  • 堆栈:通过将元素推入列表的头部,然后再从头部弹出元素,Redis列表可以作为LIFO(后入先出)堆栈使用。

以下是一些基本的列表操作和示例:

  • LPUSH key value:将一个或多个值插入到列表头部。
LPUSH mylist "world"
LPUSH mylist "Hello"
  • RPUSH key value:将一个或多个值插入到列表尾部。
RPUSH mylist "there"
  • LPOP key:移除并获取列表最左边的元素。
LPOP mylist
  • RPOP key:移除并获取列表最右边的元素。
RPOP mylist
  • LRANGE key start stop:获取列表在指定区间内的元素。startstop 都是0-based的索引,其中0是列表的第一个元素(头部),-1是最后一个元素(尾部)。
LRANGE mylist 0 -1

4. 集合(Sets)

Redis的Set是字符串的无序集合。集合是通过哈希表实现的,所以添加、删除、查找的复杂度都是O(1)。集合中最大的成员数为 232 - 1 (4294967295,每个集合可存储40多亿条记录)。集合在Redis中有很多应用场景,如:

  • 社交网络:你可以用集合来存储用户的朋友列表或者粉丝列表,然后通过求交集、并集、差集等操作来获取共同的朋友、特定群体的用户等。

  • 标签系统:你可以为每个标签创建一个集合,然后将带有该标签的项(如文章的ID)添加到集合中。然后你可以很容易地获取带有某个或某些特定标签的所有项。

  • 数据过滤:由于集合的元素是唯一的,所以你可以通过向集合添加元素的方式来过滤重复的数据。

以下是一些基本的集合操作和示例:

  • SADD key member:将一个或多个成员元素加入到集合中
SADD myset "Hello"
SADD myset "World"
  • SREM key member:移除集合中一个或多个成员。
SREM myset "World"
  • SMEMBERS key:返回集合中的所有成员。
SMEMBERS myset
  • SISMEMBER key member:判断 member 元素是否是集合 key 的成员。
SISMEMBER myset "World"
  • SUNION key1 key2:返回一个集合的并集。
SUNION myset otherset
  • SINTER key1 key2:返回一个集合的交集。
SINTER myset otherset
  • SDIFF key1 key2:返回一个集合的差集。
SDIFF myset otherset

5. 有序集合(Sorted sets)

和Sets相比,Sorted Sets类型也是set类型,但是每个元素都会关联一个score,redis正是通过score来为集合中的成员进行从小到大的排序的。有序集合的成员是唯一的,但score可以重复。有序集合中最大的成员数为 232 - 1 (4294967295,可以存储40多亿条记录)。

由于元素是按照分值排序的,有序集合非常适合以下几种用途:

  • 排行榜:可以使用有序集合创建实时的排行榜,如游戏得分排行、用户活跃度排行等。

  • 时间序列:如果把时间戳作为分值,那么有序集合就可以存储时间序列数据,如用户登录记录、文章发布记录等。

  • 按距离排序的地理位置数据:如果把地理位置的距离作为分值,有序集合可以用来实现本地化的功能,如查找附近的餐厅或朋友。

以下是一些基本的有序集合操作和示例:

  • ZADD key score member:将一个或多个成员元素及其分数值加入到有序集当中。

ZADD myzset 1 "one"
ZADD myzset 2 "two"
  • ZREM key member:移除有序集合中的一个或多个成员。
ZREM myzset "one"
  • ZRANGE key start stop [WITHSCORES]:返回有序集中指定区间内的成员,成员位置按分数值递增来排序。
ZRANGE myzset 0 -1 WITHSCORES
  • ZREVRANGE key start stop [WITHSCORES]:返回有序集中指定区间内的成员,成员位置按分数值递减来排序。
ZREVRANGE myzset 0 -1 WITHSCORES
  • ZSCORE key member:返回有序集中,成员的分数值。
ZSCORE myzset "two"
  • ZRANK key member:返回有序集合中指定成员的索引(排名)。
ZRANK myzset "two"

二、SpringBoot连接Redis操作

1. 添加依赖:首先,在你的Maven或Gradle项目中添加Spring Boot Data Redis依赖。如果你使用的是Maven,可以在pom.xml中添加如下依赖:

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

2. 配置Redis连接:在你的application.properties或者application.yml文件中,可以配置如下Redis连接参数:(application.properties示例如下)

#配置连接reds
spring.redis.host= 127.0.0.1
#配置连接的端口号
spring.redis.port=8891
# 如果Redis服务器设置了密码,需要配置这一项
spring.redis.password=1111
#配置使用哪个Redis数据库
spring.redis.database=1

3. 在Spring应用中使用Redis:Spring Boot会自动配置一个RedisTemplateStringRedisTemplate实例,你可以直接在你的应用中注入这些实例,然后就可以使用它们进行Redis操作了。例如:

// 使用 @RestController 注解,这样类中的方法都会以Json格式返回
@RestController
public class RedisController {// 通过 @Autowired 注解,Spring Boot 会自动为我们注入一个 RedisTemplate 对象,我们可以使用它来操作 Redis@Autowiredprivate RedisTemplate redisTemplate;// 定义一个 HTTP 的 endpoint,当你访问 "/save" 这个路径时,会执行这个方法// 使用 @RequestMapping 注解,可以将 HTTP 请求映射到特定的处理方法上@RequestMapping("/save")public String save() {// 使用 RedisTemplate 的 opsForValue() 方法获取到一个 ValueOperations 对象,// 然后调用 set 方法将 "userinfo" 的值设置为 "zhangsan"redisTemplate.opsForValue().set("userinfo","zhangsan");// 返回 "ok" 字符串作为 HTTP 响应return "ok";}// 定义一个 HTTP 的 endpoint,当你访问 "/get" 这个路径时,会执行这个方法@RequestMapping("/get")public Object get() {// 使用 RedisTemplate 的 opsForValue() 方法获取到一个 ValueOperations 对象,// 然后调用 get 方法获取 "userinfo" 的值return redisTemplate.opsForValue().get("userinfo");}// 定义一个 HTTP 的 endpoint,当你访问 "/save2" 这个路径时,会执行这个方法@RequestMapping("/save2")public String save2() {// 使用 RedisTemplate 的 opsForHash() 方法获取到一个 HashOperations 对象,// 然后调用 put 方法在 "myhash" 这个 hash 中添加一个键值对,键是 "username",值是 "lisi"//myhash是哈希表的名字,然后username是该哈希表内的一个字段,它的值是lisi。redisTemplate.opsForHash().put("myhash","username","lisi");// 返回 "ok" 字符串作为 HTTP 响应return "ok";}// 定义一个 HTTP 的 endpoint,当你访问 "/get2" 这个路径时,会执行这个方法@RequestMapping("/get2")public Object get2() {// 使用 RedisTemplate 的 opsForHash() 方法获取到一个 HashOperations 对象,// 然后调用 get 方法从 "myhash" 这个 hash 中获取 "username" 的值return redisTemplate.opsForHash().get("myhash","username");}
}

三、Spring Session持久化

1. 引进sping session的依赖 , 配置相应的session存储方式(redis) 实现持久化

  • 在上面配置好redis的基础上,继续在pom.xml文件中添加以下依赖:
<dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId>
</dependency>
  • 然后在application.properties文件里修改上面redis的配置
// 通过注解@RestController,告诉Spring这是一个REST控制器,用于处理HTTP请求。
@RestController// @RequestMapping("/user")为此控制器指定一个公共路径前缀,所以在此控制器中的所有路由都将在其前添加/user路径。
@RequestMapping("/user")
public class UserController {// SESSION_KEY_USERINFO是用于保存在HttpSession中的用户信息的键名。为此键名设置一个常量可以帮助避免键名出现打字错误。private static final String SESSION_KEY_USERINFO = "SESSION_KEY_USERINFO";// 定义了一个路由/user/set,客户端可以通过HTTP请求这个路由来设置用户信息。@RequestMapping("/set")public String save(HttpSession session) {// 将用户信息(在此示例中为"zhangsan")存储在HttpSession中。存储信息时使用了之前定义的SESSION_KEY_USERINFO键名。session.setAttribute(SESSION_KEY_USERINFO,"zhangsan");// 如果存储成功,则返回"ok"。return "ok";}// 定义了一个路由/user/get,客户端可以通过HTTP请求这个路由来获取用户信息。@RequestMapping("/get")public Object get(HttpServletRequest request) {// 获取HttpSession。如果请求中没有对应的HttpSession,则返回null。HttpSession session = request.getSession(false);// 检查session是否存在,并且session中是否有对应的用户信息。如果都满足,则返回存储在SESSION_KEY_USERINFO键名下的用户信息。if(session != null && session.getAttribute(SESSION_KEY_USERINFO) != null) {return session.getAttribute(SESSION_KEY_USERINFO);}// 如果session不存在,或者session中没有用户信息,则返回"null"。return "null";}
}
  • 最后就可以使用HttpSession的接口进行操作,将用户信息存储到session中即可(此时session会被存储到redis中)

// 使用@RestController注解,告诉Spring这是一个REST控制器,用于处理HTTP请求。
@RestController// @RequestMapping("/user")注解为此控制器指定一个公共路径前缀,所以在此控制器中的所有路由都将在其前添加/user路径。
@RequestMapping("/user")
public class UserController {// 这是一个字符串常量,代表了在HttpSession中保存用户信息的键名。将这个键名定义为一个常量可以帮助避免键名的打字错误。private static final String SESSION_KEY_USERINFO = "SESSION_KEY_USERINFO";// 这是一个路由处理方法,用于处理/save的HTTP请求。在请求中,客户端可以通过这个方法向HttpSession中保存用户信息。@RequestMapping("/save")public String save(HttpSession session) {// 创建一个新的UserInfo对象,设置其属性,然后将其保存到HttpSession中。UserInfo userInfo = new UserInfo();userInfo.setId(1);userInfo.setUsername("lisi");userInfo.setAge(18);// 将UserInfo对象保存到HttpSession中,键名为SESSION_KEY_USERINFO。session.setAttribute(SESSION_KEY_USERINFO, userInfo);// 如果保存成功,则返回"ok"。return "ok";}// 这是一个路由处理方法,用于处理/get的HTTP请求。在请求中,客户端可以通过这个方法从HttpSession中获取用户信息。@RequestMapping("/get")public Object get(HttpServletRequest request) {// 从HttpServletRequest中获取HttpSession。如果请求中没有对应的HttpSession,则返回null。HttpSession session = request.getSession(false);// 检查session是否存在,并且session中是否有对应的用户信息。如果都满足,则返回存储在SESSION_KEY_USERINFO键名下的用户信息。if(session != null && session.getAttribute(SESSION_KEY_USERINFO) != null) {return session.getAttribute(SESSION_KEY_USERINFO);}// 如果session不存在,或者session中没有用户信息,则返回"null"。return "null";}
}

在完成以上步骤之后,你的Spring Boot应用就会自动将Session数据存储在Redis中,而不是在内存中。这样,即使你的应用重启,用户的Session数据也不会丢失。此外,这也使得在多实例环境下共享Session数据成为可能。

2. Spring Session的工作原理

  • Spring Session提供了一个透明的方式来替换HttpSession。当你在应用中加入了Spring Session的依赖并配置了相应的Session存储方式(如这里的Redis)后,Spring Session会在后台替换原生的HttpSession实现。
  • 在我上面的代码中,我并没有直接使用Redis的API,仍然是使用HttpSession的接口进行操作。然而,因为Spring Session的存在,这些操作实际上已经被映射到了Redis上。这就是为什么你只需要配置Redis和引入Spring Session的依赖,就可以将Session存储在Redis中的原因。
  • 也就是说,Spring Session提供了一种透明的方式来更改Session的存储位置,而开发者无需更改自己的代码。这也使得在不同环境中切换Session存储的方式变得非常方便。例如,你可能在开发环境中使用内存存储Session,而在生产环境中则使用Redis存储Session。只需要更改配置文件,而无需更改代码。

四、序列化和反序列化  (知识点补充)

在 Java 中,对象的序列化是将对象的状态(包括它的数据或属性)转换为字节流的过程,反序列化则是将字节流恢复为原来的对象。这个过程主要涉及两个接口:Serializable 和 Externalizable。

为什么要序列化?

序列化的主要目的是为了保存对象的状态,以便可以在未来的某个时间点再将其恢复。以下是使用序列化的几个常见场景:

  1. 在网络中发送对象:序列化可以将对象转换为字节流,然后可以将这个字节流在网络中传输。在接收端,我们可以再将这个字节流反序列化为对象。

  2. 持久化:如果你想将对象的状态保存到磁盘上,那么你可以将对象序列化为字节流,然后将这个字节流写入到磁盘。在需要的时候,你可以再从磁盘读取这个字节流,并将其反序列化为对象。

  3. 跨JVM内存共享:例如在分布式计算或者微服务架构中,一个服务的JVM可能需要将对象发送给另一个服务的JVM。

如果你觉得这篇文章有价值,或者你喜欢它,那么请点赞并分享给你的朋友。你的支持是我创作更多有用内容的动力,感谢你的阅读和支持。祝你有个美好的一天!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“前端已死”

一、一些迹象 逛社区&#xff0c;偶然看到了这张图片&#xff1a; 嗯……我眉头一皱&#xff0c;久久不语&#xff0c;心想&#xff0c;有这么夸张吗&#xff0c;假的吧&#xff1f; 突然想到&#xff0c;最近我在社区发了个前端招聘的信息&#xff0c;结果简历漫天纷飞&…

并发-JMM-CPU缓存一致性协议MESI

回顾 指令重排 第一V读&#xff0c;都不能指令重排&#xff1b;第二个V写&#xff0c;都不能指令重排 普通读写&#xff0c;写读都会发生指令重排&#xff0c;V写普通读写会发生指令重排&#xff0c;普通读写V读会发生指令重排 CPU缓存一致性协议MESI java—》cpu的执行过程…

kafka基础

文章目录 1、什么是消息队列&#xff1f;2、基础架构3、Kafka为什么快4、零拷贝5、Rebalance机制6、kafka如何避免重复消费7、避免消息丢失8、Kafka怎么实现消息的顺序消费9、什么是ISR10、Kafka文件存储机制 1、什么是消息队列&#xff1f; kafka是一个消息队列的中间件&…

MySQL - 数据库级别的外键

1. 外键 FOREIGN KEY (了解) 测试数据 &#xff1a; 学生表 CREATE TABLE IF NOT EXISTS student (id INT(4) NOT NULL AUTO_INCREMENT COMMENT 学号,name VARCHAR(30) NOT NULL DEFAULT 匿名 COMMENT 姓名,pwd VARCHAR(20) NOT NULL DEFAULT 123456 COMMENT 密码,sex VARC…

FastDFS单机部署及SpringBoot整合

前言 FastDFS是一个开源的高性能分布式文件系统。它的主要功能包括&#xff1a;文件存储、文件同步和文件访问&#xff08;文件上传和文件下载&#xff09;&#xff0c;可以解决高容量和负载平衡问题。FastDFS应满足其服务基于文件的网站的要求&#xff0c;如照片共享网站和视…

卷积基础知识总结

卷积层是卷积神经网络中的核心模块&#xff0c;**卷积层的目的是提取输入特征图的特征&#xff0c;**如下图所示&#xff0c;卷积核可以提取图像中的边缘信息。卷积也成为过滤器&#xff0c;即Filter 1 卷积的计算方法 卷积运算本质上就是在滤波器和输入数据的局部区域间做点…

ECharts数据可视化

目录 第一章 什么是ECharts 第二章 搭建环境 2.1 Echarts的下载 2.2 Visual Studio Code下载 第三章 一个简单的可视化展示 第四章 Echarts组件 4.1 标题 4.2 提示框 4.3 工具栏 4.4 图例 4.5 时间轴 4.6 数据区域缩放 4.6.1 滑动条型数据区域缩放 4.6.2 内置型…

IDEA中创建编写JSP

一、安装Tmocat并配置环境 安装请参考&#xff1a;https://www.cnblogs.com/weixinyu98/p/9822048.html 安装请参考&#xff1a;https://www.cnblogs.com/zhanlifeng/p/14917777.html 注意&#xff1a;在安装成功Tomcat测试是否成功安装时&#xff0c;访问“http://localhost:8…

MyBatisPlus代码生成器插件

1、下载IDEA插件&#xff1a;MybatisPlus。 2、使用插件生成代码 首先点击IDEA导航菜单上的Other选项&#xff0c;然后进行数据库和代码生成器的配置&#xff1a; 数据库配置&#xff1a; 代码生成器配置&#xff0c;然后点击code generator&#xff1a; 最会插件会按照配置…

VSCode+GDB+Qemu调试ARM64 linux内核

俗话说&#xff0c;工欲善其事 必先利其器。linux kernel是一个非常复杂的系统&#xff0c;初学者会很难入门。 如果有一个方便的调试环境&#xff0c;学习效率至少能有5-10倍的提升。 为了学习linux内核&#xff0c;通常有这两个需要 可以摆脱硬件&#xff0c;方便的编译和…

【MySQL数据库】MySQL 高级SQL 语句二

MySQL 高级 SQL 语句二 一、连接查询1.1 inner join&#xff08;内连接&#xff09;1.2 left join &#xff08;左连接&#xff09;1.3 right join(右连接) 二、CREATE VIEW ---- 视图三、 UNION - - 连集3.1 UNION3.2 UNION ALL 四、交集值&#xff08;取两个SQL语句结果的交集…

pwn学习day4——ret2text

文章目录 原理&#xff1a;例子x64x32 原理&#xff1a; 覆盖函数返回地址到程序内存在的gadgets获取shell 例子 #include<stdio.h> #include<stdlib.h>void hint(){system("$0"); } int main(){char buf[0x10];printf("input: ");scanf(&q…