官网:https://projects.spring.io/spring-data-redis/
应用场景
1、数据库缓存
2、缓存微信的access_token,因为同一时间只有最后一次获取的access_token有效,因此把access_token放在一个地方最为合理
3、会话共享
IDEA配置
1、Maven新增依赖
<dependency>
<groupId>redis.clients</groupId> <!-- Redis客户端 -->
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId> <!-- Spring 集成 Redis -->
<version>2.0.10.RELEASE</version>
</dependency>
基本使用
Jedis jedis = new Jedis ("localhost", 6379 );
// jedis.auth("password"); // 如果需密码
try {
jedis.set("test", "1") ;
System.out.println(jedis.get("test"));
} finally {
jedis.close();
}
连接池使用
JedisPoolConfig poolCfg =new JedisPoolConfig() ;
poolCfg.setMaxIdle(50); // 最大空闲数
poolCfg.setMaxTotal(100) ; // 最大连接数
poolCfg.setMaxWaitMillis(20000); // 最大等待毫秒数
JedisPool pool = new JedisPool(poolCfg, "localhost");
Jedis jedis = pool.getResource() ;
// jedis.auth("password"); // 如果需密码
try {
jedis.set("test", "1") ;
System.out.println(jedis.get("test"));
} finally {
jedis.close();
}
Spring使用
1、Spring 配置文件中加入
<!-- 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="2048" />
<property name="maxIdle" value="200" />
<property name="numTestsPerEvictionRun" value="1024" />
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<property name="minEvictableIdleTimeMillis" value="-1" />
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<property name="maxWaitMillis" value="1500" />
<property name="testOnBorrow" value="true" />
<property name="testWhileIdle" value="true" />
<property name="testOnReturn" value="false" />
<property name="jmxEnabled" value="true" />
<property name="blockWhenExhausted" value="false" />
</bean>
<bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:use-pool="true" p:host-name="localhost" p:port="6379"> <!-- 连接工厂 -->
<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnFactory"/> <!-- Redis操作类 -->
2、注入与使用
@Autowired // 自动注入
private RedisTemplate<String, Object> redisTemplate; // 定型,指明要往redis存的对象类型
City city = new City(); // City 必须可序列化
city.setCityName("广州");
redisTemplate.opsForValue().set("city_1", city); // 存入
// RedisTemplate的泛型被定型为City后,这里就不用强制类型转换了
City city1 = redisTemplate.opsForValue().get("city_1"); // 上下两次操作可能用的不是同一个连接
redisTemplate.opsForHash() // Hash数据操作
redisTemplate.opsForList() // List数据操作
redisTemplate.opsForSet() // Set数据操作
redisTernplate.opsForZSet() // ZSet数据操作
SessionCallback callBack = new SessionCallback<City>(){ // 定型为execut要返回的类型
public City execute(RedisOperations ops) throws DataAccessException {
ops.multi(); // 开启事务来执行
ops.boundValueOps("role_l").set(city);
return (City) ops.boundValueOps("role_l").get() ;
}
};
city1 = (City) redisTemplate.execute(callBack); // 用同一个连接 执行
city1 = (City) redisTemplate.executePipelined(callBack) ; // 批量执行
订阅与发布
1、定义消息处理器
public class MessageListener{
public void handleMessage(String message){ };
public void handleMessage(Map message){ };
public void handleMessage(byte[] message){ };
public void handleMessage(Serializable message){ };
public void handleMessage(Serializable message, String channel){ };
}
2、xml中配置消息处理器
<bean id="listener" class="com.hogen.redis.MessageListener"/>
<redis:listener-container> <!-- 默认依赖的连接工厂的ID为 redisConnectionFactory -->
<redis:listener ref="listener" method="handleMessage" topic="topic1" />
</redis:listener-container>
3、发布消息
redisTemplate.convertAndSend("topic1", "消息1");
哨兵模式
1、配置Bean
<!-- 哨兵配置 -->
<bean id="sentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<property name="master">
<bean class="org.springframework.data.redis.connection.RedisNode">
<property name="name" value="mymaster"></property> <!-- master名称,与Redis的sentinel.conf中的配置一致 -->
</bean>
</property>
<property name="sentinels">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode"> <!-- 可以配置多个哨兵 -->
<constructor-arg name="host" value="47.105.112.41"></constructor-arg>
<constructor-arg name="port" value="26379"></constructor-arg> <!-- 哨兵的端口,Spring通过哨兵间接访问Redis -->
</bean>
</set>
</property>
<property name="database" value="0"></property> <!-- 使用redis的第0个db -->
</bean>
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
<constructor-arg name="sentinelConfig" ref="sentinelConfiguration"></constructor-arg>
</bean>
<bean id="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="redisConnectionFactory">
<property name="keySerializer" ref="stringRedisSerializer"/> <!-- 指定序列化器,否则key会有乱码 -->
<property name="valueSerializer" ref="jdkSerializationRedisSerializer"/>
</bean>
集群模式
<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
<property name="maxRedirects" value="${redis.maxRedirects}"></property>
<property name="clusterNodes">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host1}"></constructor-arg>
<constructor-arg name="port" value="${redis.port1}"></constructor-arg>
</bean>
<!-- 后面还有5个 -->
</set>
</property>
</bean>
<!-- 连接工厂 -->
<bean id="jeidsConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<constructor-arg name="clusterConfig" ref="redisClusterConfiguration"/>
<constructor-arg name="poolConfig" ref="jedisPoolConfig"/>
</bean>
Redis 用于缓存 mysql 数据
java读操作
1、尝试从redis读数据
2、redis中没有该数据,则从mysql中读取,读出后写入redis,并设置超时时间
java写操作
1、写入mysql
2、写入Redis,并设置超时时间
java删操作
1、从mysql删除
2、从Redis删除
Spring 缓存机制
1、装载RedisCacheManager,在能被<context:component-scan>扫描到的类中加入
// 可以定义一个初始化的类,专门用于装载框架的Bean
@Bean(name="redisCacheManager")
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
return RedisCacheManager.create(connectionFactory);
}
2、启用缓存注解驱动
<!-- 启用注解驱动,即将缓存机制应用于@Cacheable注解的方法 -->
<cache:annotation-driven cache-manager="redisCacheManager"/>
3、注解Service方法
// @Cacheable实现 读操作的缓存机制。redis中没有对应的数据 才执行该方法,并将该方法的返回值存入redis;redis中的key为 cacheNames::key
// 用Spring表达式语言(SpringEL)获取方法的参数;不指定key 则为所有参数的toStirng;如果有空格、符号,会导致key有双引号,可以用base64对值编码来避免
// 在搜索场景中,要扣除无限值的字段,否则可能导致 key 爆炸
@Cacheable(cacheNames="city",key="'city_' + #id", condition="#query.search==null")
public City getCity(long id){
return cityMapper.getCity(id);
}
// @CachePut实现 写操作的缓存机制。执行该方法,并将该方法的返回值存入redis
@CachePut(cacheNames="city",key="'city_' + #city.id")
public City setCity(City city){
return cityMapper.setCity(city);
}
// @CacheEvict实现 删操作的缓存机制。执行该方法,从redis删除数据
@CacheEvict(cacheNames="city",key="'city_' + #id")
public City setCity(long id){
return cityMapper.rmCity(id);
}
SpringBoot 整合 redis
0、mybatis-config.xml
<setting name="lazyLoadingEnabled" value="false"/> <!--如果为true,会出错-->
1、pom.xml
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、application.yml
redis:
host: r-2zerb3ixj026hfuvhp.redis.rds.aliyuncs.com
port: 6379
password: ****
database: 0
timeout: 1000ms
lettuce: # 也可以是 jedis,jedis 和 lettuce 都是 redis client
pool:
max-active: 200
max-wait: -1ms
max-idle: 10
min-idle: 0
3、主类中注解 @EnableCaching
4、RedisTemplate 与 StringRedisTemplate
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig {
@Bean
// 使用 JdkSerializationRedisSerializer 进行序列化,将数据序列化成字节数组
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
// 使用 StringRedisSerializer 进行序列化,将数据序列化成字符串
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
// 设置 数据库 缓存 的默认有效时间
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().ntryTtl(Duration.ofHours(24)).
// 设置 key 的前缀,可以用于区分不同profile;会使 @Cacheable的cacheNames 失效
disableCachingNullValues().prefixKeysWith("dev::").
// 计算生成key的前缀
.computePrefixWith(cacheName -> profiles.concat("::").concat(cacheName).concat(":"));
RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).
cacheDefaults(config).transactionAware().build();
return redisCacheManager;
}
}
5、@Cacheable、@CachePut、@CacheEvict的使用与上文相同
6、使用redisTemplate、stringRedisTemplate、redisCacheManager
stringRedisTemplate.opsForValue().set("access_token", accessToken);
stringRedisTemplate.expire("access_token", duration, TimeUnit.SECONDS); // 设置过期时间
String accessToken = stringRedisTemplate.opsForValue().get("access_token");
Long millis = stringRedisTemplate.getExpire("access_token", TimeUnit.MILLISECONDS); // 获取过期时间
网友评论