zoukankan      html  css  js  c++  java
  • Spring-data-redis操作redis cluster

         Redis 3.X版本引入了集群的新特性,为了保证所开发系统的高可用性项目组决定引用Redis的集群特性。对于Redis数据访问的支持,目前主要有二种方式:一、以直接调用jedis来实现;二、使用spring-data-redis,通过spring的封装来调用。下面分别对这二种方式如何操作Redis进行说明。

    一、利用Jedis来实现

          通过Jedis操作Redis Cluster的模型可以参考Redis官网,具体如下:

            Set<HostAndPort>  jedisClusterNodes = new HashSet<HostAndPort>();

              //Jedis Cluster will attempt to discover cluster nodes automatically

             jedisClusterNodes.add(new HostAndPort("10.96.5.183",9001));

             jedisClusterNodes.add(new HostAndPort("10.96.5.183",9002));

             jedisClusterNodes.add(new HostAndPort("10.96.5.183",9003));

            JedisCluster jc = new JedisCluster(jedisClusterNodes);

            jc.set("foo","bar");

            jc.get("foo";

    二、利用spring-data-redis来实现

          目前spring-data-redis已发布的主干版本都不能很好的支持Redis Cluster的新特性。为了解决此问题spring-data-redis开源项目组单独拉了一个315分支,但截止到目前尚未发布。下面在分析spring-data-redis源码的基础上配置spring实现操作Redis Cluster.下面分别针对XML和注入的方式进行说明。

        315分支gitHub下载路径如下:https://github.com/spring-projects/spring-data-redis

        315分支源码下载路径:http://maven.springframework.org/snapshot/org/springframework/data/spring-data-redis/1.7.0.DATAREDIS-315-SNAPSHOT/

    (1)采用setClusterNodes属性方式构造RedisClusterConfiguration

         代码目录结构如下所示:

             src

                 com.example.bean

                  com.example.repo

                 com.example.repo.impl

                 resources

        A.在resources目录下增加spring-config.xml配置,配置如下:

         <!--通过构造方法注入RedisNode-->

         <bean id="clusterRedisNodes1"   class="org.springframework.data.redis.connection.RedisNode"> 

                <constructor-arg value="10.96.5.183" />

               <constructor-arg value="9002" type="int" />

         </bean>

         ....

        <!--setter方式注入-->

        <bean id="redisClusterConfiguration"   class="org.springframework.data.redis.connection.RedisClusterConfiguration">

           <property name="clusterNodes">

                  <set>

                            <ref bean="clusterRedisNodes1"/>

                           <ref bean="clusterRedisNodes2"/>

                           <ref bean="clusterRedisNodes3"/>

                  </set>

           </property>

         <!--红色所示部分在从gitHub上获取的jar包中无对应setter方法,因此需要修改其对应的源码。

             另外,如果不设置clusterTimeOut值,源码中默认为2S。当集群服务器与客户端不在同一服务器上时,容易报:Could not get a resource from the Cluster;

                       如果不设置maxRedirects值,源码中默认为5。一般当此值设置过大时,容易报:Too many Cluster redirections -->

            <property name="clusterTimeOut"  value="10000" />

            <property name="maxRedirects"   value="5" />

        </bean>

      <!--setter方式注入,对应的属性需存在setterXXX方法-->

       <bean id="jedisPoolConfig"   class="redis.clients.jedis.JedisPoolConfig">

                <property name="maxToal" value="1000" />

               <property name="maxIdle" value="1000" />

               <property name="maxWaitMillis" value="1000" />

       </bean>

      <bean id="jedisConnFactory"   class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:use-pool="true">

               <constructor-arg ref="redisClusterConfiguration" />

               <constructor-arg ref="jedisPoolConfig" />

      </bean>

     <bean id="redisTemplate"   class="org.springframework.data.redis.core.RedisTemplatep:connection-factory-ref="jedisConnFactory" />

    <!--setter方式注入PersonRepoImpl-->

    <bean id="personRepo"  class="com.example.repo.impl.PersonRepoImpl">

           <property name="redisTemplate" ref="redisTemplate" />

    </bean>

    注:加载lua文件

    <bean id ="XXX" class="org.springframework.data.redis.core.script.DefaultRedisScript">

       <property name="location"  value="./redis/XXX.lua" />

      <property name="resultType" value="java.lang.Void" />

    </bean>

    com.example.repo.impl下增加PersonRepoImpl,主要包括属性private RedisTemplate<String,Bean>  redisTemplate(该属性存在setterXXX方法,对应property属性);

    利用redisTemplate.opsForHash().put()即可完成对Redis Cluster的操作。

     ClassPathXmlApplicationContext  context = new ClassPathXmlApplicationContext(new ClassPathResource("resources/spring-config.xml").getPath());

     Repo repo =(Repo)context.getBean("personRepo");

    (2)采用RedisClusterConfiguration(PropertySource<?> propertySource)方式构造RedisClusterConfiguration

      代码目录结构如下所示:

             src

                 com.redis.cluster.support.config

                           MonitorConfig

                 resources

                          spring-config.xml

                           redis.properties

       A.在resources目录下增加spring-config.xml配置,配置如下:

        <!--配置文件加载-->

         <context:property-placeholder location="resources/redis.properties"/>

        <context:property-placeholder location="resources/xxx.properties"/>

         <bean class="com.redis.cluster.support.config.MonitorConfig" />

        <!--对静态资源文件的访问-->

         <mvc:default-servlet-handler/>

         <mvc:annotation-driven />

         <context:component-scan base-package="com.redis.cluster"/>

      B.添加redis.properties文件

        spring.redis.cluster.nodes=10.48.193.201:7389,10.48.193.201:7388

        spring.redis.cluster.timeout=2000

        spring.redis.cluster.max-redirects=8

      C.编写初始化JedisConnectionFactory连接工厂的java类

        @Configuration

        public class MonitorConfig {

           @Value("${spring.redis.cluster.nodes}")

           private String clusterNodes;

           @Value("${spring.redis.cluster.timeout}")

           private Long timeout;

          @Value("${spring.redis.cluster.max-redirects}")

           private int redirects;

           @Bean

           public RedisClusterConfiguration getClusterConfiguration() {

                Map<String, Object> source = new HashMap<String, Object>();

                source.put("spring.redis.cluster.nodes", clusterNodes);

                source.put("spring.redis.cluster.timeout", timeout);

                source.put("spring.redis.cluster.max-redirects", redirects);

               return new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration", source));

              }

           @Bean

           public JedisConnectionFactory getConnectionFactory() {

               return new JedisConnectionFactory(getClusterConfiguration());

              }

          @Bean

           public JedisClusterConnection getJedisClusterConnection() {

               return (JedisClusterConnection) getConnectionFactory().getConnection();

              }

           @Bean

           public RedisTemplate getRedisTemplate() {

               RedisTemplate clusterTemplate = new RedisTemplate();

               clusterTemplate.setConnectionFactory(getConnectionFactory());

               clusterTemplate.setKeySerializer(new DefaultKeySerializer());

               clusterTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());

               return clusterTemplate;

              }

           }

         D.通过注解方式使用JedisClusterConnection和RedisTemplate

           @Autowired

           JedisClusterConnection clusterConnection;

          @Autowired

          RedisTemplate redisTemplate;

    三、简单集成Spring

        自己编写jedisCluster的工厂类JedisClusterFactory,然后通过Spring注入的方式获取jedisCluster,实现客户端使用Redis3.0版本的集群特性。

    请参考:http://my.oschina.net/FACEqiu/blog/512773?fromerr=I2SnVz8P

                   http://www.cnblogs.com/niceplay/p/4992614.html

    使用时,直接通过注解或者XML注入即可,如下所示:

         @Autowired

         JedisCluster jedisCluster;

      或者

        <bean id="testRedis" class="com.test.TestRedis">

            <property name="jedisCluster" ref="jedisClusterFactory" />

       </bean>

     ClassPathXmlApplicationContext  context = new ClassPathXmlApplicationContext(new ClassPathResource("resources/spring-config.xml").getPath());

     TestRedis testRedis=(TestRedis)context.getBean("testRedis");

    四、Redis Cluster调试中常见错误

    (1)当客户端与集群服务器不在同一台服务器上时,有如下错误Could not get a resource from the Cluster

        一般当客户端与集群服务器在同一台服务器上时,操作Redis Cluster正常; 当二者不在同一台服务器上时报如上错误,可能是clusterTimeOut时间设置过小;

    (2)操作Redis时报Too many cluster redirections

        初始化JedisCluster时,设定JedisCluster的maxRedirections.

       JedisCluster(Set<HostAndPort> jedisClusterNode, int timeout, int maxRedirections) ;
       JedisCluster jc = new JedisCluster(jedisClusterNodes,5000,1000);

    请参考:https://gitHub.com/xetorthio/jedis/issues/659

    (3)Redis Cluster数据写入慢

       检查在通过./redis-trib命令建立集群时,如果是通过127.0.0.1的方式建立的集群,那么在往Redis Cluster中写入数据时写入速度比较慢。可以通过配置真实的IP来规避此问题。

  • 相关阅读:
    每天学点Linux-选取命令CUT和GREP
    每天学点Linux-切割命令split
    基于netty-socketio的web推送服务
    Redis学习-LUA脚本
    spring中InitializingBean接口使用理解
    外包采用Gradle生成多套app打包
    Android Studio 快捷键 for mac
    使用ClipboardUtils兼容API LEVEL 11以下实现复杂粘贴
    finished with non-zero exit 添加v7包报错的问题
    Infer初体验 for Android
  • 原文地址:https://www.cnblogs.com/moonandstar08/p/5149585.html
Copyright © 2011-2022 走看看