为了账号安全,请及时绑定邮箱和手机立即绑定

spring整合redis

标签:
Java

redis概述

参考:《spring boot 整合redis之缓存》之redis概述章节;

  • spring整合reids

  • 项目中使用redis做缓存管理

  • 注意事项(问题及解决方案)

项目源码地址:
码云地址:https://gitee.com/wyait/project.git
github地址:https://github.com/wyait/project.git

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 */// @Componentpublic 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

  • 访问:http://127.0.0.1:8063/addHash ; 原代码中key的值也是: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/addHash  
    结果:hello world  
    redis桌面工具中数据显示:  

访问: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//更新数据OKtry {    //避免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桌面工具会对其进行统一分类,方便查看!  

注意

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

项目源码地址:
码云地址:https://gitee.com/wyait/project.git
github地址:https://github.com/wyait/project.git

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消