上一篇简单介绍了Redis,本文介绍一下如何操作Redis。对于现有的操作Redis比较知名的框架有Jedis(历史悠久)和Lettuce(后来居上,大有赶超之势,推荐使用lettuce,他是基于netty实现的非阻塞redis客户端,并且同时提供同步和异步的API,具体介绍请移步官网)。SpringData对Jedis与Lettuce做了封装方便我们开发,这里主要介绍一下Spring-Redis的使用。
搭建Spring-Redis环境
首先建立Spring Boot项目,maven文件如下:
maven文件Redis的配置类如下:
和JDBC与MQ一样,要连接上Redis,我们首先需要先注入连接工厂,Spring-Redis对应Jedis和Lettuce的连接工厂分别是JedisConnectionFactory和LettuceConnectionFactory。
注入连接工厂后,相信大家已经很熟悉Spring的套路了,Spring通过RedisTemplate来操作redis(注:因为我们平常对redis都是字符串操作,spring提供了StringRedisTemplate方便我们开发)。
以上基本的环境就搭建好了,接下来让我们编写相关方法对Redis进行操作。
简单测试:
为了方便起见,我们直接将操作写在controller里,代码格式也瞎写了。
启动项目,当我们访问 “redis/add” 时,就会看到刚刚存入Redis的Person字符串了。注意上面的ValueOperations,他是Spring提供给我们方便操作Redis 中值数据类型为String的类(还记得Redis中的数据类型有多少吗?),Spring对Redis中每个数据类型都提供了对应的操作类。操作类也可以通过redisTemplate.opsForValue()方法获取。注意,如果你用的开发工具是Idea,resource注解按上面的写法注入时会提示注入错误,这时需要我们修改一下Idea中关于Spring 注入的提示级别即可。
序列化器:
上面我们存入的是字符串,如果我想存入一个我们自定义的JavaBean呢?Spring也为我们提供了极其方便得方法使我们可以直接存入,我们调用redisTemplate.opsForHash().put("t","l",new Person(2,"zz"));,我们发现此时并不需要进行手动的将其转换为字符串,这是因为Spring提供了默认的JdkSerializationRedisSerializer序列化器,它在我们存入的时候自动帮我们进行序列化。默认的序列化器由名字可知,使用的是JDK的序列化机制,这就要求我们的bean需要实现Serializable接口。Spring提供了很多其他的序列化器,比如支持json的Jackson2JsonRedisSerializer,支持xml的OxmSerializer,要使用他们只需要在template中进行一下set即可。
事务操作:
Redis的事务可以理解为一个批量执行脚本,单个 Redis 命令的执行是原子性的,但 Redis 事务的执行并不是原子性的,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。这是Redis事务与普通数据库事务行为的不同之处。我们可以在事务执行时对指定的key进行watch操作,这样在事务执行过程中若有其他线程对该key做了操作,那么事务会被打断。
让我们使用Spring完成一个事务的操作,由于默认情况下Spring不保证事务中所有的操作都通过一个connection完成,Spring提供了SessionCallback来保证事务中的操作在一个连接上完成。
返回值txResult是一个LIst,每一项代表了语句是否执行成功,访问/redis/tx我们可以看到返回值为1并且控制台成功打印,表明该条语句执行成功。
我们也可以在Redis的config类中开启全局的事务配置,这样的话默认情况下所有的set操作都会在事务中执行,读操作不会在事务中执行。
批量操作:
Redis提供了pipline来进行批量操作,嗯。。使用方法和事务操作类似,也是使用sessionCallback,就不想截图了。。。
对于LUA脚本的支持:
由于多个Redis命令原子化时,Lua脚本为我们提供了支持,我们一般使用Lua脚本作为Redis分布式锁的解锁工作(加锁使用set命令,忘记那个版本后set命令可以指定多个参数,通过她我们可以实现加锁的原子性),Spring下开发LUA脚本十分简单,他为我们提供了非常Java化的操作方式,我们先将脚本注册为bean
接下来使用就跟我们正常调用dao,service里的方法一样了。
对于缓存的支持:
Spring-Redis通过Spring-Cache实现缓存。
我们先来说一下Spring-Cache,Spring-Cache主要缓存的是方法的结果,这样对于一些传递参数基本不变且执行成本较高的方法比较适合。Spring本身并不提供缓存存储的地方,只是缓存的逻辑不需要自己手动编写,Spring通过CacheManager来实现这种行为。一般常见的缓存管理器由ConcurrentMap,Ecache(单机缓存的性能很高),或者是本文的Redis。项目中使用Spring缓存一般通过注解的方式,使用也很简单,让我们简单介绍他的常用注解。
@Cacheable(cacheNames="",key="",sync=true,condition="",unless=""):方法级别,表明该方法会将执行结果存入缓存,下次使用相同参数的调用时会直接返回结果。该注解可以指定多个cacheNames,即多份缓存,但是一般情况下我们都会指定一个name。key代表我们取缓存时的key值,因为缓存本质上是map的形式,我们需要通过key获取缓存的value,其中key的指定可以使用EL表达式。sync代表是否将该方法转为同步方法用于多线程访问的情况。condition代表缓存该方法的条件。unless类似于condition也可以用于判断是否缓存该结果,与condition不同的是,他是在方法执行完成之后才进行判断。
@CachePut(cacheNames="", key=""):用于将方法的执行结果放入缓存。用于缓存同步,比方说我已经将查询结果放入缓存,这时我对数据库内容进行了更新,但缓存中还是旧的数据,这时就需要在数据库更新方法上用到该注解。
@CacheEvict(cacheNames="",allEntries=true):即缓存清除,和@CachePut对立,allEntries代表是否删除该缓存空间中所有的缓存,beforeInvocation属性代表是否在方法体执行之前进行删除。
@Caching:支持同时写入多个@CacheEvict或@CachePut。
@CacheConfig:类级别的注解,用于配置一些公用值。
@EnableCaching:这个就不用说了。。Spring Boot所有开启xx功能的注解都是以Enable开头。
说完了基础,接下来我们就来配置Redis的cacheManager,然后在启动类上加上@EnableCaching注解
这个是最简单的cacheManager配置方式,如果想进行其他的个性化设置的话,可以通过RedisCacheManager的build模式进行创建,并设置相应的RedisCacheConfiguration,具体设置项可以去官网查看,这里不详细介绍了。配置完之后,给出测试方法
我们可以看到,当我们连续两次请求get时并且参数相同,控制台只会打印一次,说明我们的缓存生效。
此时我们查看Redis数据库,也会看到Spring写进Redis的缓存。
Redis Repositories:
如果你使用过Spring-JPA的话对Repositories应该不会陌生,我们通过继承各种Repositories接口后就可以直接使用其中的方法完成增删改查等一系列操作。Redis Repositories与其类似,但是它主要用于Redis的Hash类型,通过它我们可以方便的进行实体类与Redis hash类型的转换。
其中的@RedisHash注解表明存入Redis中hash的名称,@id代表hash中的key。接下来需要在Redis配置类上加入@EnableRedisRepositories注解,并编写接口实现相应的Repository接口。
这里我们继承CrudRepository接口,对于该系列接口不熟悉的同学请移步Spring-JPA。
接下来让我们编写测试方法。
我们可以看到已经可以取出保存进去的user对象了。让我们再来看下redis数据库中的内容:
可以看到,我们的user对象已经正常的存入redis中了。如果我们想要设置存在redis中对象的过期时间,只需要在实体类中加入表示时间的字段并加上@TimeToLive注解即可。
end:
好了,关于Spring-Redis就差不多介绍完了,有想详细了解的同学请移步官网。
网友评论