redis 3.x版本引入了集群的新特性,为了保证所开发系统的高可用性项目组决定引用redis的集群特性。对于redis数据访问的支持,目前主要有二种方式:一、以直接调用jedis来实现;二、使用spring-data-redis,通过spring的封装来调用。下面分别对这二种方式如何操作redis进行说明。
一、利用jedis来实现
通过jedis操作redis cluster的模型可以参考redis官网,具体如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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
代码目录结构如下所示:
1
2
3
4
5
|
src com.example.bean com.example.repo com.example.repo.impl resources |
a.在resources目录下增加spring-config.xml配置,配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<!--通过构造方法注入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 -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<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文件
1
2
3
4
5
6
7
|
<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的操作。
1
2
3
|
classpathxmlapplicationcontext context = new classpathxmlapplicationcontext( new classpathresource( "resources/spring-config.xml" ).getpath()); repo repo =(repo)context.getbean( "personrepo" ); |
(2)采用redisclusterconfiguration(propertysource<?> propertysource)方式构造redisclusterconfiguration
代码目录结构如下所示:
1
2
3
4
5
6
|
src com.redis.cluster.support.config monitorconfig resources spring-config.xml redis.properties |
a.在resources目录下增加spring-config.xml配置,配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<!--配置文件加载--> <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文件
1
2
3
|
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类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
@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
1
2
3
4
5
6
7
|
@autowired jedisclusterconnection clusterconnection; @autowired redistemplate redistemplate; |
三、简单集成spring
自己编写jediscluster的工厂类jedisclusterfactory,然后通过spring注入的方式获取jediscluster,实现客户端使用redis3.0版本的集群特性。
请参考:http://www.zzvips.com/article/140100.html
使用时,直接通过注解或者xml注入即可,如下所示:
1
2
|
@autowired jediscluster jediscluster; |
或者
1
2
3
4
5
|
<bean id= "testredis" class = "com.test.testredis" > <property name= "jediscluster" ref= "jedisclusterfactory" /> </bean> |
1
2
3
|
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.
1
2
|
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来规避此问题。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://www.cnblogs.com/moonandstar08/p/5149585.html