Redis内存数据库

  这些天项目上赶得有些急,每天都要学一些新东西,像WebLogic配置啊,Redis的用法啊,反向代理服务器啊(其实都是后台大佬家里有事,我就顶着了-_-||),老师布置的读论文的任务不好意思要拖一拖了((。・_・。)ノI’m sorry~啊~),不过今天的东西也很有用,(如果毕设数据量大的话-_-||),相当有用啊。好了,现在开始Redis学习之旅吧。

  Redis 是完全开源免费的一个高性能的key-value数据库

  Redis 有以下三个特点:
1)Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
2)Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储(这些数据类型主要指的的是value的,key是正常的字符串)
3)Redis支持数据的备份

  Redis的安装:

根据自己的情况,新建一个目录,名字为redis(例如,D:\redis),注意路径中不要出现中文字符.

把下载好的Redis的压缩包解压到新建的指定文件夹中,可见一些可执行文件(版本不同可能此处会有区别)
redis-server.exe redis 服务器
redis-cli.exe redis 命令行客户端
redis-benchmar.exe redis 性能测试工具
redis-check-aof.exe AOF 文件修复工具

  Redis简单的测试:
启动Redis服务器
开启一个cmd窗口
使用cd命令切换目录到 D:\redis
运行 redis-server.exe redis.windows.conf
启动成功后会看到启动的图案和启动信息(包括Redis版本、监听端口号等)
注意:这个服务器的运行窗口不能关闭,如果关闭Redis服务器就停了
注意:ctrl+c可以也关闭redis服务器

启动Redis客户端
另开启一个cmd窗口,原来的不要关闭,不然就无法访问服务端了
切换到redis目录下运行
redis-cli.exe -h 127.0.0.1 -p 6379
或者
redis-cli.exe
不加任何参数默认就是127.0.0.1 和 6379

设置键值对操作 set name briup
取出键值对操作 get name

这时候客户端使用shutdown命令可以关闭服务端

 

其余的一些命令我也不做详细解释了,我使用Redis的重点在于使用Redis作为Mybatis的二级缓存!!!

mybatis缓存分为一级缓存和二级缓存

一级缓存,又叫本地缓存,是PerpetualCache类型的永久缓存,保存在执行器中(BaseExecutor),而执行器又在SqlSession(DefaultSqlSession)中,所以一级缓存的生命周期与SqlSession是相同的。

二级缓存,又叫自定义缓存,实现了Cache接口的类都可以作为二级缓存,所以可配置如encache等的第三方缓存。二级缓存以namespace名称空间为其唯一标识,被保存在Configuration核心配置对象中。

所以我们可以自定义缓存类,实现Mybatis提供的缓存接口Cache,其中的方法使用Jedis来实现,然后把这个缓存实现类配置为Mybatis的二级缓存提供者即可

 

Jedis相关配置文件和工具类

redis.properties

redis.pool.maxTotal=100
redis.pool.maxIdle=20
redis.pool.maxWait=3000
redis.ip=127.0.0.1
redis.port=6379

封装Jedis的工具类
JedisUtils.java

package com.briup.utils;

import java.util.ResourceBundle;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;


/*
 * 工具类
 */
public class JedisUtils {
    
    public static JedisPool jedisPool;
    
    static{
        
        //ResourceBundle会查找classpath下的xxx.properties的文件,xxx是方法中指定的
        ResourceBundle resourceBundle = 
                ResourceBundle.getBundle("redis");
        
        int maxTotal = Integer.parseInt(resourceBundle.getString("redis.pool.maxTotal"));
        int maxIdle = Integer.parseInt(resourceBundle.getString("redis.pool.maxIdle"));
        int maxWait = Integer.parseInt(resourceBundle.getString("redis.pool.maxWait"));
        String ip = resourceBundle.getString("redis.ip");
        int port = Integer.parseInt(resourceBundle.getString("redis.port"));
        
        
        JedisPoolConfig config = new JedisPoolConfig();
        // 设置最大连接数
        config.setMaxTotal(maxTotal);
        // 设置最大空闲数
        config.setMaxIdle(maxIdle);
        // 设置超时时间
        config.setMaxWaitMillis(maxWait);
        // 初始化连接池
        jedisPool = new JedisPool(config, ip, port);
        
    }
    
    
    public static void set(Object key, Object value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.set(SerializingUtils.serialize(key), SerializingUtils.serialize(value));
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
    }

    
    public static Object get(Object key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            byte[] keyBytes = SerializingUtils.serialize(key);
            if(jedis.exists(keyBytes)){
                return SerializingUtils.deserialize(jedis.get(keyBytes));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return null;
    }
    
    public static void del(Object key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.del(SerializingUtils.serialize(key));
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
    }
    
    public static void clear() {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.flushDB();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
    }
    public static int getSize() {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            jedis.close();
        }
        return jedis.dbSize().intValue();
    }
    
    public static Jedis getResource(){
        return jedisPool.getResource();
    }
    
    
}

SerializingUtils.java

package com.briup.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;


/*
 * 工具类
 */
public class SerializingUtils {
    
    //java对象 ---> 字节数组
    public static byte[] serialize(Object obj) {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream out = null;
        try {
            bos = new ByteArrayOutputStream();
            out = new ObjectOutputStream(bos);
            out.writeObject(obj);
            out.flush();
        }
        catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(out!=null)out.close();
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bos.toByteArray();
    }
    
    //字节数组 ---> java对象
    public static Object deserialize(byte[] data) {
        ObjectInputStream in = null;
        Object obj = null;
        try {
            ByteArrayInputStream bis = new ByteArrayInputStream(data);
            in = new ObjectInputStream(bis);
            obj = in.readObject();
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if(in!=null)in.close();
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
        return obj;
    }
    
    
}

封装MyBatis的工具类
MyBatisSqlSessionFactory.java

package com.briup.utils;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyBatisSqlSessionFactory {
    private static SqlSessionFactory sqlSessionFactory;
    
    public static SqlSessionFactory getSqlSessionFactory(){
        if(sqlSessionFactory == null){
            InputStream inputStream = null;
            try {
                inputStream = Resources.getResourceAsStream("mybatis-config.xml"); 
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e.getCause());
            }
        }
        return sqlSessionFactory;
    }
    
    public static SqlSession openSession() { 
        return openSession(false); 
    }
    public static SqlSession openSession(boolean autoCommit) { 
        return getSqlSessionFactory().openSession(autoCommit); 
    }
    
}

自定义cache接口实现类MybatisRedisCache.java

package com.briup.cache;

import java.util.concurrent.locks.ReadWriteLock;

import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheException;

import com.briup.utils.JedisUtils;
/**
 * Cache为缓存接口,给缓存供应商的SPI(Service Provider Interface)
 * Cache接口的实现类必须有一个具有String类型参数的构造方法,该参数作为实现类对象的id,对其进行唯一标识
 */
public class MybatisRedisCache implements Cache{

    private String id;
    
    public MybatisRedisCache(String id) {
        this.id = id;
    }
    
    /**
     * 清空缓存
     */
    @Override
    public void clear() {
        JedisUtils.clear();
    }
    
    /**
     * 获取缓存类对象的唯一标识
     */
    @Override
    public String getId() {
        return this.id;
    }
    
    /**
     * 从缓存中获取key对应的value
     */
    @Override
    public Object getObject(Object key) {
        return JedisUtils.get(key);
    }
    
    
    /**
     * 获取读写锁
     * 可选的方法,从3.2.6起这个方法不再被框架核心调用
     * 任何需要的锁,都必须由缓存供应商提供
     */
    @Override
    public ReadWriteLock getReadWriteLock() {
        
        return null;
    }
    
    /**
     * 获取缓存对象中存储的键/值对的数量
     * 可选的方法,没有被框架核心调用
     */
    @Override
    public int getSize() {
        return JedisUtils.getSize();
    }
    
    /**
     * 保存key/value到缓存对象中
     * key可以是任何对象
     */
    @Override
    public void putObject(Object key, Object value) {
        JedisUtils.set(key, value);
    }
    
    
    /**
     * 可选的方法,没有被核心框架调用,移除key对应的value
     */
    @Override
    public Object removeObject(Object key) {
        
        return null;
    }
    
    /**
     * 重新equals方法
     */
    @Override
    public boolean equals(Object o) {
        if (getId() == null)
            throw new CacheException("Cache instances require an ID.");
        if (this == o)
            return true;
        if (!(o instanceof Cache))
            return false;

        Cache otherCache = (Cache) o;
        return getId().equals(otherCache.getId());
    }
    
    /**
     * 重新hashCode方法
     */
    @Override
    public int hashCode() {
        if (getId() == null)
            throw new CacheException("Cache instances require an ID.");
        return getId().hashCode();
    }

}

在mybatis中开启二级缓存(虽然默认也是开启的)

<settings>
<setting name="cacheEnabled" value="true"/>
</settings>

配置<cache/>标签
在需要缓冲的映射文件中加入<cache/>标签,并且指定提供缓存功能的cache实现类的全限定名

<cache type="XXX.MybatisRedisCache"></cache>

测试:

  第一次运行,mybatis【发出】对应select进行查询数据库,然后在redis中查看key可知,已经把数据存进了redis中,
之后再运行,mybatis【不发出】sql语句,数据直接从redis中取出

 

posted @ 2018-04-01 14:33  渊源谭  阅读(449)  评论(4编辑  收藏  举报