Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。
Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
Redis支持数据的备份,即master-slave模式的数据备份。
性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
Redis是一种Nosql数据库
NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。
NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
我主要是看的这篇博文:https://blog.csdn.net/zhanglf02/article/details/74999231#commentBox
环境:jdk1.8+maven+ssm+redis+sqlserver
项目结构:
1.引入redis依赖
org.springframework.data
spring-data-redis
1.0.2.RELEASE
redis.clients
jedis
2.1.0
org.mybatis.caches
mybatis-redis
1.0.0-beta2
2.在spring配置文件中,开启redis缓存
true
false
true
3.添加redis.proerties
redis.ip=127.0.0.1
redis.port=6379
redis.key=SOA
redis.password=
#是否启用redis?true启用,false不启用。
redis.switch=true
jedis.pool.maxActive=3000
jedis.pool.maxIdle=1000
jedis.pool.maxWait=1500
jedis.pool.testOnBorrow=true
jedis.pool.testOnReturn=true
jedis.pool.timeout=5000
4.添加ConfigUtils JedisUtils RedisCache 这3个工具类。
ConfigUtils.java
package com.wolwo.cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Properties;
public class ConfigUtils {
private static Logger logger=LoggerFactory.getLogger(ConfigUtils.class);
public static boolean redisSwitch;
public static int maxIdle;
public static boolean testOnBorrow;
public static boolean testOnReturn;
public static String ip;
public static int port;
public static String key;
public static String password;
public static int timeout;
public static int fail_count=0;
static{
Properties props=new Properties();
try {
props.load(JedisUtils.class.getResourceAsStream("/redis.properties"));
redisSwitch=Boolean.valueOf(props.getProperty("redis.switch"));
maxIdle=Integer.valueOf(props.getProperty("jedis.pool.maxIdle"));
testOnBorrow=Boolean.valueOf(props.getProperty("jedis.pool.testOnBorrow"));
testOnReturn=Boolean.valueOf(props.getProperty("jedis.pool.testOnReturn"));
ip=String.valueOf(props.getProperty("redis.ip"));
port=Integer.valueOf(props.getProperty("redis.port"));
password=String.valueOf(props.getProperty("redis.password"));
key=String.valueOf(props.getProperty("redis.key"));
timeout=Integer.valueOf(props.getProperty("jedis.pool.timeout"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//对redis开关进行设置,有三种情况:1.如果现在开关开,则关闭redispool 2.如果开关关闭,则设置redispool为开启状态 3.现在状态和要设置的状态一致,不做操作。
public static void setSwitch(boolean redisSwitch){
if(true==ConfigUtils.redisSwitch && false== redisSwitch){
logger.info("switch:open-->close");
JedisUtils.closeJedisPool();
}else if(ConfigUtils.redisSwitch==false && true == redisSwitch){
logger.info("switch:close-->open");
JedisUtils.getInstence();
}
ConfigUtils.redisSwitch=redisSwitch;
}
//当redis连接异常超过一定数量之后,不再走redis,但是没有一个机制,当reids恢复后重新使用redis
public static void setFail(){
if(redisSwitch){
fail_count=fail_count+1;
if(fail_count >10){
logger.info("setSwitch(false)");
setSwitch(false);
}
}
}
public static void setSucc(){
if(fail_count >0){
fail_count=0;
}
if(!redisSwitch){
setSwitch(true);
}
}
}
JedisUtils.java
package com.wolwo.cache;
import org.mybatis.caches.redis.SerializeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisUtils {
private static Logger logger=LoggerFactory.getLogger(JedisUtils.class);
private static JedisPool JEDISPOOL;
public static void getInstence(){
if(JEDISPOOL == null){
logger.info("JeidsUtils getInstence...");
try {
JedisPoolConfig conf=new JedisPoolConfig();
conf.setMaxIdle(ConfigUtils.maxIdle);
conf.setTestOnBorrow(ConfigUtils.testOnBorrow);
//当配置中配置有password时,则创建带密码的缓存池
if(ConfigUtils.password !=null && !"".equals(ConfigUtils.password)){
JEDISPOOL=new JedisPool(conf,ConfigUtils.ip,ConfigUtils.port,ConfigUtils.timeout,ConfigUtils.password);
}else{
//没有配置则用无密码的缓存池。
JEDISPOOL=new JedisPool(conf,ConfigUtils.ip,ConfigUtils.port,ConfigUtils.timeout);
}
} catch (Exception e) {
logger.error("加载【jedis.properties】异常,异常信息为:"+e.getMessage());
}
}
}
public static Jedis getJedis(){
try {
return JEDISPOOL.getResource();
} catch (Exception e) {
return null;
}
}
public static void closeJedis(Jedis jedis){
if(jedis !=null){
jedis.quit();
}
}
public static void closeJedisPool(){
if(JEDISPOOL !=null){
JEDISPOOL.destroy();
}
}
//redis 序列化存储Object
public static void put(String id,Object key,Object value){
Jedis jedis=getJedis();
logger.info("redis put ... key =["+key+"]");
try {
jedis.hset(SerializeUtil.serialize(id), SerializeUtil.serialize(key), SerializeUtil.serialize(value));
ConfigUtils.setSucc();
} catch (Exception e) {
ConfigUtils.setFail();
logger.error("redis执行异常【"+e.getMessage()+"】");
}finally{
closeJedis(jedis);
}
}
public static Object get(String id,Object key){
Jedis jedis=getJedis();
try {
Object object = SerializeUtil.unserialize(jedis.hget(SerializeUtil.serialize(id), SerializeUtil.serialize(key)));
logger.info("redis get ... key=["+key+"],value=["+object+"]");
ConfigUtils.setSucc();
return object;
} catch (Exception e) {
ConfigUtils.setFail();
logger.error("Redis执行异常【"+e.getMessage()+"】");
}finally{
closeJedis(jedis);
}
return null;
}
public static Long remove(String id,Object key){
Jedis jedis=getJedis();
try {
Long num = jedis.hdel(id.toString(), key.toString());
ConfigUtils.setSucc();
return num;
} catch (Exception e) {
ConfigUtils.setFail();
logger.error("Redis执行异常,异常信息:"+e.getMessage());
}finally{
closeJedis(jedis);
}
return 0l;
}
public static void removeAll(String id){
Jedis jedis=getJedis();
try {
jedis.del(id.toString());
ConfigUtils.setSucc();
} catch (Exception e) {
ConfigUtils.setFail();
logger.error("Redis执行异常【"+e.getMessage()+"】");
}finally{
closeJedis(jedis);
}
}
public static int getSize(String id){
Jedis jedis=getJedis();
try {
return jedis.hgetAll(SerializeUtil.serialize(id)).size();
} catch (Exception e) {
ConfigUtils.setFail();
logger.error("Redis执行异常【"+e.getMessage()+"】");
}finally{
closeJedis(jedis);
}
return -1;
}
3.RedisCache.java
package com.wolwo.cache;
import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class RedisCache implements Cache {
private static Logger logger = LoggerFactory.getLogger(RedisCache.class);
private String cacheId;
/**
* 读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。如果你的代码只读数据,可以很多人
* 同时读,但不能同时写,那就上读锁;如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上
* 写锁!
*/
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
private final Lock read = readWriteLock.readLock();
private final Lock write = readWriteLock.writeLock();
public RedisCache(String cacheId) {
if (cacheId == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.cacheId = ConfigUtils.key + "." + cacheId;
logger.info("查询结果存入缓存对应的缓存空间生成的名字cacheId: " + this.cacheId);
if (ConfigUtils.redisSwitch) {
JedisUtils.getInstence();
}
}
@Override
public String getId() {
return cacheId;
}
@Override
public void putObject(Object key, Object value) {
// TODO 从缓存中写数据,用写锁锁定,不允许读
logger.info("NTSRedisCache putObject=" + cacheId);
if (ConfigUtils.redisSwitch) {
write.lock();
try {
JedisUtils.put(cacheId, key, value);
} finally {
write.unlock();
}
}
}
@Override
public Object getObject(Object key) {
// TODO 从缓存中读数据,用读锁锁定,不允许写
// logger.info("从缓存cacheId="+cacheId+"中拿数据key="+key+"对应的value");
logger.info("》》》》》》》》》》》》》》》》》在缓存中根据cacheid="+cacheId+" 拿对应的key和value");
if (ConfigUtils.redisSwitch) {
read.lock();
try {
return JedisUtils.get(cacheId, key);
} finally {
read.unlock();
}
}
return null;
}
@Override
public Object removeObject(Object key) {
// TODO 从缓存中改动数据,用写锁锁定,不允许读,改动结束后释放写锁。
logger.info("NTSRedisCache clear =" + cacheId);
if (ConfigUtils.redisSwitch) {
write.lock();
try {
return JedisUtils.remove(cacheId, key);
} finally {
write.unlock();
}
}
return null;
}
@Override
public void clear() {
// TODO 从缓存中改动数据,用写锁锁定,不允许读,改动结束后释放写锁。
logger.info("NTSRedisCache clear =" + cacheId);
if (ConfigUtils.redisSwitch) {
write.lock();
try {
JedisUtils.removeAll(cacheId);
} finally {
write.unlock();
}
}
}
@Override
public int getSize() {
// TODO Auto-generated method stub
logger.info("NTSRedisCache clear =" + cacheId);
if (ConfigUtils.redisSwitch) {
read.lock();
try {
return JedisUtils.getSize(cacheId);
} finally {
read.unlock();
}
}
return -1;
}
@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}
}
按照文章,能够成功,不过需要注意的是:
在JedisUtils 里面, jedis.close()是没有的应该用 jedis.quit() ;JEDISPOOL.close()应该是JEDISPOOL.destroy();
花了快一天,终于做出来了一个demo