点进来你就是我的人了
博主主页:戳一戳,欢迎大佬指点!欢迎志同道合的朋友一起加油喔
目录
一、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最基本的数据类型,你可以理解它为与Memcached类似的功能,它是二进制安全的。也就是说,Redis的字符串可以包含任何数据,比如jpg图片或者序列化的对象。一个Redis字符串类型的值最大能存储512MB。由于其简单且灵活,字符串类型在Redis中有很多用途,如:
缓存:你可以将数据库查询的结果、用户会话、网页内容等存储为字符串,从而实现缓存功能。
计数器:Redis的字符串可以存储64位的整数和双精度浮点数,并支持自增或自减操作,所以你可以用字符串实现计数器。
分布式锁:你可以用SET key value [EX seconds] [PX milliseconds] [NX|XX]
命令实现分布式锁。
以下是一些基本的字符串操作和示例:
SET mykey "Hello"
GET mykey
DEL mykey
INCR mycounter
DECR mycounter
APPEND mykey " World"
Redis的哈希(Hash)类型是字符串字段和字符串值之间的映射,因此它们是适合存储对象的理想数据类型。每个哈希可以存储2^32-1个键值对(超过40亿个)
哈希在Redis中常见的应用场景包括:
存储对象:哈希类型非常适合存储对象,因为它们可以存储与对象相关的多个字段和值。
缓存:哈希可以作为缓存的一种数据结构,例如存储一些数据库查询的结果。
计数器:哈希字段的值可以增加或减少,可以用来实现多个计数器。
以下是一些基本的哈希操作和示例:
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
则是它们对应的值。HSET
命令支持同时设置多个字段。如果你的Redis版本较旧,可能需要分别执行多次 HSET
命令来存储每个字段。获取存储的对象也同样简单,你可以使用 HGETALL
命令:
HGETALL person
这将返回哈希中所有的字段和值:
1) "name"
2) "Bob"
3) "age"
4) "30"
5) "city"
6) "New York"
Redis的列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素至列表的头部(左边)或者尾部(右边)。一个列表最多可以包含 232 - 1 元素 (4294967295,每个列表超过40亿个元素)。列表中的元素可以重复,并且列表是双向的,这意味着元素可以从列表的两端推入或弹出。这种数据类型适合用于各种不同的场景,如:
消息队列:Redis列表的push、pop操作使得它非常适合作为消息队列使用。例如,应用程序可以将要处理的任务推入列表中,然后工作线程可以从列表中取出并处理任务。
时间线或者新闻feed:如果你想追踪最新的几件事情或者记录日志,Redis的列表类型很适合。可以将新的元素推入列表,然后仅保留最新的N个元素。
堆栈:通过将元素推入列表的头部,然后再从头部弹出元素,Redis列表可以作为LIFO(后入先出)堆栈使用。
以下是一些基本的列表操作和示例:
LPUSH mylist "world"
LPUSH mylist "Hello"
RPUSH mylist "there"
LPOP mylist
RPOP mylist
start
和 stop
都是0-based的索引,其中0是列表的第一个元素(头部),-1是最后一个元素(尾部)。LRANGE mylist 0 -1
Redis的Set是字符串的无序集合。集合是通过哈希表实现的,所以添加、删除、查找的复杂度都是O(1)。集合中最大的成员数为 232 - 1 (4294967295,每个集合可存储40多亿条记录)。集合在Redis中有很多应用场景,如:
社交网络:你可以用集合来存储用户的朋友列表或者粉丝列表,然后通过求交集、并集、差集等操作来获取共同的朋友、特定群体的用户等。
标签系统:你可以为每个标签创建一个集合,然后将带有该标签的项(如文章的ID)添加到集合中。然后你可以很容易地获取带有某个或某些特定标签的所有项。
数据过滤:由于集合的元素是唯一的,所以你可以通过向集合添加元素的方式来过滤重复的数据。
以下是一些基本的集合操作和示例:
SADD myset "Hello"
SADD myset "World"
SREM myset "World"
SMEMBERS myset
SISMEMBER myset "World"
SUNION myset otherset
SINTER myset otherset
SDIFF myset otherset
和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 myzset "one"
ZRANGE myzset 0 -1 WITHSCORES
ZREVRANGE myzset 0 -1 WITHSCORES
ZSCORE myzset "two"
ZRANK myzset "two"
1. 添加依赖:首先,在你的Maven或Gradle项目中添加Spring Boot Data Redis依赖。如果你使用的是Maven,可以在pom.xml中添加如下依赖:
org.springframework.boot
spring-boot-starter-data-redis
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会自动配置一个RedisTemplate和StringRedisTemplate实例,你可以直接在你的应用中注入这些实例,然后就可以使用它们进行Redis操作了。例如:
// 使用 @RestController 注解,这样类中的方法都会以Json格式返回
@RestController
public class RedisController {
// 通过 @Autowired 注解,Spring Boot 会自动为我们注入一个 RedisTemplate 对象,我们可以使用它来操作 Redis
@Autowired
private 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");
}
}
pom.xml
文件中添加以下依赖:
org.springframework.session
spring-session-data-redis
# 表示我们使用Redis存储,这意味着Session数据将被存储在Redis数据库中。
spring.session.store-type=redis
#配置使用哪个Redis数据库
spring.redis.database=3
# 会话在30分钟(1800秒)无交互后将过期。
server.servlet.session.timeout=1800
# Redis Session的刷新模式。
#如果设置为"on_save",那么每次在Session中保存数据时,都会立即将数据写入Redis。
spring.session.redis.flush-mode=on_save
# Spring Session在Redis中使用的命名空间。所有的键都会被前缀化,以防止键之间的冲突。
spring.session.redis.namespace=spring:session
# Redis服务器的主机地址。这是Spring Boot应用将要连接的Redis服务器的IP地址或者主机名。
spring.redis.host=
# 连接Redis服务器的密码。如果Redis服务器没有设置密码,这个属性可以为空。
spring.redis.password=1111
# Redis服务器的端口号。默认情况下,Redis服务器运行在6379端口上。
spring.redis.port=8891
// 使用@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数据成为可能。
在 Java 中,对象的序列化是将对象的状态(包括它的数据或属性)转换为字节流的过程,反序列化则是将字节流恢复为原来的对象。这个过程主要涉及两个接口:Serializable 和 Externalizable。
序列化的主要目的是为了保存对象的状态,以便可以在未来的某个时间点再将其恢复。以下是使用序列化的几个常见场景:
在网络中发送对象:序列化可以将对象转换为字节流,然后可以将这个字节流在网络中传输。在接收端,我们可以再将这个字节流反序列化为对象。
持久化:如果你想将对象的状态保存到磁盘上,那么你可以将对象序列化为字节流,然后将这个字节流写入到磁盘。在需要的时候,你可以再从磁盘读取这个字节流,并将其反序列化为对象。
跨JVM内存共享:例如在分布式计算或者微服务架构中,一个服务的JVM可能需要将对象发送给另一个服务的JVM。
如果你觉得这篇文章有价值,或者你喜欢它,那么请点赞并分享给你的朋友。你的支持是我创作更多有用内容的动力,感谢你的阅读和支持。祝你有个美好的一天!