Spring + Jedis集成Redis(集群redis数据库)
前段时间说过单例redis数据库的方法,但是生成环境一般不会使用,基本上都是集群redis数据库,所以这里说说集群redis的代码。
1、pom.xml引入jar
<!--Redis--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.0</version> </dependency>
2、在redis.properties文件里面配置redis的地址和端口(ps:这个属性文件只配置redis集群的地址和端口,方便以后扩展)
address1=redis服务器IP:6379
address2=redis服务器IP:6379
address3=redis服务器IP:6379
address4=redis服务器IP:6379
address5=redis服务器IP:6379
address6=redis服务器IP:6379
3、新建一个属性文件redisconfig.properties配置其他的redis集群环境
#客户端超时时间单位是毫秒
redis.timeout=300000
#最大连接数
redis.maxActive=300
#最小空闲数
redis.minIdle=8
#最大空闲数
redis.maxIdle=100
#最大建立连接等待时间
redis.maxWaitMillis=1000
#redis集群单位数
redis.maxRedirections=6 //这里和你的redis数据库个数一样
4、spring-redis.xml配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 读取配置文件信息 --> <context:property-placeholder ignore-unresolvable="true" location="classpath:*.properties"/> <!-- jedis cluster config --> <bean name="genericObjectPoolConfig" class="org.apache.commons.pool2.impl.GenericObjectPoolConfig" > <property name="maxTotal" value="${redis.maxActive}" /> <property name="minIdle" value="${redis.minIdle}" /> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="maxWaitMillis" value="${redis.maxWaitMillis}" /> </bean> <bean id="jedisCluster" class="com.topteam.redis.JedisClusterFactory"> <property name="addressConfig" value="classpath:redis.properties"/> <property name="addressKeyPrefix" value="address" /> <property name="timeout" value="${redis.timeout}" /> <property name="maxRedirections" value="${redis.maxRedirections}" /> <property name="genericObjectPoolConfig" ref="genericObjectPoolConfig" /> </bean> </beans>
5、序列化和反序列化工具代码
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * 序列化和反序列化工具 */ public class SerializerUtil { /** * 序列化 * @param object * @return */ public static byte[] serializeObj(Object object) { ObjectOutputStream oos = null; ByteArrayOutputStream baos = null; try { baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(object); byte[] bytes = baos.toByteArray(); return bytes; } catch (Exception e) { throw new RuntimeException("序列化失败!", e); } } /** * 反序列化 * @param bytes * @return */ public static Object deserializeObj(byte[] bytes) { if (bytes == null){ return null; } ByteArrayInputStream bais = null; try { bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); return ois.readObject(); } catch (Exception e) { throw new RuntimeException("反序列化失败!", e); } } }
6、自己新建一个JedisClusterFactory.java集群工厂类
import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.JedisCluster; import java.util.HashSet; import java.util.Iterator; import java.util.Properties; import java.util.Set; import java.util.regex.Pattern; /** * JedisCluster集群工厂类 */ public class JedisClusterFactory implements FactoryBean<JedisCluster>, InitializingBean { private Resource addressConfig; private String addressKeyPrefix; private JedisCluster jedisCluster; private Integer timeout; private Integer maxRedirections; private GenericObjectPoolConfig genericObjectPoolConfig; private Pattern p = Pattern.compile("^.+[:]\\d{1,5}\\s*$"); public JedisClusterFactory() { } public JedisCluster getObject() throws Exception { return this.jedisCluster; } public Class<? extends JedisCluster> getObjectType() { return this.jedisCluster != null?this.jedisCluster.getClass():JedisCluster.class; } public boolean isSingleton() { return true; } private Set<HostAndPort> parseHostAndPort() throws Exception { try { Properties ex = new Properties(); ex.load(this.addressConfig.getInputStream()); HashSet haps = new HashSet(); Iterator i$ = ex.keySet().iterator(); while(i$.hasNext()) { Object key = i$.next(); if(((String)key).startsWith(this.addressKeyPrefix)) { String val = (String)ex.get(key); boolean isIpPort = this.p.matcher(val).matches(); if(!isIpPort) { throw new IllegalArgumentException("ip 或 port 不合法"); } String[] ipAndPort = val.split(":"); HostAndPort hap = new HostAndPort(ipAndPort[0], Integer.parseInt(ipAndPort[1])); haps.add(hap); } } return haps; } catch (IllegalArgumentException var9) { throw var9; } catch (Exception var10) { throw new Exception("解析 jedis 配置文件失败", var10); } } public void afterPropertiesSet() throws Exception { Set haps = this.parseHostAndPort(); this.jedisCluster = new JedisCluster(haps, this.timeout.intValue(), this.maxRedirections.intValue(), this.genericObjectPoolConfig); } public void setAddressConfig(Resource addressConfig) { this.addressConfig = addressConfig; } public void setTimeout(int timeout) { this.timeout = Integer.valueOf(timeout); } public void setMaxRedirections(int maxRedirections) { this.maxRedirections = Integer.valueOf(maxRedirections); } public void setAddressKeyPrefix(String addressKeyPrefix) { this.addressKeyPrefix = addressKeyPrefix; } public void setGenericObjectPoolConfig(GenericObjectPoolConfig genericObjectPoolConfig) { this.genericObjectPoolConfig = genericObjectPoolConfig; } }
7、操作实现类,这里只提供了3个实现方法,其他的可以根据需求来
(ps:我这里是通过序列化方式来实现的key和value,所以不需要分List集合还是String字符串,统一对待,统一处理)
import org.springframework.stereotype.Component; import redis.clients.jedis.JedisCluster; import javax.annotation.Resource; /** * Created by chengwenwen on 2016/11/4. */ @Component public class RedisCache { @Resource private JedisCluster jedisCluster; /** * 添加缓存数据 * @param key * @param obj * @param <T> * @return * @throws Exception */ public <T> long putCache(String key, T obj) throws Exception { final byte[] bkey = key.getBytes(); final byte[] bvalue = SerializerUtil.serializeObj(obj); return jedisCluster.setnx(bkey,bvalue); } /** * 添加缓存数据,设定缓存失效时间 * @param key * @param obj * @param expireTime * @param <T> * @throws Exception */ public <T> String putCacheWithExpireTime(String key, T obj, final int expireTime) throws Exception { final byte[] bkey = key.getBytes(); final byte[] bvalue = SerializerUtil.serializeObj(obj); String result = jedisCluster.setex(bkey, expireTime,bvalue); return result; } /** * 根据key取缓存数据 * @param key * @param <T> * @return * @throws Exception */ public <T> T getCache(final String key) throws Exception { byte[] result = jedisCluster.get(key.getBytes()); return (T) SerializerUtil.deserializeObj(result); } }
8、测试代码
import com.topteam.redis.RedisCache; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import javax.annotation.Resource; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 测试类 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath*:spring-test.xml") public class test { @Resource private RedisCache redisCache; @Test public void test() throws Exception{ List<String> list = new ArrayList<String>(); list.add("测试list"); list.add("测试list2"); redisCache.putCache("testList","redis集群测试"); Map<String,Object> map = new HashMap<String, Object>(); map.put("test*","测试数据"); map.put("测试数据","啥的"); map.put("listTest",list); redisCache.putCache("testMap",map); redisCache.putCache("testString","redis集群测试"); Map resultMap = new HashMap(); resultMap.put("testList",redisCache.getCache("testList")); resultMap.put("testMap",redisCache.getCache("testMap")); resultMap.put("testString",redisCache.getCache("testString")); System.out.print(map); } }
测试结果:
OK,一切正常。这里可以关闭一个主redis数据库服务,然后经过测试,还是可以获取数据。