一、Spring整合redis(单机版)
1、pom.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>redisdemo</groupId>
<artifactId>com.mh.redis</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.1.0-m1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
</dependencies>
</project>
2、redis.properties配置文件
#ip地址
redis.host= 127.0.0.1
#端口号
redis.port = 6379
# 密码 (如果有密码需要配置)
redis.password = root
#客户端超时时间单位是毫秒 默认是2000
redis.timeout = 3000
#数据库,默认的是0
redis.database = 0
#最大空闲链接
redis.maxIdle=300
#最小的空闲链接
redis.minIdle=10
#连接池的最大数据库连接数
redis.maxTotal=400
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
redis.maxWaitMillis=1000
#在空闲时检查有效性, 默认false
redis.testOnBorrow=false
#连接耗尽是否阻塞,false代表抛异常,true代表阻塞直到超时,默认为true
redis.blockWhenExhausted=false
3、spring的配置文件
<?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" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean class="com.mh.redis.mapper.SingleReidsMapper" id="singleRedis">
<property name="jedisPool" ref="jedisPool"></property>
</bean>
<!--加载redis的配置文件-->
<context:property-placeholder location="classpath:redis.properties"/>
<!--JedisPool这个bean的构造方法需要多个参数,使用构造方法的方式注入bean -->
<bean class="redis.clients.jedis.JedisPool" id="jedisPool">
<constructor-arg name="host" value="${redis.host}"></constructor-arg>
<constructor-arg name="port" value="${redis.port}"></constructor-arg>
<constructor-arg name="password" value="${redis.password}"></constructor-arg>
<constructor-arg name="timeout" value="${redis.timeout}"></constructor-arg>
<constructor-arg name="database" value="${redis.database}"></constructor-arg>
<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
</bean>
<!--redis配置项-->
<bean class="redis.clients.jedis.JedisPoolConfig" id="jedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="minIdle" value="${redis.minIdle}" />
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
<property name="blockWhenExhausted" value="${redis.blockWhenExhausted}" />
</bean>
</beans>
4、操作redis的接口
public interface RedisMapper {
String set(String key, String value);
String get(String key);
Boolean exists(String key);
Long expire(String key, int seconds);
Long ttl(String key);
Long incr(String key);
Long hset(String key, String field, String value);
String hget(String key, String field);
Long hdel(String key, String... field);
Boolean hexists(String key, String field);
List<String> hvals(String key);
Long del(String key);
}
5、实现类
public class SingleReidsMapper implements RedisMapper{
private JedisPool jedisPool;
public JedisPool getJedisPool() {
return jedisPool;
}
public void setJedisPool(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
@Override
public String set(String key, String value) {
Jedis jedis = jedisPool.getResource();
String result = jedis.set(key, value);
jedis.close();
return result;
}
@Override
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String result = jedis.get(key);
jedis.close();
return result;
}
@Override
public Boolean exists(String key) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.exists(key);
jedis.close();
return result;
}
@Override
public Long expire(String key, int seconds) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.expire(key, seconds);
jedis.close();
return result;
}
@Override
public Long ttl(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.ttl(key);
jedis.close();
return result;
}
@Override
public Long incr(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.incr(key);
jedis.close();
return result;
}
@Override
public Long hset(String key, String field, String value) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hset(key, field, value);
jedis.close();
return result;
}
@Override
public String hget(String key, String field) {
Jedis jedis = jedisPool.getResource();
String result = jedis.hget(key, field);
jedis.close();
return result;
}
@Override
public Long hdel(String key, String... field) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hdel(key, field);
jedis.close();
return result;
}
@Override
public Boolean hexists(String key, String field) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.hexists(key, field);
jedis.close();
return result;
}
@Override
public List<String> hvals(String key) {
Jedis jedis = jedisPool.getResource();
List<String> result = jedis.hvals(key);
jedis.close();
return result;
}
@Override
public Long del(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.del(key);
jedis.close();
return result;
}
}
6、测试类
public class RedisTest {
@Test
public void redisTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
SingleReidsMapper redis = context.getBean(SingleReidsMapper.class);
redis.set("k1", "哼哼");
String value = redis.get("k1");
System.out.println(value);
}
}
//这里的测试只是整合一个,其他的都和这个类似,如果感兴趣可以自己动手实践
二、Spring整合redis(集群)
1、搭建集群的环境
redis集群最少需要三个节点,因为投票容错机制要求超过半数节点挂了改节点才是挂了。要保证集群的高可用,需要每个节点都有从节点,也就是备份节点,所以redis集群至少需要6台服务器。
1.1 修改每台服务器上redis的配置文件
注:修改:bind 127.0.0.1 为自己的ip地址,集群不要在bind上设置回环ip地址,负责后面创建的时候可能出问题。
cluster-enabled yes #开启集群
cluster-config-file nodes-6379.conf
#每个加入集群的redis服务器都会自动生成一个节点配置文件,这里设置名称
cluster-node-timeout 10000
#节点互联超时时间,超过这个设置的时间redis会触发故障迁移,把某台从服务器提升为主服务器
cluster-slave-validity-factor < factor>: (redis5.0以后将slave 变成了replica)
#在进行故障转移的时候全部slave都会请求申请为master,但是有些slave可能与master断开连接一段时间,导致数据过于陈旧,不应该被提升为master。该参数就是用来判断slave节点与master断线的时间是否过长。判断方法是:比较slave断开连接的时间和(node-timeout * slave-validity-factor)+ repl-ping-slave-period,如果节点超时时间为三十秒, 并且slave-validity-factor为10,假设默认的repl-ping-slave-period(定义心跳(PING)间隔。)是10秒,即如果超过310秒slave将不会尝试进行故障转移。
cluster-migration-barrier < count>:
#master的slave数量大于该值,slave才能迁移到其他孤立master上,如这个参数被设为2,那么只有当一个主节点拥有2个可工作的从节点时,它的一个从节点才会尝试迁移。
cluster-require-full-coverage < yes/no>:
#设置为yes,这也是默认值,集群全部的slot有节点负责,集群状态才为ok并提供服务。设置为no可以在slot没有全部分配的时候提供服务。不建议打开该配置,这样会造成分区的时候,小分区的master一直在接受写请求,而造成很长时间数据不一致。
cluster-slave-no-failover/cluster-replica-no-failover
在主节点失效期间,从节点不允许对master失效转移,取值yes,no
2、准备好集群环境,下面我们在单机版的基础上来实现spring整合redis 的集群版。
1、修改spring的配置文件
<?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" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 连接redis集群 -->
<bean class="cn.ybzy.springredis.dao.RedisCluster" id="redisCluster">
<property name="jedisCluster" ref="jedisCluster"/>
</bean>
<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
<constructor-arg name="nodes">
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.238.4"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.238.5"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.238.6"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.238.7"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.238.8"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.238.9"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
</set>
</constructor-arg>
<!--constructor-arg .....根据构造函数的参数来设置!-->
</bean>
</beans>
2、RedisMapper 接口的实现类 (集群版)RedisCluster
public class JedisPoolDaoImpl2 implements JedisClient {
private JedisCluster jedisCluster;
public JedisCluster getJedisCluster() {
return jedisCluster;
}
public void setJedisCluster(JedisCluster jedisCluster) {
this.jedisCluster = jedisCluster;
}
@Override
public String set(String key, String value) {
return jedisCluster.set(key, value);
}
@Override
public String get(String key) {
return jedisCluster.get(key);
}
@Override
public Boolean exists(String key) {
return jedisCluster.exists(key);
}
@Override
public Long expire(String key, int seconds) {
return jedisCluster.expire(key, seconds);
}
@Override
public Long ttl(String key) {
return jedisCluster.ttl(key);
}
@Override
public Long incr(String key) {
return jedisCluster.incr(key);
}
@Override
public Long hset(String key, String field, String value) {
return jedisCluster.hset(key, field, value);
}
@Override
public String hget(String key, String field) {
return jedisCluster.hget(key, field);
}
@Override
public Long hdel(String key, String... field) {
return jedisCluster.hdel(key, field);
}
@Override
public Boolean hexists(String key, String field) {
return jedisCluster.hexists(key, field);
}
@Override
public List<String> hvals(String key) {
return jedisCluster.hvals(key);
}
@Override
public Long del(String key) {
return jedisCluster.del(key);
}
}
测试和单例测试一样,这里不做演示了!!