springboot 整合Redis
0、导入 maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
1、SDR说明
Spring Data Redis(SDR),是SpringFramework提供的一套简化访问Redis的API,是对Jedis的又一层封装。
SDR集成了Jedis,JRedis,SRP,Lettuce这四种开源的Redis Connector,这些Connector都是针对于Redis的开源Java库。
其中,JRedis和SRP从spring-data-redis1.7开始,就不支持了。
2、RedisTemplate说明
SDR支持底层次的通过连接器connector连接到Redis,支持高层次的友好的模板类RedisTemplate,RedisTemplate是建立在低级别的connection基础之上。
RedisConnection接收或返回字节数组需要自身处理连接,比如关闭连接,而RedisTemplate负责处理串行化和反串行化,并且对连接进行管理。
RedisTemplate是线程安全的,能够用于多个实例中。
RedisTemplate是SDR的一个核心Helper类,该类是一个高级的抽象(对Jedis的又一层封装),它封装了对Redis中的数据的CRUD操作,包含“高级封装”。
---????-->
RedisTemplate默认选择java-based串行化,也可以切换为其它的串行化方式,
或者设置enabledDefaultSerializer为false或者设置串行化器为null,则RedisTemplate用raw byte arrays表示数据。
(1)高级封装(推荐使用)
高级封装的操作包含:OpsForValue(),OpsForList(),OpsForSet(),OpsForZset(),OpsForHash()等等。
SDR官方文档中对Redistemplate的介绍:
the template is in fact the central class of the Redis module due to its rich feature set. The template offers a high-level abstraction for Redis interactions.
通过Redistemplate可以调用ValueOperations和ListOperations等等方法,分别是对Redis命令的高级封装。
但是ValueOperations等等这些命令最终是要转化成为RedisCallback来执行的。
也就是说通过使用RedisCallback可以实现更强的功能,
SDR文档对RedisCallback的介绍:
RedisTemplate and StringRedisTemplate allow the developer to talk directly to Redis through the RedisCallback interface.
This gives complete control to the developer as it talks directly to the RedisConnection。
(2)从高级封装获得低级封装的过渡:
RedisOperations<String, Object> operations = opsForValue.getOperations();
3、RedisConnection提供了“低级封装”。
低级封装的操作是通过连接到Redis的Connection对象,直接对Redis数据进行操作。
低级封装的核心是:
redisTemplate.execute(
new RedisCallback(){
// .....
}
)
=========== redis 源码头=============================
RedisTemplate的使用
这个类作为一个模版类,提供了很多快速使用redis的api,而不需要自己来维护连接,事务。
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V> {
private boolean enableTransactionSupport = false;
private boolean exposeConnection = false;
private boolean initialized = false;
private boolean enableDefaultSerializer = true;
private RedisSerializer<?> defaultSerializer = new JdkSerializationRedisSerializer();
private RedisSerializer keySerializer = null;
private RedisSerializer valueSerializer = null;
private RedisSerializer hashKeySerializer = null;
private RedisSerializer hashValueSerializer = null;
private RedisSerializer<String> stringSerializer = new StringRedisSerializer();
private ScriptExecutor<K> scriptExecutor;
// cache singleton objects (where possible)
private ValueOperations<K, V> valueOps;
private ListOperations<K, V> listOps;
private SetOperations<K, V> setOps;
private ZSetOperations<K, V> zSetOps;
================== 实战 ======================
package cn.test.config.data; import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig; import java.util.HashSet;
import java.util.Set; /**
* Created by Miraculous on 15/7/4.
*/
@Configuration
public class RedisConfig { @Value("${test.data.redis.defaultExpiration}")
private Long defaultExpiration;
@Value("${test.redis.master.host}")
private String masterHost;
@Value("${test.redis.master.port}")
private int masterPort;
@Value("${test.redis.master.name}")
private String masterName;
@Value("${test.redis.sentinel1.host}")
private String sentinel1Host;
@Value("${test.redis.sentinel1.port}")
private int sentinel1port;
@Value("${test.redis.sentinel2.host}")
private String sentinel2Host;
@Value("${test.redis.sentinel2.port}")
private int sentinel2port;
@Value("${test.redis.sentinel3.host}")
private String sentinel3Host;
@Value("${test.redis.sentinel3.port}")
private int sentinel3port; /**
连接工厂
*/
private RedisConnectionFactory generateDevConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName(masterHost);
factory.setPort(masterPort);
factory.setUsePool(true);
factory.setConvertPipelineAndTxResults(true);
JedisPoolConfig poolConfig = generatePoolConfig();
factory.setPoolConfig(poolConfig); // 注入连接池
factory.afterPropertiesSet();
return factory;
} private RedisConnectionFactory generateReleaseConnectionFactory() {
RedisSentinelConfiguration sentinelConfiguration = new RedisSentinelConfiguration();
RedisNode master = new RedisNode(masterHost, masterPort);
master.setName(masterName);
Set<RedisNode> sentinels = new HashSet<>();
RedisNode sentinel1 = new RedisNode(sentinel1Host, sentinel1port);
RedisNode sentinel2 = new RedisNode(sentinel2Host, sentinel2port);
RedisNode sentinel3 = new RedisNode(sentinel3Host, sentinel3port);
sentinels.add(sentinel1);
sentinels.add(sentinel2);
sentinels.add(sentinel3);
sentinelConfiguration.setMaster(master);
sentinelConfiguration.setSentinels(sentinels);
JedisPoolConfig poolConfig = generatePoolConfig();
JedisConnectionFactory factory = new JedisConnectionFactory(sentinelConfiguration, poolConfig);
factory.setHostName(masterHost);
factory.setPort(masterPort);
factory.setTimeout(10000);
factory.setUsePool(true);
factory.setConvertPipelineAndTxResults(true);
factory.afterPropertiesSet();
return factory;
} /**redis连接池基本配置
*/
private JedisPoolConfig generatePoolConfig() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMinIdle(20);
poolConfig.setMaxTotal(300);
poolConfig.setMaxWaitMillis(5000);
poolConfig.setTestOnBorrow(true);
return poolConfig;
} @Bean(name = "redisConnectionFactory")
RedisConnectionFactory factory() {
if (StringUtils.isEmpty(masterName)) {
return generateDevConnectionFactory();
} else {
return generateReleaseConnectionFactory();
}
} @Bean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory factory) {
final RedisTemplate<String, Object> template = new RedisTemplate<>();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer(); template.setEnableTransactionSupport(false); //是否启用事务支持
template.setKeySerializer(stringRedisSerializer); //keySerializer:这个是对key的默认序列化器。默认值是StringSerializer。
template.setHashKeySerializer(stringRedisSerializer);//对hash结构数据的hashkey序列化器,默认值是取自DefaultSerializer的JdkSerializationRedisSerializer。
template.setValueSerializer(jdkSerializationRedisSerializer); //这个是对value的默认序列化器,默认值是取自DefaultSerializer的JdkSerializationRedisSerializer。
template.setDefaultSerializer(jdkSerializationRedisSerializer);
template.setConnectionFactory(factory); // 注入工厂
return template;
} @Bean(name = "stringRedisTemplate")
public RedisTemplate<String, String> stringRedisTemplate(
RedisConnectionFactory factory) {
final RedisTemplate<String, String> template = new RedisTemplate<>();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setEnableTransactionSupport(true);
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setValueSerializer(stringRedisSerializer);
template.setDefaultSerializer(stringRedisSerializer);
template.setConnectionFactory(factory);
return template;
} @Bean(name = "cacheManager")
public CacheManager cacheManager(RedisTemplate<String, Object> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setDefaultExpiration(defaultExpiration);
// cacheManager.setExpires(ImmutableMap.of("apixDistrictCache", 3600 * 24 * 7L));
cacheManager.setUsePrefix(true);
return cacheManager;
}
}
一、为什么要使用Serializer
因为redis是以key-value的形式将数据存在内存中,key就是简单的string,key似乎没有长度限制,不过原则上应该尽可能的短小且可读性强,无论是否基于持久存储,key在服务的整个生命周期中都会在内存中,因此减小key的尺寸可以有效的节约内存,同时也能优化key检索的效率。
value在redis中,存储层面仍然基于string,在逻辑层面,可以是string/set/list/map,不过redis为了性能考虑,使用不同的“encoding”数据结构类型来表示它们。(例如:linkedlist,ziplist等)。
所以可以理解为,其实redis在存储数据时,都把数据转化成了byte[]数组的形式,那么在存取数据时,需要将数据格式进行转化,那么就要用到序列化和反序列化了,这也就是为什么需要配置Serializer的原因。
二、 RedisTempalte的Serializer
用过jedis操作的都知道,所有connection的操作方法,都是传入字节数组。那么,将一个对象和字节相互转换,就需要通过序列化和反序列化。
模版方法中,Spring提供了默认的StringSerializer和JdkSerializer,第一个很简单,就是通过String.getBytes()来实现的。而且在Redis中,所有存储的值都是字符串类型的。所以这种方法保存后,通过Redis-cli控制台,是可以清楚的查看到我们保存了什么key,value是什么。
但是对于JdkSerializationRedisSerializer来说,这个序列化方法就是Jdk提供的了。
首先要求我们要被序列化的类继承自Serializable接口,然后通过,然后通过Jdk对象序列化的方法保存。
(注:这个序列化保存的对象,即使是个String类型的,在redis控制台,也是看不出来的,因为它保存了一些对象的类型什么的额外信息)

这么一长串,其实就是一个int类型的123。
三、事物支持
enableTransactionSupport:是否启用事务支持。我们在代码中搜索下用到这个变量的地方,会看到,在调用RedisCallback之前,有一行代码是如果启用事务支持,那么conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport),也就是说,系统自动帮我们拿到了事务中绑定的连接。
可以在一个方法的多次对Redis增删该查中,始终使用同一个连接。但是,即使使用了同样的连接,没有进行connection.multi()和connection.exec(),依然是无法启用事务的。
我没有仔细的查阅代码,但是可以知道的是,Spring已经对这个,给了我们一个更好的支持:@Transactional
在调用RedisTempalte中的execute()方法的地方,加入这个注解(是spring包下面提供的,不要引用成rt包下的注解),能让这个方法中的所有execute,自动加入multi()以及异常的回滚或者是正常运行时候的提交!
redis对事务提供支持,包括multi,exec,discard命令,这些命令也能用于RedisTemplate,然后redisTemplate不保证用相同的连接在同一个事务执行所有操作。
SDR提供SessionCallback接口用于同线程的多操作执行。
四、 RedisSerializer 接口 的是实现子类
public interface RedisSerializer<T> {
}

其中JdkSerializationRedisSerializer和StringRedisSerializer是最基础的序列化策略,
其中“JacksonJsonRedisSerializer”与“OxmSerializer”都是基于stirng存储,因此它们是较为“高级”的序列化(最终还是使用string解析以及构建java对象)。
基本推荐使用JdkSerializationRedisSerializer和StringRedisSerializer,因为其他两个序列化策略使用起来配置很麻烦,
如果实在有需要序列化成Json和XML格式,可以使用java代码将String转化成相应的Json和XML。
springboot 整合Redis的更多相关文章
- SpringBoot整合Redis、ApachSolr和SpringSession
SpringBoot整合Redis.ApachSolr和SpringSession 一.简介 SpringBoot自从问世以来,以其方便的配置受到了广大开发者的青睐.它提供了各种starter简化很多 ...
- SpringBoot整合Redis及Redis工具类撰写
SpringBoot整合Redis的博客很多,但是很多都不是我想要的结果.因为我只需要整合完成后,可以操作Redis就可以了,并不需要配合缓存相关的注解使用(如@Cacheable). ...
- SpringBoot 整合 Redis缓存
在我们的日常项目开发过程中缓存是无处不在的,因为它可以极大的提高系统的访问速度,关于缓存的框架也种类繁多,今天主要介绍的是使用现在非常流行的NoSQL数据库(Redis)来实现我们的缓存需求. Spr ...
- SpringBoot系列十:SpringBoot整合Redis
声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:SpringBoot 整合 Redis 2.背景 Redis 的数据库的整合在 java 里面提供的官方工具包:jed ...
- springboot整合redis(注解形式)
springboot整合redis(注解形式) 准备工作 springboot通常整合redis,采用的是RedisTemplate的形式,除了这种形式以外,还有另外一种形式去整合,即采用spring ...
- springboot整合redis(简单整理)
Redis安装与开启 我这里是在windows上练习,所以这里的安装是指在windows上的安装,操作非常简单,点击https://github.com/MicrosoftArchive/redis/ ...
- SpringBoot整合redis哨兵主从服务
前提环境: 主从配置 http://www.cnblogs.com/zwcry/p/9046207.html 哨兵配置 https://www.cnblogs.com/zwcry/p/9134721. ...
- springboot整合redis——redisTemplate的使用
一.概述 相关redis的概述,参见Nosql章节 redisTemplate的介绍,参考:http://blog.csdn.net/ruby_one/article/details/79141940 ...
- 九、springboot整合redis二之缓冲配置
1.创建Cache配置类 @Configuration @EnableCaching public class RedisCacheConfig extends CachingConfigurerSu ...
- 三:Springboot整合Redis
一:springboot整合redis redis版本:3.0.0 运行环境:linux 1.安装redis 1.1安装gcc yum install gcc-c++ 1.2解压redis.3.0.0 ...
随机推荐
- 用淘宝ip地址库查ip
这是一个通过调用淘宝ip地址库实现ip地址查询的功能类 using System; using System.Collections.Generic; using System.Linq; using ...
- Visual Studio Code 怎么支持中文
这其实是编码问题 和字体什么的没有关系,在VSCode中默认是用UTF-8编码方式打开文件,只要你的文件是这个编码就能正常打开如果不是,不进行设置VSCode是不会自动切换编码方式打开 手动可以Reo ...
- rpm 命令
这些事rpm的常用参数!!! 你可以在linux下man 一下rpm就知道了!!! 不过是英文的,不然你可以百度一下rpm就知道了额!!! 下面我帮你贴几个!!!!rpm 常用命令1.安装一个包 # ...
- 【Delphi】获取EIP
var EIP: Cardinal; procedure GetEIP(); stdcall; asm pop eax; mov EIP,eax; push eax; end; procedure T ...
- PHPCMS 模板制作标签
内容模块: 栏目调用1: {pc:content action="category" catid="0" num="25" siteid=& ...
- phpcms使用细节
1.在模板中使用php语句 <?php for ($i=0; $i < 10; $i++) { echo $i."#######<br>"; }?& ...
- SQL 查询总结
参考资料: SELECT 查询语句格式与简单查询 SQL中distinct的用法 SQL 查询总结
- scanf 格式化字符串详解
scanf格式控制的完整格式: % * m l或h 格式字符 ①格式字符与printf函数中的使用方式相同,以%d.%o.%x.%c.%s.%f.%e,无%u格式.%g ...
- php 快速排序法
function quicksort(array $arr = array()){ $len = count($arr); if ($len > 1) { $key = $arr[0]; $l_ ...
- 分词工具ICTCLAS5.0使用心得
接触自然语言处理有一年多了,最基本的一些自然是分词,词性标注,命名实体识别之类的知识,有些应用知道原理是一回事,自己动手做起来又是另外一回事了.最近又开始重操旧业:分词.分词最著名的自然就是中科院的分 ...