一、Redis环境
Redis 官网 :http://redis.io/
windows下载:https://github.com/dmajkic/redis/downloads
1、文件解压缩
2、启动Redis服务器
3、启动Redis客户端
4、测试Redis缓存
redis-cli.exe -h 127.0.0.1 -p 6379
set keytest valuestest 根据key、value加入缓存
get keytest 根据key获取值
flushall 清空所有缓存
5、设置Redis密码
6、conf配置文件
#是否以后台守护进程运行,默认为no, 取值yes, no
daemonize no
#pid文件存放路径
pidfile/var/run/redis.pid
#配置redis端口,默认6379
port6379#绑定ip。默认绑定所有本机ip,一般用在服务器多ip下,可以只监听内网服务器ip,保证服务安全
bind127.0.0.1#sock文件
unixsocket/tmp/redis.sock
#客户端超时时间,单位秒
timeout300#log级别,支持四个级别,debug,notice,verbose,warning
loglevel verbose
#log文件路径
logfile
#log输出到标准设备,logs不写文件,输出到空设备,/deb/nulllogfile stdout
#保存快照的频率,在多长时间内执行一定数量的写操作时,保存快照的频率,可以设置多个条件。如果都注释掉,则不做内存数据持久化。如果只是把redis只用作cache,不开启持久化功能
savesave900 1#是否使用压缩
rdbcompression
#快照数据库名称
dbfilename
#数据库存放路径
dir
#redis主从 做法 在从上填上主的IP和端口号 主上不用做任何设置
slaveof#主库服务器口令,如果主服务器未打开requirepass,则不需要此项
masterauth#在master服务器挂掉或者同步失败时,从服务器是否继续提供服务
slave-serve-stale-data yes
#设置redis服务密码,如果开启,则客户端连接时需要-a 指定密码,否则操作会提示无权限
requirepass foobared
#命令改名,相当于linux alias,可以用改功能屏蔽一些危险命令
rename-command
#最大连接数;0表示不限制
maxclients128#最大使用内存(分配的内存),推荐生产环境下做相应调整,我们用的是只用来做高速缓存,限制2G。默认情况下,redis会占用可用的所有内存
maxmemory#过期策略,提供六种策略
maxmemory-policy volatile-lruvolatile-lru //删除过期和lru 的key(默认值)
allkeys-lru //删除lru算法的key
volatile-random //随机删除即将过期key
allkeys->random //随机删除
volatile-ttl //删除即将过期的
noeviction //永不过期,返回错误
#是否开启appendonlylog,开启的话每次写操作会记一条log。相当于mysql的binlog;不同的是,每次redis启动都会读此文件构建完整数据。即使删除rdb文件,数据也是安全的
appendonly
#日志文件的名称,默认appendonly.aof
appendfilename appendonly.aof
#异步写append file 的策略。类似mysql事物log写方式。三种
appendfsync
appendfsync always//同步,每次写都要flush到磁盘,安全,速度慢。
appendfsync everysec //每秒写(默认值,推荐值)同mysql
appendfsync no //交给操作系统去做flush的动作
#虚拟内存开关
vm-enabled no
#swap文件,不同redis swap文件不能共享。而且生产环境下,不建议放在tmp目录
vm-swap-file /tmp/redis.swap
#vm大小限制。0:不限制,建议60-80%可用内存大小
vm-max-memory 0#根据缓存内容大小调整,默认32字节
vm-page-size 32#page数。每8 page,会占用1字节内存。vm-page-size * vm-pages 等于 swap 文件大小
vm-pages 134217728#vm 最大io线程数。注意:0标志禁止使用vm
vm-max-threads 4
二、实现Redis缓存
1、整体思路
参考Ehcache实现MyBatis二级缓存代码(Maven引用对应jar查阅)
使用Spring管理Redis连接池
模仿EhcacheCache,实现RedisCache
2、pom.xml中加入Maven依赖
org.springframework.data
spring-data-redis
1.6.2.RELEASE
redis.clients
jedis
2.8.0
3、引入applicationContext.xml中引入redis配置
4、redis.properties配置文件
#============================#
#==== Redis settings ====#
#============================#
#redis 服务器 IP
redis.host=127.0.0.1#redis 服务器端口
redis.port=6379#redis 密码
redis.pass=#redis 支持16个数据库(相当于不同用户)可以使不同的应用程序数据彼此分开同时又存储在相同的实例上
redis.dbIndex=3#redis 缓存数据过期时间单位秒(3600*12 = 43 200)
redis.expiration=43200#控制一个 pool 最多有多少个状态为 idle 的jedis实例
redis.maxIdle=200#控制一个 pool 可分配多少个jedis实例
redis.maxActive=1000#当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
redis.maxWait=500#在borrow一个jedis实例时,是否提前进行alidate操作;如果为true,则得到的jedis实例均是可用的;
redis.testOnBorrow=true
5、创建缓存实现类RedisCache
packagecom.hsmdata.springTest.modules.cache;importorg.apache.ibatis.cache.Cache;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.data.redis.connection.jedis.JedisConnection;importorg.springframework.data.redis.connection.jedis.JedisConnectionFactory;importorg.springframework.data.redis.serializer.JdkSerializationRedisSerializer;importorg.springframework.data.redis.serializer.RedisSerializer;importredis.clients.jedis.exceptions.JedisConnectionException;importjava.util.concurrent.locks.ReadWriteLock;importjava.util.concurrent.locks.ReentrantReadWriteLock;/***@author* 2018-04-10 20:50
* $DESCRIPTION}*/
public class RedisCache implementsCache
{private static final Logger logger = LoggerFactory.getLogger(RedisCache.class);private staticJedisConnectionFactory jedisConnectionFactory;private finalString id;/*** The {@codeReadWriteLock}.*/
private final ReadWriteLock readWriteLock = newReentrantReadWriteLock();public RedisCache(finalString id) {if (id == null) {throw new IllegalArgumentException("Cache instances require an ID");
}
logger.debug("MybatisRedisCache:id=" +id);this.id =id;
}
@Overridepublic voidclear()
{
JedisConnection connection= null;try{
connection=jedisConnectionFactory.getConnection();
connection.flushDb();
connection.flushAll();
}catch(JedisConnectionException e)
{
e.printStackTrace();
}finally{if (connection != null) {
connection.close();
}
}
}
@OverridepublicString getId()
{return this.id;
}
@OverridepublicObject getObject(Object key)
{
Object result= null;
JedisConnection connection= null;try{
connection=jedisConnectionFactory.getConnection();
RedisSerializer serializer = newJdkSerializationRedisSerializer();
result=serializer.deserialize(connection.get(serializer.serialize(key)));
}catch(JedisConnectionException e)
{
e.printStackTrace();
}finally{if (connection != null) {
connection.close();
}
}returnresult;
}
@OverridepublicReadWriteLock getReadWriteLock()
{return this.readWriteLock;
}
@Overridepublic intgetSize()
{int result = 0;
JedisConnection connection= null;try{
connection=jedisConnectionFactory.getConnection();
result=Integer.valueOf(connection.dbSize().toString());
}catch(JedisConnectionException e)
{
e.printStackTrace();
}finally{if (connection != null) {
connection.close();
}
}returnresult;
}
@Overridepublic voidputObject(Object key, Object value)
{
JedisConnection connection= null;try{
connection=jedisConnectionFactory.getConnection();
RedisSerializer serializer = newJdkSerializationRedisSerializer();
connection.set(serializer.serialize(key), serializer.serialize(value));
}catch(JedisConnectionException e)
{
e.printStackTrace();
}finally{if (connection != null) {
connection.close();
}
}
}
@OverridepublicObject removeObject(Object key)
{
JedisConnection connection= null;
Object result= null;try{
connection=jedisConnectionFactory.getConnection();
RedisSerializer serializer = newJdkSerializationRedisSerializer();
result=connection.expire(serializer.serialize(key), 0);
}catch(JedisConnectionException e)
{
e.printStackTrace();
}finally{if (connection != null) {
connection.close();
}
}returnresult;
}public static voidsetJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
RedisCache.jedisConnectionFactory=jedisConnectionFactory;
}
}
View Code
6、创建中间类RedisCacheTransfer,完成RedisCache.jedisConnectionFactory的静态注入
packagecom.hsmdata.springTest.modules.cache;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.connection.jedis.JedisConnectionFactory;/***@author* 2018-04-10 20:52
* $DESCRIPTION}*/
public classRedisCacheTransfer {
@Autowiredpublic voidsetJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
RedisCache.setJedisConnectionFactory(jedisConnectionFactory);
}
}
View Code
7、mapper中加入MyBatis二级缓存
8、Mybatis全局开启二级缓存
View Code
9、测试
packagecom.springTest.mybatis.cache;importcom.hsmdata.springTest.modules.entity.User;importcom.hsmdata.springTest.modules.mapper.UserMapper;importcom.hsmdata.springTest.modules.service.UserService;importorg.apache.ibatis.session.SqlSession;importorg.apache.ibatis.session.SqlSessionFactory;importorg.junit.Test;importorg.junit.runner.RunWith;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.test.context.ContextConfiguration;importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;/***@author* 2018-04-10 15:11
* $DESCRIPTION}*/@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/config/applicationContext.xml", "classpath:/config/spring-servlet.xml"})public classCacheTest {
@AutowiredprivateUserService userService;
@AutowiredprivateSqlSessionFactory sqlSessionFactory;/*** 同一个sqlSession*/@Testpublic voidtestFirstCache(){
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMapper userMapper= sqlSession.getMapper(UserMapper.class);
User user=userMapper.selectByPrimaryKey(56);
System.out.println(user);/*对sqlsession执行commit操作,也就意味着用户执行了update、delete等操作,那么数据库中的数据势必会发生变化,如果用户请求数据仍然使用之前内存中的数据,那么将读到脏数据。
所以在执行sqlsession操作后,会清除保存数据的HashMap,用户在发起查询请求时就会重新读取数据并放入一级缓存中了。*/
//sqlSession.commit();
user=userMapper.selectByPrimaryKey(56);
System.out.println(user);
}/*** 不同的sqlSession*/@Testpublic voidtestSecondaryCache(){
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMapper userMapper= sqlSession.getMapper(UserMapper.class);
User user=userMapper.selectByPrimaryKey(56);
System.out.println(user);//即使开启了二级缓存,不同的sqlsession之间的缓存数据也不是想互访就能互访的,必须等到sqlsession关闭了以后,才会把其一级缓存中的数据写入二级缓存。//关闭session//sqlSession.close();//通过sqlSessionFactory创建一个新的session
sqlSession=sqlSessionFactory.openSession();//获取mapper对象
userMapper=sqlSession.getMapper(UserMapper.class);
user=userMapper.selectByPrimaryKey(56);
System.out.println(user);
}/*** 不同的sqlSession*/@Testpublic voidtestSecondaryCache2() {/*User user=new User("cache","123456","cache","","male",20);
userService.insert(user);*/User user= userService.get(56);
System.out.println(user);
User user1= userService.get(56);
System.out.println(user1);
}
@Testpublic voidtestFirstCache2() {/*User user=new User("cache","123456","cache","","male",20);
userService.insert(user);*/User user= userService.getTwo(56);
System.out.println(user);
}
@Testpublic voidtestRedisCache(){
User user=userService.get(55);
System.out.println(user);
User user2=userService.get(56);
System.out.println(user2);
User user3=userService.get(55);
System.out.println(user3);
}
}