

Redis 是什么,能做什么
Redis 是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel 提供高可用,通过 Redis Cluster 提供自动分区。(摘自 Redis 官网)
作为内存数据库,在现代互联网 web 系统中,还是主要将 Redis 作为缓存使用。大型互联网 Web 系统对性能要求很高,而在前端和数据层之间增加数据缓存已成为必不可少的手段之一,当前比较流行的两个技术就是 Redis 和 Memcached,至于两者有什么区别,不是本文要说的内容。本文主要讲 Java web 如何操作 Redis 及 Redis 集群。
一般 Java 程序操作Redis
Redis 提供了多种语言的客户端,在 Java 中最流行的是 Jedis 。访问可查看源码及使用方式。目前 Jedis 最新版本是2.9.0。无论是单机还是集群,Jedis 都有很详细的说明和实例代码,这里只做简单说明。如果用 Maven 做包管理,需要引用 jedis 包,本例使用最新的2.9.0版本,如下:
redis.clients jedis 2.9.0
操作 Redis 单机
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Created by fengdezitai on 2016/10/9.
*/
public class JedisClient {
private static final String host= "192.168.31.121";
private static final JedisClient jedisClient = new JedisClient();
private Jedis jedis = null;
/**
* 私有构造函数
*/
private JedisClient(){}
public static JedisClient getInstance(){
return jedisClient;
}
private JedisPoolConfig getPoolConfig(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(10);
jedisPoolConfig.setMaxTotal(100);
jedisPoolConfig.setMaxWaitMillis(3000);
return jedisPoolConfig;
}
/**
* 添加
* @param key
* @param value
* @return
* @throws Exception
*/
public Boolean add(String key,String value) throws Exception{
JedisPool pool = new JedisPool(getPoolConfig(),host);
Jedis jedis = null;
try {
jedis = pool.getResource();
if(jedis.exists(key)){
throw new Exception(String.format("key (%s) 已存在 ",key));
}
jedis.set(key,value);
}catch (Exception e){
throw e;
}
finally {
if(jedis!=null){
jedis.close();
}
}
pool.destroy();
return true;
}
/**
* 获取值
* @param key
* @return
* @throws Exception
*/
public String get(String key) throws Exception{
JedisPool pool = new JedisPool(getPoolConfig(),host);
Jedis jedis = null;
String result = "";
try {
jedis = pool.getResource();
result = jedis.get(key);
}catch (Exception e){
throw e;
}
finally {
if(jedis!=null){
jedis.close();
}
}
pool.destroy();
return result;
}
public static void main(String[] args) {
JedisClient jedisClient = JedisClient.getInstance();
try {
/*Boolean result = jedisClient.add("hello", "redis1");
if(result){
System.out.println("success");
}*/
System.out.println(jedisClient.get("hello"));
}catch (Exception e){
e.printStackTrace();
}
}
}操作 redis 集群
import redis.clients.jedis.*;
import java.util.HashSet;
import java.util.Set;
/**
* Created by fengdezitai on 2016/10/13.
*/
public class JedisClusterClient {
private static int count = 0;
private static final JedisClusterClient redisClusterClient = new JedisClusterClient();
/**
* 私有构造函数
*/
private JedisClusterClient() {}
public static JedisClusterClient getInstance() {
return redisClusterClient;
}
private JedisPoolConfig getPoolConfig(){
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(1000);
config.setMaxIdle(100);
config.setTestOnBorrow(true);
return config;
}
public void SaveRedisCluster() {
Set jedisClusterNodes = new HashSet();
jedisClusterNodes.add(new HostAndPort("192.168.31.245", 7000));
jedisClusterNodes.add(new HostAndPort("192.168.31.245", 7001));
jedisClusterNodes.add(new HostAndPort("192.168.31.245", 7002));
jedisClusterNodes.add(new HostAndPort("192.168.31.210", 7003));
jedisClusterNodes.add(new HostAndPort("192.168.31.210", 7004));
jedisClusterNodes.add(new HostAndPort("192.168.31.210", 7005));
JedisCluster jc = new JedisCluster(jedisClusterNodes,getPoolConfig());
jc.set("cluster", "this is a redis cluster");
String result = jc.get("cluster");
System.out.println(result);
}
public static void main(String[] args) {
JedisClusterClient jedisClusterClient = JedisClusterClient.getInstance();
jedisClusterClient.SaveRedisCluster();
}
} Spring mvc 操作 Redis
在 Spring mvc 中操作 Redis ,首先当然要搭好 Spring mvc 框架了。以下是在假设 Spring mvc 环境已经架好的情况下。本例中 Spring 版本为 4.3.2 RELEASE。关于 Spring 的 maven 引用如下:
4.3.2.RELEASE
org.springframework spring-core ${spring.version} commons-logging commons-logging
org.springframework spring-web ${spring.version}
org.springframework spring-oxm ${spring.version}
org.springframework spring-tx ${spring.version}
org.springframework spring-jdbc ${spring.version}
org.springframework spring-webmvc ${spring.version} commons-logging commons-logging
org.springframework spring-aop ${spring.version}
org.springframework spring-context-support ${spring.version}
org.springframework spring-test ${spring.version}操作 Redis 单机
只用 Jedis 自己实现注入(区别于下面的引用spring-data-redis)
把前面的 JedisClient 代码拿过来引用即可,只需实现一个访问 Redis 的 Service ,就可以集成到 Spring mvc 。Service 代码如下:
import org.springframework.stereotype.Service;
import util.JedisClient;
/**
* Created by fengdezitai on 2016/10/9.
*/
@Service
public class RedisService {
public String get(String key) throws Exception{
JedisClient jedisClient = JedisClient.getInstance(); //上面实现的JedisClient
String result = "";
try {
result = jedisClient.get("hello");
}catch (Exception e){
throw e;
}
return result;
}
}Controller 实现如下:
@Controller
@RequestMapping(value = "redisAllInOne")
public class RedisAllInOneController {
@Autowired
private RedisService redisService;
@RequestMapping(value = "get",method = RequestMethod.GET)
@ResponseBody
public Object getByMyService(String key){
try {
String result = redisService.get(key);
return result;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
} 用 spring-data-redis 包做集成
上面是自己实现的注入,这里用 spring-data-redis 进行集成,只需简单配置即可,需要引用 maven 包如下,版本为目前最新版 1.7.2.RELEASE:
org.springframework.data spring-data-redis 1.7.2.RELEASE
使用 spring-data-redis ,即省去了自己实现注入的过程,通过它提供的一些配置,即可实现连接池配置、RedisTemplate 配置、JedisConnectionFactory 配置;通过 JedisConnectionFactory 可配置连接池参数、redis 服务器、端口、密码、超时时间、database索引等;RedisTemplate 即注入的bean ,可以使用 RedisTemplate 自动注入的实体进行 redis 的一系列操作,具体看配置;
redis 服务属性配置文件:
redis.maxIdle=300 redis.maxWait=3000 redis.testOnBorrow=true redis.host=192.168.31.121 redis.port=6379 redis.password=password redis.timeout=3000
spring-data-redis xml 配置文件 redis-context.xml:
--> -->
之后在 spring 配置文件中引用以上文件:
解释一下上面的配置:
poolConfig 即配置 redis 连接池,之后配置了两个 JedisConnectionFactory 和 RedisTemplate ,一个 RedisTemplate 对应一个 JedisConnectionFactory ,这样可以配置根据场景配置不同的 Redis 连接,比如超时时间要求不一致、database 0-15 可以存储不同的数据等。这里就配置了database 1 和 2 ,调用 commonRedisTemplate 会存到 database1 ,调用 cacheRedisTemplate 会存到 database2。
之后在 Service 层即可注入并引用这两个 RedisTemplate ,如下代码:
import org.apache.commons.lang3.StringUtils;
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.Repository;
import javax.annotation.Resource;
import java.io.*;
@Repository
public class RedisCache {
@Resource(name = "cacheRedisTemplate")
private RedisTemplate最后在 Controller 中调用即可
@Autowired
private RedisCache redisCache;
@RequestMapping(value = "get", method = RequestMethod.GET)
@ResponseBody
public Object getByMyService(String key) {
try {
String result = redisService.get(key);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@RequestMapping(value = "save", method = RequestMethod.GET)
@ResponseBody
public Object save() {
Token token = new Token();
token.setAccess_token("token");
token.setExpires_in(1000);
try {
redisCache.put("token", token);
} catch (Exception e) {
e.printStackTrace();
}
return "ok";
} 操作 Redis 集群
只用 Jedis 自己实现注入(区别于下面的引用spring-data-redis)
把前面的 JedisClusterClient 代码拿过来引用即可,只需实现一个访问 Redis 的 Service ,就可以集成到 Spring mvc 。Service 代码如下:
import org.springframework.stereotype.Service;
import util.JedisClusterClient;
/**
* Created by fengdezitai on 2016/10/13.
*/
@Service
public class RedisClusterService {
public void save() throws Exception{
//调用 JedisClusterClient 中的方法
JedisClusterClient jedisClusterClient = JedisClusterClient.getInstance();
try {
jedisClusterClient.SaveRedisCluster();
}catch (Exception e){
throw e;
}
}
}最后在 Controller 中调用实现的 Service 即可
@Controller
@RequestMapping(value = "redisCluster")
public class RedisClusterController {
@Autowired
private RedisClusterService redisClusterService;
@RequestMapping(value = "save",method = RequestMethod.GET)
@ResponseBody
public Object save(){
try{
redisClusterService.save();
}catch (Exception e){
e.printStackTrace();
return String.format("error: %s",e.getMessage());
}
return "ok";
}
} 用 spring-data-redis 包做集成
Spring 和 spring-data-redis maven 包引用和前面一致,之所以引用 spring-data-redis 1.7.2.RELEASE,是因为目前只有这个最新版本才支持集群操作。
redis 集群服务属性配置
redis.maxIdle=300 redis.maxWait=3000 redis.testOnBorrow=false redis.timeout=3000
spring-data-redis xml 集群配置文件 redis-cluster-context.xml
之后在 Spring 配置文件中引用
解释以上配置:
poolConfig是连接池配置,redisClusterConfig 配置了 Redis 集群的各个节点(节点 host 和 port 最好写在属性配置文件中),集群搭建可见 我的 另一篇博客 。然后下面和单机配置一样了,一对 JedisConnectionFactory 和 RedisTemplate 。
之后在 Service 层即可注入并引用这个 RedisTemplate,代码如下:
import org.apache.commons.lang3.StringUtils;
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.Repository;
import java.io.*;
/**
* Created by fengdezitai on 2016/9/29.
*/
@Repository
public class RedisClusterCache {
@Autowired
private RedisTemplate 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最后在 Controller 中调用即可
@Controller
@RequestMapping(value = "redisCluster")
public class RedisClusterController {
@Autowired
private RedisClusterCache redisClusterCache;
@RequestMapping(value = "clusterSave",method = {RequestMethod.GET,RequestMethod.POST})
@ResponseBody
public Object clusterSave(){
//redisClusterCache.put("cluster","save cluster");
Token token = new Token();
token.setExpires_in(1000);
token.setAccess_token("hello world");
redisClusterCache.put("token",token);
return "ok";
}
@RequestMapping(value = "getKey",method = RequestMethod.GET)
@ResponseBody
public Object getCluster(String key){
Object val = redisClusterCache.get(key);
return val;
}
} 注意事项:
版本问题,如果用 spring-data-redis 做集成操作 Reids 集群,只有 spring-data-redis 目前最新版本1.7才包含对集群的操作,而最新的 spring-data-redis 中的某些功能对 Spring mvc 的版本也有些限制,所以尽量选择高版本的 Spring mvc 对应。
如果存储的value值是一个实体对象,那么一定要实现 Serializable 接口
【相关推荐】
1. 详解Spring框架注解的用法代码实例
2. Java事务管理学习之Spring和Hibernate的代码详解
