在感叹完Spring对于程序的大大简化之后,在这里总结一下Redis在Spring之中的使用技巧。Spring将Redis封装成一个RedisTemplate,所以本文之中主要总结的是如何使用这个RedisTemplate。话不多说,现在开始。
参考文章地址:https://www.cnblogs.com/superfj/p/9232482.html
本博客之中之前对于Redis的部分学习笔记:
关于Redis,MyBatis和Spring之中问题的一点梳理
概述
本文内容主要:
- 关于 spring-redis
- 关于 redis 的 key 设计
- redis 的基本数据结构
- 介绍 redis 和 springboot 的整合
- springboot 之中的 redistemplate 的使用
关于spring-redis
Spring-data-redis 针对 jedis 提供了如下功能:
-
连接池自动管理,提供了一个高度封装的”RedisTemplate” 类
-
针对 Jedis 客户端之中的大量 API 进行了归类封装,将同一类型的操作封装为 operation 接口。
ValueOperations: 简单K-V操作
SetOperations: set 类型数据操作
ZSetOperations: zset 类型数据操作
HashOperations: 针对 map 类型的数据操作
ListOperations: 针对 list 类型的数据操作。
由上可见,其直接将同一类的数据类型的操作归类,直接操作接口即可对某种数据类型进行直接操作,大大减小其操作复杂度。
-
提供了对于 key 的 “bound” (绑定)便捷化操作 API, 可以通过 bound 封装指定的 key,即BoundKeyOperations:
BoundValueOperations
BoundSetOperations
BoundListOperations
BoundHashOperations
-
将事务操作封装,由容器控制
-
针对数据的 ” 序列化/反序列化“, 提供了多种可选择策略(RedisSerializer)
JdkSerializationRedisSerializer
: POJO 对象的存取场景,使用 JDK 本身序列化机制,将 pojo 类通过 ObjectInputStream/ObjectOutputStream 进行序列化操作,最终在 redis-server 之中存储字节序列。是目前最常用的序列化策略。StringRedisSerializer
: Key 或者 Value 为字符串的场景,根据指定的 charset, 对数据的字节序列编码成String,是new String(bytes,charset)
和String.getBytes(charset)
的直接封装。是最轻量级和高效的策略。JacksonJsonRedisSerializer
: Jackson-json 提供了 javabean 和 json 之间的转换能力,可以将pojo实例序列化成json之后存储在Redis之中,也可以将json格式的数据转换成pojo实例。因为 jackson 工具在序列化和反序列化的时候,需要明确指定Class类型,因此此策略封装起来略微复杂。需要【jackson-mapper-asl工具支持】OxmSerializer: 提供了将 javabean 和 xml 之间的转换能力,目前可用的三方支持包括 jaxb,apache-xmlbeans,redis 存储的数据将是xml 工具,但是难度大,效率低,不建议使用。
如果数据需要被第三方工具解析,那么数据应该使用StringRedisSerializer,而不是 JdkSerializationRedisSerializer
关于Key的设计
key的存活时间:
一个很好的例子就是存储一些诸如临时认证key之类的东西。当去查找一个授权key的时候,以OAUTH为例,通常会得到一个超时时间。在超时时间过了之后,Redis就会自动清除。
关系型数据库的Redis key 设计
- 将表名换为key前缀,比如 tag
- 第二段放置用于区分 key 的字段,对应 mysql 之中主键的列名,比如 userid
- 第三段放主键值,如 2,3,4, a, b, c
- 第四段,写存储的列名
例子:user:userid:9:username
Redis的数据类型
String字符串
- String 是 redis 最基本的类型,一个 key 对应一个 value
- String 类型是二进制安全的,意味着 Redis的String 可以存储任何数据,包含jpg图片或者序列化对象
- String 类型是 Redis 最基本的数据类型,一个键最大可以存储512MB
链表
- Redis列表是最简单的字符串列表,排序为插入的顺序,列表的最大长度为2^32-1
- Redis的列表是使用链表实现的,这意味着在列表头部或者尾部增加一个元素的时间是常量时间
- 可以使用列表获取最新的内容,比如帖子,微博等等。用 itrim 很容易就可以获取最新的内容,并移除旧的内容
- 用列表可以实现生产者消费者模式,生产者调用 lpush 添加项到列表之中,消费者调用 rpop 从列表之中提取。如果没有元素,则轮询去获取,或者使用 brpop等待生产者添加项到列表之中。
集合
- redis 的集合是无序的字符串集合,集合之中的值是唯一的,无序的,可以对集合进行传统意义上面的所有操作,比如查看某个元素是否存在,对几个集合取交集,取并集等等。
- 通常可以使用集合去表示存储一些无关顺序的,表示对象之间关系的数据。比如可以用 sismember 查看用户是否拥有某个角色
- 在用到随机值的场合非常合适,因为可以使用 smember 来随机获取一个元素。同时,采用
@EnableCaching
开启声明式缓存支持,这种注解缓存是对于缓存使用的抽象,通过在代码之中的注释就可以达到缓存的效果。
Zset有序集合
- 有序集合,由唯一的,不重复的字符串元素组成。有序集合之中,每个元素都关联了一个浮点值,称为score。 可以看做是一个hash和集合的混合体,score 就是 hash 的key。
- 有序集合之中的元素就是按序存储的,而不是在请求的时候才排序的
Hash-哈希
- Redis的哈希值是字符串字段和字符串之间的映射。
- 哈希之中的字段数量没有限制,所以可以在应用程序用不同的方式来使用哈希
RedisConfig
在RedisConfig 之中,有:
- CacheManager : 选择 Redis 作为默认的缓存工具
- RedisTemplate : 配置连接工厂,并且配置序列化和反序列化redis的value的方法与序列化模式
- 对各种类型的操作:String , List , Set , ZSet , Hash。但是大部分只是封装本身具有的方法
对于封装本身就有的方法的情况,一般是新建一个类,对于这个类的某些参数进行默认配置的情况才会做很多个的封装。在本教程之中的这个封装必要性不大。
RedisService
这个又犯了我们前面所说这个“没有必要封装”的问题。很多都是针对RedisTemplate自己所有的方法进行单纯包装而已。但是还是总结一下。
- boolean existsKey : 检查 Key 是否存在
- void renameKey:重命名Key。如果newKey已经存在就覆盖newKey的原值
- renameKeyNotExist:在newKey不存在的时候才进行重命名。
- deleteKey(String key):删除Key
- deleteKeys:删除多个Key
- deleteKey(Collection<String> keys):删除 Key的集合
- void expireKey:设置Key的生命周期
- void expireKeyAt:指定key 在指定的日期过期
- long getKeyExpire: 查询key的生命周期
- void persistKey:将Key设置为永远有效
RedisKeyUtil
是Redis的Key工具类。redis的key形式为:表名:主键名:主键值:列名
注解缓存的使用
@Cacheable
:在方法执行之前Spring先查看缓存之中是否有数据,如果有数据,则直接返回缓存数据;没有则调用方法并将方法返回值放入缓存@CachePut
:将方法的返回值放入缓存@CacheEvict
: 将缓存之中的数据删除掉。