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中取出