近期在项目中使用到了Redis用作缓存, 减少了MySQL的压力, 为什么会用redis用作缓存? 一点是因为redis能够支持多种数据类型(String , list, Set, Hash, Zset), 二是redis中的数据都是加载到内存中进行缓存, 可以设置数据有效时间, 故响应速度非常之快, 而且还有各种非常强大的功能例如数据淘汰机制, 过多的这里就不再做陈述; 主要是记录自己在项目中使用到的redis的配置与功能接口的开发; 方便后期的整理与回顾;
项目使用到的是Maven来进行整个的项目搭建, 使用聚合工程的方式方便了各种jar包的统一管理与服务之间的依赖调用; 那么鉴于以上所说, redis缓存服务可能会被用于多个服务做缓存, 那么我就将redis服务的接口与实现类放到了统一的公共工程下common;
项目结构
服务调用方
在common工程下的pom.xml文件添加依赖
1. 配置redis.properties文件
#单机版Redis
jedisPool.host=192.168.12.128
jedisPool.port=6379
#集群版Redis
cluster.redis1.host=192.168.12.128
cluster.redis1.port=7001
cluster.redis2.host=192.168.12.128
cluster.redis2.port=7002
cluster.redis3.host=192.168.12.128
cluster.redis3.port=7003
cluster.redis4.host=192.168.12.128
cluster.redis4.port=7004
cluster.redis5.host=192.168.12.128
cluster.redis5.port=7005
cluster.redis6.host=192.168.12.128
cluster.redis6.port=7006
2. 准备RedisService接口
/**
* Redis服务接口
* @author 黄家大少
*
*/
public interface RedisService {
/**
* 设置键与值
* @param key 键
* @param value 值
* @return
*/
String set(String key, String value);
/**
* 设置键与值的有效时间
* @param key 键
* @param value 值
* @param seconds 时间: 秒
* @return
*/
String setex(String key, String value, int seconds);
/**
* 设置键的有效时间
* @param key 键
* @param seconds 时间: 秒
* @return
*/
Long expire(String key, int seconds);
/**
* 获取一个键的值
* @param key 键
* @return 值
*/
String get(String key);
/**
* 删除一个键
* @param key 键
* @return 状态码
*/
Long del(String key);
/**
* 获取一个键的自增长的值
* @param key
* @return
*/
Long incr(String key);
}
接口实现类中, 会出现很多重复的操作, 这里我使用了命令模式将公共操作模式抽取出来;
Redis集群操作实现类JedisClusterServiceImpl
import javax.annotation.Resource;
import ******.common.redis.RedisService;
import redis.clients.jedis.JedisCluster;
/**
* Redis集群操作实现类
* @author 黄家大少
*
*/
public class JedisClusterServiceImpl implements RedisService{
/**
* 全自动类型注入JedisCluster
*/
@Resource
private JedisCluster jedisCluster;
@Override
public String set(String key, String value) {
return jedisCluster.set(key, value);
}
@Override
public String setex(String key, String value, int seconds) {
return jedisCluster.setex(key, seconds, value);
}
@Override
public Long expire(String key, int seconds) {
return jedisCluster.expire(key, seconds);
}
@Override
public String get(String key) {
return jedisCluster.get(key);
}
@Override
public Long del(String key) {
return jedisCluster.del(key);
}
@Override
public Long incr(String key) {
return jedisCluster.incr(key);
}
}
Redis单机版服务接口实现类
import javax.annotation.Resource;
import com.******.common.redis.RedisFunction;
import com.******.common.redis.RedisService;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* Redis单机版操作业务实现类
* @author 黄家大少
*
*/
@SuppressWarnings("all")
public class JedisPoolServiceImpl implements RedisService {
//注入JedisPool
@Resource
private JedisPool jedisPool;
/** 通用的执行方法 */
private <T> T execute(RedisFunction<T> redisFunction){
Jedis jedis = null;
try{
jedis = jedisPool.getResource();
/** 命令模式 */
return redisFunction.callback(jedis);
}finally{
/** 关闭jedis */
if (jedis != null) jedis.close();
}
}
/**
* 设置键与值
*/
@Override
public String set(final String key, final String value) {
return execute(new RedisFunction<String>(){
@Override
public String callback(Jedis jedis) {
return jedis.set(key, value);
}
});
}
/**
* 设置键值的有效时间
*/
@Override
public String setex(final String key, final String value, final int seconds) {
return execute(new RedisFunction<String>(){
@Override
public String callback(Jedis jedis) {
return jedis.setex(key, seconds, value);
}
});
}
/**
* 设置键的有效时间
*/
@Override
public Long expire(final String key, final int seconds) {
return execute(new RedisFunction<Long>(){
@Override
public Long callback(Jedis jedis) {
return jedis.expire(key, seconds);
}
});
}
/**
* 根据键获取值
*/
@Override
public String get(final String key) {
return execute(new RedisFunction<String>(){
@Override
public String callback(Jedis jedis) {
return jedis.get(key);
}
});
}
/**
* 删除一个键
*/
@Override
public Long del(final String key) {
return execute(new RedisFunction<Long>(){
@Override
public Long callback(Jedis jedis) {
return jedis.del(key);
}
});
}
/**
* 获取一个键的自增长值
*/
@Override
public Long incr(final String key) {
return execute(new RedisFunction<Long>(){
@Override
public Long callback(Jedis jedis) {
return jedis.incr(key);
}
});
}
}
配置服务调用层的redis配置文件applicationContext-redis.xml
applicationContext-redis.xml
在实际使用中, 如果需要使用单机版, 那么把集群版注释即可, 反之亦然;
在实际业务开发中, redis的业务逻辑是不影响原有的功能下进行添加, 即先从redis中查询是否存在相关数据, 如果没有, 就从数据库中查询出来然后放入redis中; 以下是示例:
如果没有, 则从数据库中查询出来:
那么完成这一系列操作后, 下次再进行以上操作, redis缓存中就会有相关数据, 就会直接访问redis中的目标数据; 以上一系列的操作必须建立在自己本机(我自己是在本机的liunx上安装了集群跟单机版的redis), 有相关的集群跟单机redis并成功启动正常运行的条件下;