欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring-data-redis操作redis cluster的示例代码

程序员文章站 2024-03-06 22:21:56
redis 3.x版本引入了集群的新特性,为了保证所开发系统的高可用性项目组决定引用redis的集群特性。对于redis数据访问的支持,目前主要有二种方式:一、以直接调用j...

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下载路径如下:

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.redistemplate" p: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版本的集群特性。

请参考:

使用时,直接通过注解或者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来规避此问题。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。