spring整合redis

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
简介:

spring 整合redis

导入依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.7.5.RELEASE</version>
</dependency>

配置文件

redis.properties

redis相关参数文件:

#ip地址  
redis.host.ip=127.0.0.1
#端口号  
redis.port=6379  
#如果有密码  
redis.password=  
#客户端超时时间单位是毫秒 默认是2000  
redis.timeout=3000  

#最大空闲数  
redis.maxIdle=6  
#连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal  
#redis.maxActive=600  
#控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性  
redis.maxTotal=20  
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。  
redis.maxWaitMillis=3000  
#连接的最小空闲时间 默认1800000毫秒(30分钟)  
redis.minEvictableIdleTimeMillis=300000  
#每次释放连接的最大数目,默认3  
redis.numTestsPerEvictionRun=4  
#逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1  
redis.timeBetweenEvictionRunsMillis=30000  

applicationContext-redis.xml

spring整合redis配置文件:

    <!--1,如果你有多个数据源需要通过<context:property-placeholder管理,且不愿意放在一个配置文件里,那么一定要加上ignore-unresolvable=“true" -->
    <context:property-placeholder location="classpath:redis.properties"
        ignore-unresolvable="true" />

    <!--2,注意新版本2.3以后,JedisPoolConfig的property name,不是maxActive而是maxTotal,而且没有maxWait属性,建议看一下Jedis源码或百度。 -->
    <!-- redis连接池配置 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!--最大空闲数 -->
        <property name="maxIdle" value="${redis.maxIdle}" />
        <!--连接池的最大数据库连接数 -->
        <property name="maxTotal" value="${redis.maxTotal}" />
        <!--最大建立连接等待时间 -->
        <property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
        <!--逐出连接的最小空闲时间 默认1800000毫秒(30分钟) -->
        <property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}" />
        <!--每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3 -->
        <property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}" />
        <!--逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1 -->
        <property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}" />
    </bean>

    <!--redis连接工厂 -->
    <bean id="jedisConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
        destroy-method="destroy">
        <property name="poolConfig" ref="jedisPoolConfig"></property>
        <!--IP地址 -->
        <property name="hostName" value="${redis.host.ip}"></property>
        <!--端口号 -->
        <property name="port" value="${redis.port}"></property>
        <!--如果Redis设置有密码 -->
        <!-- <property name="password" value="${redis.password}" /> -->
        <!--客户端超时时间单位是毫秒 -->
        <property name="timeout" value="${redis.timeout}"></property>
    </bean>

    <!-- redis操作模板,这里采用尽量面向对象的模板 -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <!-- 指定redis中key-value的序列化方式(此处省略) -->
    </bean>

    <!--redis工具类 (也可以通过注解的方式注入) -->
    <bean id="redisUtil" class="com.spring.redis.utils.RedisUtil">
        <property name="redisTemplate" ref="redisTemplate" />
    </bean>

RedisUtils工具类

代码片段:

package com.spring.redis.util;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;

/** 
 * 
 * @项目名称:common
 * @类名称:RedisUtil
 * @类描述:基于spring和redis的redisTemplate工具类;
 * @创建人:wyait
 * @创建时间:2017年12月8日 下午3:32:38 
 * @version:V1.0
 */
// @Component
public class RedisUtil {
    // 通过构造方法注入
    // @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /*
     * 如果使用注解注入RedisTemplate对象,则不需要该setter方法
     */
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /** 
     * String类型缓存获取 
     * @param key 键 
     * @return 值 
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /** 
     * String类型缓存保存 
     * @param key 键 
     * @param value 值 
     * @return true:成功;false:失败 
     */
    public boolean set(String key, Object value) {
        try {
            if (StringUtils.isNotEmpty(key) && null != value) {
                redisTemplate.opsForValue().set(key, value);
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

   // ... ...

}

测试

  • 访问:http://127.0.0.1:8063/add 
    结果:hello world 
    查看redis桌面工具,已有数据,虽然看不懂。。。如图: 
    image 
    乱码的原因是:RedisTemplate默认的使用org.springframework.data.redis.serializer.JdkSerializationRedisSerializer这个类进行序列化导致的,如果单独指定了redis的key-value序列化方式,就不会出现乱码的情况。 (源码中已解决乱码问题)

访问:http://127.0.0.1:8063/get 
结果:aaa

Caused by: redis.clients.jedis.exceptions.JedisDataException: WRONGTYPE Operation against a key holding the wrong kind of value
    at redis.clients.jedis.Protocol.processError(Protocol.java:127)

因为redis数据库中已经存在了相同的key, 而且key对应的值类型并不是HashMap或Object;再调用setHash时,就会抛出此错误。

解决:更改key的值;

访问:http://127.0.0.1:8063/getHash 
结果:{"user":{"id":1,"age":11,"name":"李四"}}

使用redis API做缓存管理

这里用RedisUtils工具类实现数据缓存; 
使用缓存注解,请参考:《spring boot 整合redis之缓存》之redis缓存管理;

项目中使用redis

项目中查询业务做缓存,必须在不影响正常业务的情况下,对数据进行缓存;具体做法:

  • 1,查mysql数据库和redis缓存结合使用; 
    查询业务:先查询redis缓存,有就返回数据;没有,直接查询mysql数据库; 
    代码片段:
// 从redis中缓存中获取详情数据
String redisString = "";
try {
    //避免redis异常影响到正常业务
    redisString=this.redisUtil.get("aaa:bbb");
} catch (Exception e) {
    //TODO
    LOGGER.error("redis get error");
}
if (StringUtils.isEmpty(redisString)) {
    //查询数据库
    //TODO
}

更新业务:先更新mysql数据库中的数据,更新成功;更新redis缓存中的数据;比如:添加数据,先添加到mysql中;在添加一条数据在redis中; 
代码片段:

//TODO
//更新数据OK
try {
    //避免redis异常影响到正常业务
    //更新redis中数据,并指定保存时间
    redisString=this.redisUtil.set("aaa:bbb","值",3600);
} catch (Exception e) {
    //TODO
    LOGGER.error("redis set error");
}
  • 2,对于redis操作,进行try...catch...处理;保证应用程序的可用性,如上面两段代码;

redis中key使用策略

Redis上踩过的一些坑-美团:http://blog.csdn.net/chenleixing/article/details/50530419 
redis内存使用优化:http://carlosfu.iteye.com/blog/2254572

(1) 使用Redis字符串数据结构, userId为key, weiboCount作为Value 
(2) 使用Redis哈希结构,hashkey只有一个, key="allUserWeiboCount",field=userId,fieldValue= weiboCount 
(3) 使用Redis哈希结构, hashkey为多个, key=userId/100, field=userId%100, fieldValue= weiboCount 
前两种比较容易理解,第三种方案解释一下:每个hashKey存放100个hash-kv,field=userId%100。。。

实际使用根据具体的业务而定,数据量没那么大的情况下,不用考虑内存优化的问题;

另外在使用String类型的key的时候,推荐用:

aaa:bbb

这种格式,这样在redis桌面工具中查看方便直观,针对key中有:的情况,redis桌面工具会对其进行统一分类,方便查看! 
image

注意

spring data redis会有版本冲突问题,导致启动异常;

异常情况:

aused by: java.lang.NoSuchMethodError: org.springframework.core.serializer.support.DeserializingConverter.<init>(Ljava/lang/ClassLoader;)V
    at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.<init>(JdkSerializationRedisSerializer.java:53)
  • 原因: 
    spring-data-redis版本:1.7.2.RELEASE ,不兼容spring 版本:4.1.3.RELEASE
  • 解决方案: 
    spring data redis版本不能高于:1.7.1.RELEASE

稳定版本:

spring版本:4.2.3.RELEASE - 4.3.9.RELEASE 
spring-data-redis版本:1.7.2.RELEASE - 1.7.11.RELEASE
jedis版本:2.9.0



本文转自 wyait 51CTO博客,原文链接:http://blog.51cto.com/wyait/2049866,如需转载请自行联系原作者

相关文章
|
NoSQL 安全 Java
深入理解 RedisConnectionFactory:Spring Data Redis 的核心组件
在 Spring Data Redis 中,`RedisConnectionFactory` 是核心组件,负责创建和管理与 Redis 的连接。它支持单机、集群及哨兵等多种模式,为上层组件(如 `RedisTemplate`)提供连接抽象。Spring 提供了 Lettuce 和 Jedis 两种主要实现,其中 Lettuce 因其线程安全和高性能特性被广泛推荐。通过手动配置或 Spring Boot 自动化配置,开发者可轻松集成 Redis,提升应用性能与扩展性。本文深入解析其作用、实现方式及常见问题解决方法,助你高效使用 Redis。
1243 4
|
NoSQL Java 关系型数据库
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
本文介绍在 Spring Boot 中集成 Redis 的方法。Redis 是一种支持多种数据结构的非关系型数据库(NoSQL),具备高并发、高性能和灵活扩展的特点,适用于缓存、实时数据分析等场景。其数据以键值对形式存储,支持字符串、哈希、列表、集合等类型。通过将 Redis 与 Mysql 集群结合使用,可实现数据同步,提升系统稳定性。例如,在网站架构中优先从 Redis 获取数据,故障时回退至 Mysql,确保服务不中断。
448 0
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
|
7月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
655 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
9月前
|
NoSQL Java Redis
Redis基本数据类型及Spring Data Redis应用
Redis 是开源高性能键值对数据库,支持 String、Hash、List、Set、Sorted Set 等数据结构,适用于缓存、消息队列、排行榜等场景。具备高性能、原子操作及丰富功能,是分布式系统核心组件。
743 2
|
11月前
|
消息中间件 缓存 NoSQL
基于Spring Data Redis与RabbitMQ实现字符串缓存和计数功能(数据同步)
总的来说,借助Spring Data Redis和RabbitMQ,我们可以轻松实现字符串缓存和计数的功能。而关键的部分不过是一些"厨房的套路",一旦你掌握了这些套路,那么你就像厨师一样可以准备出一道道饕餮美食了。通过这种方式促进数据处理效率无疑将大大提高我们的生产力。
353 32
|
NoSQL Java API
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Spring Boot 集成 Redis
本文介绍了在Spring Boot中集成Redis的方法,包括依赖导入、Redis配置及常用API的使用。通过导入`spring-boot-starter-data-redis`依赖和配置`application.yml`文件,可轻松实现Redis集成。文中详细讲解了StringRedisTemplate的使用,适用于字符串操作,并结合FastJSON将实体类转换为JSON存储。还展示了Redis的string、hash和list类型的操作示例。最后总结了Redis在缓存和高并发场景中的应用价值,并提供课程源代码下载链接。
2707 0
|
NoSQL Java Redis
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 安装
本教程介绍在 VMware 虚拟机(CentOS 7)或阿里云服务器中安装 Redis 的过程,包括安装 gcc 编译环境、下载 Redis(官网或 wget)、解压安装、修改配置文件(如 bind、daemonize、requirepass 等设置)、启动 Redis 服务及测试客户端连接。通过 set 和 get 命令验证安装是否成功。适用于初学者快速上手 Redis 部署。
395 0
|
NoSQL Java Redis
SpringBoot集成Redis解决表单重复提交接口幂等(亲测可用)
SpringBoot集成Redis解决表单重复提交接口幂等(亲测可用)
1020 0
|
NoSQL Java Redis
SpringBoot集成Redis
SpringBoot集成Redis
708 0
|
JSON 安全 Java
Springboot最全权限集成Redis-前后端分离-springsecurity-jwt-Token5
Springboot最全权限集成Redis-前后端分离-springsecurity-jwt-Token5
247 81