Spring-data-redis操作redis cluster的示例代码
作者:moonandstar08
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
(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版本的集群特性。
请参考:https://www.jb51.net/article/128895.htm
使用时,直接通过注解或者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来规避此问题。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。