搭建完redis集群跟java结合起来(redis集群搭建见上一篇博客)
一:不使用框架的情况
1.引入jar(一个jedis jar就够了)
2.创建节点对象,把节点对象加入JedisCluster对象中,然后就可以正常使用
public static void main(String[] args) {
// 创建并填充节点信息
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("127.0.0.1", 7001));
nodes.add(new HostAndPort("127.0.0.1", 7002));
nodes.add(new HostAndPort("127.0.0.1", 7003));
nodes.add(new HostAndPort("127.0.0.1", 7004));
nodes.add(new HostAndPort("127.0.0.1", 7005));
nodes.add(new HostAndPort("127.0.0.1", 7006));
// 创建JedisCluster对象
JedisCluster jedisCluster = new JedisCluster(nodes);
// 使用jedisCluster操作redis
String key = "jedisCluster";
String setResult = jedisCluster.set(key, "hello redis!");
System.out.println(setResult);
String getResult = jedisCluster.get(key); System.out.println(getResult);
// 关闭jedisCluster(程序执行完后才能关闭,内部封装了连接池) jedisCluster.close();
}
二:redis集群结合SSM框架
1.新建redis的配置属性文件redis.properties
redis.pool.maxTotal=30(最大连接数)
redis.pool.maxIdle=10(最大空闲时间)
redis.pool.numTestsPerEvictionRun=1024
redis.pool.timeBetweenEvictionRunsMillis=30000
redis.pool.minEvictableIdleTimeMillis=1800000
redis.pool.softMinEvictableIdleTimeMillis=10000
redis.pool.maxWaitMillis=1500
redis.pool.testOnBorrow=true
redis.pool.testWhileIdle=true
redis.pool.blockWhenExhausted=false
redis.maxRedirects=3
redis.host1=127.0.0.1(集群的主机ip)
redis.port1=7001(集群的主机端口)
redis.host2=127.0.0.1
redis.port2=7002
redis.host3=127.0.0.1
redis.port3=7003
redis.host4=127.0.0.1
redis.port4=7004
redis.host5=127.0.0.1
redis.port5=7005
redis.host6=127.0.0.1
redis.port6=7006
2.pom文件添加依赖
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.1.RELEASE</version>
</dependency>
不用问我为什么要加这么多其他的,这是个坑,版本原因。
3.新建spring-redis.xml配置文件
为了方便我贴代码了
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- redis连接池 这里引用的是jedis 包中的功能 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.maxActive:1024}" />
<property name="maxIdle" value="${redis.maxIdle:1024}" />
<property name="maxWaitMillis" value="${redis.maxWait:10000}" />
<property name="testOnBorrow" value="${redis.testOnBorrow:true}" />
<property name="testOnReturn" value="${redis.testOnReturn:true}" />
</bean>
<!-- Redis集群配置 这里使用的是spring-data-redis 包中内容 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:redis.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<bean id="redisClusterConfig" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
<property name="maxRedirects" value="6"></property>
<property name="clusterNodes">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host1}"></constructor-arg>
<constructor-arg name="port" value="${redis.port1}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host2}"></constructor-arg>
<constructor-arg name="port" value="${redis.port2}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host3}"></constructor-arg>
<constructor-arg name="port" value="${redis.port3}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host4}"></constructor-arg>
<constructor-arg name="port" value="${redis.port4}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host1=5}"></constructor-arg>
<constructor-arg name="port" value="${redis.port5}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.host6}"></constructor-arg>
<constructor-arg name="port" value="${redis.port6}"></constructor-arg>
</bean>
</set>
</property>
</bean>
<!-- Redis连接工厂 -->
<bean id="redis4CacheConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<constructor-arg name="clusterConfig" ref="redisClusterConfig" />
<property name="timeout" value="${redis.timeout:10000}" />
<property name="poolConfig" ref="jedisPoolConfig" />
</bean>
<!-- 存储序列化 -->
<bean name="stringRedisSerializer"
class="org.springframework.data.redis.serializer.StringRedisSerializer" />
<!-- 集群Resis使用模板 -->
<bean id="clusterRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="redis4CacheConnectionFactory" />
<property name="keySerializer" ref="stringRedisSerializer" />
<property name="hashKeySerializer" ref="stringRedisSerializer" />
<property name="valueSerializer" ref="stringRedisSerializer" />
<property name="hashValueSerializer" ref="stringRedisSerializer" />
</bean>
</beans>
注意点:当项目中有多个属性文件.properties时,加载每个文件前用
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:某某.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
声明,原因是因为spring中加载属性文件的类是单例的,加载完就认为结束了,需要多次开启它
4.在service层编写RedisClusterClient服务类
package cn.zds.service.impl;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service
public class RedisClusterClient {
@Autowired
private RedisTemplate<String,String> clusterRedisTemplate;
//添加数据
public void put(Object key, Object value) {
if(null == value) {
return;
}
if(value instanceof String) {
if(StringUtils.isEmpty(value.toString())) {
return;
}
}
// TODO Auto-generated method stub
final String keyf = key + "";
final Object valuef = value;
final long liveTime = 86400;
clusterRedisTemplate.execute(new RedisCallback<Long>() {
public Long doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] keyb = keyf.getBytes();
byte[] valueb = toByteArray(valuef);
connection.set(keyb, valueb);
if (liveTime > 0) {
connection.expire(keyb, liveTime);
}
return 1L;
}
});
}
// 获取数据
public Object get(Object key) {
final String keyf = (String) key;
Object object;
object = clusterRedisTemplate.execute(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection)
throws DataAccessException {
byte[] key = keyf.getBytes();
byte[] value = connection.get(key);
if (value == null) {
return null;
}
return toObject(value);
}
});
return object;
}
/**
* 描述 : <byte[]转Object>. <br>
* <p>
* <使用方法说明>
* </p>
*
* @param bytes
* @return
*/
private Object toObject(byte[] bytes) {
Object obj = null;
try {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
obj = ois.readObject();
ois.close();
bis.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
return obj;
}
private byte[] toByteArray(Object obj) {
byte[] bytes = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
bytes = bos.toByteArray();
oos.close();
bos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return bytes;
}
}
5.测试
Redis一般使用方法:
将常用的信息(经常读取且内容不怎么会改变的,这里我用了首页的数据)放入redis,请求过来时优先去redis去读取,读到就返回。如果没读到就去mysql中读取,在将结果返回到客户端之前把数据同步到redis,当请求向mysql修改信息时,mysql修改完信息,再将信息同步到redis。
package cn.zds.controller;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.zds.pojo.Shop;
import cn.zds.service.impl.RedisClusterClient;
import cn.zds.service.impl.ShopServiceImpl;
@Controller
public class TestController {
@Resource
private RedisClusterClient redisClusterClient;
@Resource
private ShopServiceImpl shopServiceImpl;
@RequestMapping("/getUserFromTable")
@ResponseBody
public List getUserFromTable(){
Object object=redisClusterClient.get("FIRST_PAGE");//直接去redis读取信息
System.out.println(object);
if(object!=null){//读到了信息
return (List) object;//返回
}else {//没有读到信息
//去mysql数据库读取
List<Shop> firstShopList = shopServiceImpl.selFirstPageShop(1, 8);//查询第一页,从一开始,1页数量数量为8个shop
//同步到redis中
redisClusterClient.put("FIRST_PAGE", firstShopList);
return firstShopList;
}
}
}
6.项目目录结构: