概述
Redis是一个开源的、高效的key-value存储系统,也是nosql中的最常见的一种。redis非常适合用来做缓存系统,关于Redis的详细介绍可以查看Redis官方documentation。
Redis支持多语言的调用,官方推荐的Java版客户端是Jedis,它非常强大和稳定,支持事务、管道及有Jedis自身实现。我们对Redis数据的操作,都可以通过Jedis来完成。
使用教程
1、配置maven依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
Jedis 线程安全问题
首先,需要注意的是单个的Jedis 实例不是线程安全,在多线程环境下你应该使用JedisPool。
using Jedis in a multithreaded environment
You shouldn’t use the same instance from different threads because you’ll have strange errors. And sometimes creating lots of Jedis instances is not good enough because it means lots of sockets and connections, which leads to strange errors as well. A single Jedis instance is not threadsafe! To avoid these problems, you should use JedisPool, which is a threadsafe pool of network connections. You can use the pool to reliably create several Jedis instances, given you return the Jedis instance to the pool when done. This way you can overcome those strange errors and achieve great performance.
初始化pool
JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");
JedisPool 是线程安全的,你可以将它作为一个静态变量保存起来。
为了保证Jedis 一定会被关闭,我们可以使用try-finally语句,如下:
Jedis jedis = null;
try {
jedis = pool.getResource();
/// ... do stuff here ... for example
jedis.set("foo", "bar");
String foobar = jedis.get("foo");
jedis.zadd("sose", 0, "car"); jedis.zadd("sose", 0, "bike");
Set<String> sose = jedis.zrange("sose", 0, -1);
} finally {
if (jedis != null) {
jedis.close();
}
}
/// ... when closing your application:
pool.destroy();
在介绍Jedis API使用之前,我们先使用单例模式对JedisPool 做一个封装,代码如下:
package com.ricky.codelab.redis.sample.pool;
import java.io.IOException;
import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import com.ricky.codelab.redis.sample.util.PropertyUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisPoolManager {
private volatile static JedisPoolManager manager;
private final JedisPool pool;
private JedisPoolManager() {
try {
//加载redis配置
Properties props = PropertyUtils.load("redis.properties");
// 创建jedis池配置实例
JedisPoolConfig config = new JedisPoolConfig();
// 设置池配置项值
String maxTotal = props.getProperty("redis.pool.maxTotal", "4");
config.setMaxTotal(Integer.parseInt(maxTotal));
String maxIdle = props.getProperty("redis.pool.maxIdle", "4");
config.setMaxIdle(Integer.parseInt(maxIdle));
String minIdle = props.getProperty("redis.pool.minIdle", "1");
config.setMinIdle(Integer.parseInt(minIdle));
String maxWaitMillis = props.getProperty("redis.pool.maxWaitMillis", "1024");
config.setMaxWaitMillis(Long.parseLong(maxWaitMillis));
String testOnBorrow = props.getProperty("redis.pool.testOnBorrow", "true");
config.setTestOnBorrow("true".equals(testOnBorrow));
String testOnReturn = props.getProperty("redis.pool.testOnReturn", "true");
config.setTestOnReturn("true".equals(testOnReturn));
String server = props.getProperty("redis.server");
if(StringUtils.isEmpty(server)){
throw new IllegalArgumentException("JedisPool redis.server is empty!");
}
String[] host_arr = server.split(",");
if(host_arr.length>1){
throw new IllegalArgumentException("JedisPool redis.server length > 1");
}
String[] arr = host_arr[0].split(":");
// 根据配置实例化jedis池
System.out.println("***********init JedisPool***********");
System.out.println("host->"+arr[0]+