Redis的简介、ssm+redis的整合和使用

Redis简介:

Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。

Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。

Redis不仅仅支持简单的key-value类型的数据,同时还提供listsetzsethash等数据结构的存储。

Redis支持数据的备份,即master-slave模式的数据备份。

Redis 优势

性能极高Redis能读的速度是110000/s,写的速度是81000/s

丰富的数据类型Redis支持二进制案例的 Strings, Lists, Hashes, Sets Ordered Sets 数据类型操作。

原子Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTIEXEC指令包起来。

丰富的特性Redis还支持 publish/subscribe, 通知, key 过期等等特性。

Redis是一种Nosql数据库

NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。

NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。

Redis的配置和使用

我主要是看的这篇博文:https://blog.csdn.net/zhanglf02/article/details/74999231#commentBox

环境:jdk1.8+maven+ssm+redis+sqlserver

项目结构:


1.引入redis依赖

 <!--引入redis-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.caches</groupId>
            <artifactId>mybatis-redis</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>

2.spring配置文件中,开启redis缓存


        <!-- 在使用mybatis时 spring使用sqlsessionFactoryBean 来管理mybatis的sqlsessionFactory -->  
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
                <property name="dataSource" ref="dataSource" />  
                <!-- mybatis配置文件路径 -->
                <!-- 实体类映射文件路径多个使用mybatis/*.xml-->  
                <property name="mapperLocations" value="classpath:mybatis/*.xml" />

                <!--开启redis缓存 -->
                <property name="configurationProperties">
                        <props>
                                <!--全局映射器启用缓存-->
                                <prop key ="cacheEnabled">true</prop>
                                <!--查询时,关闭关连对象即时加载以提高性能-->
                                <prop key="lazyLoadingEnabled">false</prop>
                                <!-- 设置关联对象加载的形态,此处为按需要加载字段(加载字段由sql决定),不会加载关联表的所有字段,以提高性能-->
                                <prop key="aggressiveLazyLoading">true</prop>
                        </props>
                </property>
        </bean>  

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




猜你喜欢

转载自blog.csdn.net/honnyee/article/details/80844651