Redis-Spring Data整合Jedis
Spring整合Jedis
1.单实例
step1:毫无疑问,首先需要在pom.xml中配置Jedis依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
step2:在resources中添加settings.properties,配置redis相关属性
#jedisPoolConfig
redis.minIdle=100
redis.maxIdle=500
redis.maxTotal=50000
redis.maxWaitMillis=10000
redis.testOnBorrow=true
#jedisPool
redis.host=127.0.0.1
redis.port=6379
redis.timeout=2000
step3:在spring-context.xml配置JedisPoolConfig及JedisPool
<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="service,dao"/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:settings.properties</value>
</list>
</property>
</bean>
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
<constructor-arg name="host" value="${redis.host}" />
<constructor-arg name="port" value="${redis.port}" type="int" />
</bean>
</beans>
JedisPool只有简单配置,如果需要增加其它配置项(如密码等),请自行参照JedisPool的构造方法进行配置
JedisPool.pngstep4:在TestController中测试是否连接成功
package controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
@Controller
public class TestController {
@Autowired
private JedisPool jedisPool;
@RequestMapping(value = "test",method = RequestMethod.GET,produces = "application/json;charset=utf-8")
@ResponseBody
public String test(){
return jedisPool.getResource().ping();
}
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1",6379);
System.out.println(jedis.ping());
}
}
step5:启动、运行、报错
nested exception is java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
查看源码发现JedisPoolConfig继承自GenericObjectPoolConfig
package redis.clients.jedis;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
public class JedisPoolConfig extends GenericObjectPoolConfig {
public JedisPoolConfig() {
this.setTestWhileIdle(true);
this.setMinEvictableIdleTimeMillis(60000L);
this.setTimeBetweenEvictionRunsMillis(30000L);
this.setNumTestsPerEvictionRun(-1);
}
}
而GenericObjectPoolConfig在package org.apache.commons.pool2.impl中,所以需要引入commons-pool2依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
再次运行,得到“Pong”的response结果,测试成功
Ping.png
2.配置Redis简单主从复制
Jedis对redis的集群支持也很完善,实例化SharedJedisPool即可
<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="service,dao,redis"/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:settings.properties</value>
</list>
</property>
</bean>
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="minIdle" value="${redis.minIdle}" />
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!--
<bean id="jedisPool" class="redis.clients.jedis.JedisPool" scope="singleton">
<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
<constructor-arg name="host" value="${redis.host}" />
<constructor-arg name="port" value="${redis.port}" type="int" />
</bean>
-->
<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1">
<list>
<bean class="redis.clients.jedis.JedisShardInfo">
<constructor-arg name="host" value="${redis.host1}" />
<constructor-arg name="port" value="${redis.port1}" />
<constructor-arg name="timeout" value="${redis.timeout}" />
<constructor-arg name="name" value="node1" />
</bean>
<bean class="redis.clients.jedis.JedisShardInfo">
<constructor-arg name="host" value="${redis.host2}" />
<constructor-arg name="port" value="${redis.port2}" />
<constructor-arg name="timeout" value="${redis.timeout}" />
<constructor-arg name="name" value="node2" />
</bean>
</list>
</constructor-arg>
</bean>
</beans>
3.sentinel模式
仅仅配置了主从复制是不够的,没有sentinel就不能实现故障转移,redis集群就失去意义了。
spring-data-redis对sentinel提供了很好的支持,详细配置如下
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>me.com</groupId>
<artifactId>springmvc</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<spring.version>4.3.0.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.8.0.RELEASE</version>
</dependency>
</dependencies>
</project>
settings.properties
#jedisPoolConfig
redis.maxTotal=50000
redis.maxIdle=500
redis.minIdle=100
redis.maxWaitMillis=10000
redis.testOnBorrow=true
#redis-sentinel
redis.sentinel=127.0.0.1:26379
redis.master=mymaster
spring-context.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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="service,dao,redis"/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:settings.properties</value>
</list>
</property>
</bean>
<!-- ******************** Redis Start ******************** -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="minIdle" value="${redis.minIdle}" />
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="redisSentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<constructor-arg name="master" value="${redis.master}" />
<constructor-arg name="sentinelHostAndPorts">
<set>
<value>${redis.sentinel}</value>
</set>
</constructor-arg>
</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<!-- 如有密码可以用p:password指定 -->
<constructor-arg ref="redisSentinelConfiguration" />
<constructor-arg ref="jedisPoolConfig" />
</bean>
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<!-- ******************** Redis End ******************** -->
</beans>
TestController
package controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TestController {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@RequestMapping(value = "test",method = RequestMethod.GET,produces = "application/json;charset=utf-8")
@ResponseBody
public String test(){
stringRedisTemplate.opsForValue().set("key1","v1");
return stringRedisTemplate.opsForValue().get("key1");
}
}
另外,特别提醒:
sentinel.conf配置文件中明确说明,需要绑定ip或者解除保护模式(生产环境下建议绑定ip)
# *** IMPORTANT ***
#
# By default Sentinel will not be reachable from interfaces different than
# localhost, either use the 'bind' directive to bind to a list of network
# interfaces, or disable protected mode with "protected-mode no" by
# adding it to this configuration file.
#
# Before doing that MAKE SURE the instance is protected from the outside
# world via firewalling or other means.
#
# For example you may use one of the following:
#
# bind 127.0.0.1 192.168.1.1
#
# protected-mode no
否则会报错:All sentinels down, cannot determine where is mymaster master is running...
4.配置Redis Cluster
Redis Cluster是3.0版本后的一种集群系统,它实现了数据分片,解决了单机数据容量瓶颈问题,同时也实现了高可用。
使用Spring+Jedis配置Redis Cluster也非常简单。
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="minIdle" value="${redis.minIdle}" />
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!-- 配置redis cluster -->
<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
<property name="clusterNodes">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.ip1}"/>
<constructor-arg name="port" value="${redis.port1}"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.ip2}"/>
<constructor-arg name="port" value="${redis.port2}"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.ip3}"/>
<constructor-arg name="port" value="${redis.port3}"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.ip4}"/>
<constructor-arg name="port" value="${redis.port4}"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.ip5}"/>
<constructor-arg name="port" value="${redis.port5}"/>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.ip6}"/>
<constructor-arg name="port" value="${redis.port6}"/>
</bean>
</set>
</property>
</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<constructor-arg name="clusterConfig" ref="redisClusterConfiguration" />
<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
</bean>
org.springframework.data.redis.connection.RedisClusterConfiguration
和org.springframework.data.redis.connection.jedis.JedisConnectionFactory
已经为我们封装好了所有的设置,再通过org.springframework.data.redis.core.StringRedisTemplate
,就可以在代码中很方便地对Redis进行读写!