• Redis集群与spring的整合


    上一篇详细的赘述了Redis的curd操作及集群的搭建。下面我们开始将他整合到我们实际的项目中去。我的项目采用的是标准的ssm框架,ssm框架这里不说,直接开始整合。

    • 首先在maven管理中将我们的jar包引入
    <!--1.7.2 开始支持Redis 集群-->
    <dependency>                            
        <groupId>org.springframework.data</groupId> 
        <artifactId>spring-data-redis</artifactId>
        <version>1.7.2.RELEASE</version>
    </dependency>
    <!-- Redis 缓存Jar -->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.9.0</version>
    </dependency>
    
    <!--下面就是spring的maven坐标了,这里就不写了,读者自己引入-->
    • 在spring配置文件中我们可以进行配置Redis,但是为了将Redis分离容易修改我将它卸载另外一个xml文件中,只要在spring配置文件中引入这个Redis配置文件就行了。

    这里写图片描述

    • 下面所有的记录都是在Redis这个配置文件进行操作的。

    Redis连接池配置

    • 这里只是将设置连接池的一些基本属性,比如说最大连接数,连接前属性判断等
    <bean id="redisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
            <property name="maxTotal" value="${redis.maxTotal}" />
            <property name="maxIdle" value="${redis.maxIdle}" />
            <property name="maxWaitMillis" value="${redis.maxWait}" />
            <property name="testOnBorrow" value="${redis.testOnBorrow}" />
        </bean>
    • maxIdle:控制一个pool最多有多少个状态为idle的jedis实例;

    • 在borrow一个jedis实例时,是否提前进行alidate操作;如果为true,则得到的jedis实例均是可用的

    • maxWaitMillis : 表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;

    Redis集群配置

    这里我们就是将我们上一篇开启的Redis服务引入到项目中来。clusterNodes就是我们一个一个的Redis服务。

    <!-- Redis集群配置 -->
         <bean id="redisClusterConfig" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
            <property name="maxRedirects" value="3"></property>
            <property name="clusterNodes">
                <set>
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="127.0.0.1"></constructor-arg>
                        <constructor-arg name="port" value="7000"></constructor-arg>
                    </bean>
    
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="127.0.0.1"></constructor-arg>
                        <constructor-arg name="port" value="7004"></constructor-arg>
                    </bean>
                    <bean class="org.springframework.data.redis.connection.RedisNode">
                        <constructor-arg name="host" value="127.0.0.1"></constructor-arg>
                        <constructor-arg name="port" value="7005"></constructor-arg>
                    </bean>
                </set>
            </property>
        </bean> 

    Redis连接工厂

    我们将上面的Redis服务节点和连接池引入到工厂中,有工程去生产一个可用的jedis提供我们进行缓存的CURD操作!!

    <!-- ReDis连接工厂 -->
        <bean id="redis4CacheConnectionFactory"
            class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
            <constructor-arg name="clusterConfig" ref="redisClusterConfig" />
            <property name="timeout" value="${redis.timeout}" />
            <property name="poolConfig" ref="redisPoolConfig" />
        </bean>

    Redis模板

    提供了jedis进行操作我们就要放道模板里面给我们调用!。

    <!-- 存储序列化 -->
        <bean name="stringRedisSerializer"
            class="org.springframework.data.redis.serializer.StringRedisSerializer" />
    
        <!-- 集群Resis使用模板 -->
        <bean id="clusterRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
            <property name="connectionFactory" ref="redis4CacheConnectionFactory" />
            <property name="keySerializer" ref="stringRedisSerializer" />
            <property name="hashKeySerializer" ref="stringRedisSerializer" />
            <property name="valueSerializer" ref="stringRedisSerializer" />
            <property name="hashValueSerializer" ref="stringRedisSerializer" />
        </bean>

    项目调用

    在配置文件中都已经将jedis配置好了,我们只需要通过这个模板就可以对Redis进行CURD操作了。下面是个简单的列子

    clusterRedisTemplate.execute(new RedisCallback<Long>() {
                public Long doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    byte[] keyb = key.getBytes();
                    byte[] valueb = toByteArray(value);
                    // 判断当前值是否已经存在
                    if (connection.exists(keyb)) {
                        // 删除原数据
                        connection.del(keyb);
                    }
                    connection.set(keyb, valueb);
                    return 1L;
                }
            });

    源码探究竟

    在RedisClusterConfiguration类中我们传入的Redis服务node,我们设置的是property然后该类中就开始执行下面代码
    这里写图片描述

    然后我们在工厂中传入这些节点,

    这里写图片描述

    这个工厂给我提供了一个afterproperties方法,意思就是在这些参数设置完成之后执行的一个方法。

    这里写图片描述

    在这里我们可以看见一个creatPool的方法,这个就是去连接池里创建连接
    这里写图片描述

    Bug解决

    上面的部署 会出现一个问题,就是在项目中,每次初始化时会重连接池中选择一个可用的Redis服务连接,当这个Redis服务宕机后我们的项目还会继续连接这个Redis服务,我们只能从新启动项目,项目才会从新从连接池中选择新的Redis服务。

    • 解决办法 我在每次操作Redis时都去重构连接池,这样就保证我每次都会去连接池找一个正真可用的Redis服务。
    • 解决就是将RedisNode注入到项目中,每次都执行我们上次看到的creatPool方法
    /** Redis模板注入 */
        @Resource
        private RedisClusterConfiguration redisClusterConfig;
        private JedisConnectionFactory redis4CacheConnectionFactory;
        @Resource
        private RedisTemplate<String, Object> clusterRedisTemplate;
        //重构连接池
        private void init(){
            redis4CacheConnectionFactory=new JedisConnectionFactory(redisClusterConfig);
            redis4CacheConnectionFactory.afterPropertiesSet();
            clusterRedisTemplate.setConnectionFactory(redis4CacheConnectionFactory);
        }

    这样又出现问题了,每次都初始化连接池,这在连接池上很费性能,暂时没有解决办法,但是我初步想通过redis sentinel 来检测Redis集群中的Redis服务。当Redis宕机后通过sentinel 提供的API来通知项目重新去构建连接池,重新连接新Redis服务

  • 相关阅读:
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1553 数字反转(升级版)
    8.4 确定两个日期之间的月份数或年数
    (Java实现) 洛谷 P1553 数字反转(升级版)
  • 原文地址:https://www.cnblogs.com/zhangxinhua/p/8319218.html
Copyright © 2020-2023  润新知