Redis是一个开源的硬盘缓存软件,具有极高的存取速度,并且使用简单。
Java环境下使用redis需要添加支持的jar包,maven如下:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.5.2</version>
</dependency>
Spring Redis连接池:
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="10"/>
<property name="maxIdle" value="10"/>
<property name="minIdle" value="10"/>
<property name="maxWaitMillis" value="2000"/>
<property name="testOnBorrow" value="true"/>
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg index="0" ref="jedisPoolConfig"/>
<constructor-arg index="1" value="localhost"/>
<constructor-arg index="2" value="6379"/>
<constructor-arg index="3" value="2000"/>
<constructor-arg index="4" value="123456"/><!-- -->
</bean>
<bean class="xxx.utils.JedisUtils">
<property name="jedisPool" ref="jedisPool"></property>
</bean>
编写Redis工具类,将需要使用到的Jedis中的方法封装起来:
public class JedisUtils {
private static JedisPool jedisPool;
private static Logger log = LoggerFactory.getLogger(JedisUtils.class);
public void setJedisPool(JedisPool jedisPool) {
JedisUtils.jedisPool = jedisPool;
}
public static Jedis getJedis(){
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
} catch (Exception e) {
log.error("获取redis连接失败",e);
if(null!=jedis){
closeBroken(jedis);
}
}
return jedis;
}
private static void close(Jedis jedis){
if(null!=jedis){
try {
jedisPool.returnResource(jedis);
} catch (Exception e) {
log.error("close(Jedis jedis)",e);
}
}
}
private static void closeBroken(Jedis jedis){
if(null!=jedis){
try {
jedisPool.returnBrokenResource(jedis);
} catch (Exception e) {
log.error("closeBroken(Jedis jedis)",e);
}
}
}
public static String get(String key){
Jedis jedis = getJedis();
String value = null;
if(null!=jedis){
try {
value = jedis.get(key);
close(jedis);
} catch (Exception e) {
log.error("get(String key)", e);
closeBroken(jedis);
}
}
return value;
}
...
}
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">在使用Jedis时,一定要主意以下两点(也是使用池技术的时候需要注意的问题):</span>
1、不要使用形如:
Jedis jedis = JedisUtils.getJedis();
//业务处理,其中有涉及到redis读/取操作
JedisUtils.close(jedis);
这种使用方法存在一定的隐患:当业务处理花费的时间较长时,如果并发量较多,可能会出现redis连接池耗尽的情况,因为业务处理未完成之前,当前程序不会释放redis链接对象;可能出现遗漏的释放redis链接对象的语句,如漏写了上面的代码JedisUtils.close(jedis),从而导致连接池耗尽。
解决方法:将redis读取封装成独立方法,读写完成立即释放链接
public static String get(String key){
Jedis jedis = getJedis();
String value = jedis.get(key);
JedisUtils.close(jedis);
return value;
}
2、任何涉及到使用redis读写的代码一定要使用try catch语句包裹,否则可能出现redis读写超时(如服务器与Redis服务器之间有网络延迟)或者其他异常导致redis链接对象无法放回连接池中。
将1中的代码进行完善:
public static String get(String key){
Jedis jedis = getJedis();
String value = null;
if(null!=jedis){
try {
value = jedis.get(key);
JedisUtils.close(jedis);
} catch (Exception e) {
log.error("get(String key)", e);
JedisUtils.closeBroken(jedis);
}
}
return value;
}