一、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
port 6379 #绑定ip。默认绑定所有本机ip,一般用在服务器多ip下,可以只监听内网服务器ip,保证服务安全
bind 127.0.0.1 #sock文件
unixsocket /tmp/redis.sock #客户端超时时间,单位秒
timeout 300 #log级别,支持四个级别,debug,notice,verbose,warning
loglevel verbose #log文件路径
logfile #log输出到标准设备,logs不写文件,输出到空设备,/deb/null
logfile stdout #保存快照的频率,在多长时间内执行一定数量的写操作时,保存快照的频率,可以设置多个条件。如果都注释掉,则不做内存数据持久化。如果只是把redis只用作cache,不开启持久化功能
save <seconds> <changes>
save 900 1 #是否使用压缩
rdbcompression #快照数据库名称
dbfilename #数据库存放路径
dir #redis主从 做法 在从上填上主的IP和端口号 主上不用做任何设置
slaveof <masterip> <masterport> #主库服务器口令,如果主服务器未打开requirepass,则不需要此项
masterauth <master-password> #在master服务器挂掉或者同步失败时,从服务器是否继续提供服务
slave-serve-stale-data yes #设置redis服务密码,如果开启,则客户端连接时需要 -a 指定密码,否则操作会提示无权限
requirepass foobared #命令改名,相当于linux alias,可以用改功能屏蔽一些危险命令
rename-command #最大连接数;0 表示不限制
maxclients 128 #最大使用内存(分配的内存),推荐生产环境下做相应调整,我们用的是只用来做高速缓存,限制2G。默认情况下,redis会占用可用的所有内存
maxmemory <bytes> #过期策略,提供六种策略
maxmemory-policy volatile-lru
volatile-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依赖

<!-- spring-redis实现 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.2.RELEASE</version>
</dependency>
<!-- redis客户端jar -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>

3、引入applicationContext.xml中引入redis配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- redis数据源 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxActive}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!-- Spring-redis连接池管理工厂 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/>
<!-- 使用中间类解决RedisCache.jedisConnectionFactory的静态注入,从而使MyBatis实现第三方缓存 -->
<bean id="redisCacheTransfer" class="com.hsmdata.springTest.modules.cache.RedisCacheTransfer">
<property name="jedisConnectionFactory" ref="jedisConnectionFactory"/>
</bean>
</beans>

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

package com.hsmdata.springTest.modules.cache;

import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.jedis.JedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import redis.clients.jedis.exceptions.JedisConnectionException; import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; /**
* @author
* 2018-04-10 20:50
* $DESCRIPTION}
*/ public class RedisCache implements Cache
{
private static final Logger logger = LoggerFactory.getLogger(RedisCache.class); private static JedisConnectionFactory jedisConnectionFactory; private final String id; /**
* The {@code ReadWriteLock}.
*/
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); public RedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
logger.debug("MybatisRedisCache:id=" + id);
this.id = id;
} @Override
public void clear()
{
JedisConnection connection = null;
try
{
connection = jedisConnectionFactory.getConnection();
connection.flushDb();
connection.flushAll();
}
catch (JedisConnectionException e)
{
e.printStackTrace();
}
finally
{
if (connection != null) {
connection.close();
}
}
} @Override
public String getId()
{
return this.id;
} @Override
public Object getObject(Object key)
{
Object result = null;
JedisConnection connection = null;
try
{
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
result = serializer.deserialize(connection.get(serializer.serialize(key)));
}
catch (JedisConnectionException e)
{
e.printStackTrace();
}
finally
{
if (connection != null) {
connection.close();
}
}
return result;
} @Override
public ReadWriteLock getReadWriteLock()
{
return this.readWriteLock;
} @Override
public int getSize()
{
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();
}
}
return result;
} @Override
public void putObject(Object key, Object value)
{
JedisConnection connection = null;
try
{
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
connection.set(serializer.serialize(key), serializer.serialize(value));
}
catch (JedisConnectionException e)
{
e.printStackTrace();
}
finally
{
if (connection != null) {
connection.close();
}
}
} @Override
public Object removeObject(Object key)
{
JedisConnection connection = null;
Object result = null;
try
{
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
result =connection.expire(serializer.serialize(key), 0);
}
catch (JedisConnectionException e)
{
e.printStackTrace();
}
finally
{
if (connection != null) {
connection.close();
}
}
return result;
} public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
RedisCache.jedisConnectionFactory = jedisConnectionFactory;
} }

6、创建中间类RedisCacheTransfer,完成RedisCache.jedisConnectionFactory的静态注入

package com.hsmdata.springTest.modules.cache;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; /**
* @author
* 2018-04-10 20:52
* $DESCRIPTION}
*/ public class RedisCacheTransfer {
@Autowired
public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
RedisCache.setJedisConnectionFactory(jedisConnectionFactory);
}
}

7、mapper中加入MyBatis二级缓存

<mapper namespace="com.hsmdata.springTest.modules.mapper.UserMapper" >
<!--开启本mapper的二级缓存,隔10秒自动刷新缓存 flushInterval="10000" -->
<cache type="com.hsmdata.springTest.modules.cache.RedisCache" />

8、Mybatis全局开启二级缓存

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 开启二级缓存,默认是false -->
<setting name="cacheEnabled" value="true"/> <!--resultMap中的association和collection标签具有延迟加载的功能。-->
<!--延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息。使用关联信息时再去加载关联信息。--> <!-- lazyLoadingEnabled:延迟加载启动,默认是false
全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。-->
<setting name="lazyLoadingEnabled" value="false"/> <!-- aggressiveLazyLoading:积极的懒加载,false的话按需加载,默认是true
当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。-->
<setting name="aggressiveLazyLoading" value="true"/> <setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="true"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25000"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
</configuration>

9、测试

package com.springTest.mybatis.cache;

import com.hsmdata.springTest.modules.entity.User;
import com.hsmdata.springTest.modules.mapper.UserMapper;
import com.hsmdata.springTest.modules.service.UserService;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.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 class CacheTest {
@Autowired
private UserService userService;
@Autowired
private SqlSessionFactory sqlSessionFactory; /**
* 同一个sqlSession
*/
@Test
public void testFirstCache(){
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
*/
@Test
public void testSecondaryCache(){
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
*/
@Test
public void testSecondaryCache2() {
/* 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);
} @Test
public void testFirstCache2() {
/* User user=new User("cache","123456","cache","","male",20);
userService.insert(user);*/ User user = userService.getTwo(56);
System.out.println(user);
} @Test
public void testRedisCache(){
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); } }
 

Spring + MySQL + Mybatis + Redis【二级缓存】的更多相关文章

  1. Spring Boot + Mybatis + Redis二级缓存开发指南

    Spring Boot + Mybatis + Redis二级缓存开发指南 背景 Spring-Boot因其提供了各种开箱即用的插件,使得它成为了当今最为主流的Java Web开发框架之一.Mybat ...

  2. Spring + MySQL + Mybatis + Redis【二级缓存】执行流程分析

    一级缓存基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就 ...

  3. Redis集成到Spring做mybatis做二级缓存

    一.原理: 要缓存的 Java 对象必须实现 Serializable 接口,因为 Spring 会将对象先序列化再存入 Redis,比如本文中的 com.defonds.bdp.city.bean. ...

  4. springboot mybatis redis 二级缓存

    前言 什么是mybatis二级缓存? 二级缓存是多个sqlsession共享的,其作用域是mapper的同一个namespace. 即,在不同的sqlsession中,相同的namespace下,相同 ...

  5. spring+springmvc+mybatis+redis实现缓存

    先搭建好redis环境 需要的jar如下: jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:330 ...

  6. 使用Redis做MyBatis的二级缓存

    使用Redis做MyBatis的二级缓存 通常为了减轻数据库的压力,我们会引入缓存.在Dao查询数据库之前,先去缓存中找是否有要找的数据,如果有则用缓存中的数据即可,就不用查询数据库了. 如果没有才去 ...

  7. Redis实现Mybatis的二级缓存

    一.Mybatis的缓存 通大多数ORM层框架一样,Mybatis自然也提供了对一级缓存和二级缓存的支持.一下是一级缓存和二级缓存的作用于和定义. 1.一级缓存是SqlSession级别的缓存.在操作 ...

  8. Mybatis使用Redis二级缓存

    在Mybatis中允许开发者自定义自己的缓存,本文将使用Redis作为Mybatis的二级缓存.在Mybatis中定义二级缓存,需要如下配置: 1. MyBatis支持二级缓存的总开关:全局配置变量参 ...

  9. mybatis整合redis二级缓存

    mybatis默认开启了二级缓存功能,在mybatis主配置文件中,将cacheEnabled设置成false,则会关闭二级缓存功能 <settings> <!--二级缓存默认开启, ...

随机推荐

  1. 二、Python安装扩展库

    第一步:推荐easy_install工具 下载地址:https://pypi.python.org/pypi/setuptools 下载"ez_setup.py"文件; 通过运行c ...

  2. libxml2用xpath进行查找

    xml文档 <?xml version="1.0" encoding="UTF-8"?> <radios> <radio> ...

  3. IOS ASI和AFN的 区别

    一.底层实现 1> AFN的底层基于OC的NSURLConnection和NSURLSession2> ASI的底层基于纯C语言的CFNetwork框架3> ASI的运行性能 高于 ...

  4. ABP问题记录

    按照<Asp.NET Core2.0与 EF的ABP框架入门视频教程>(https://ke.qq.com/course/287301)下载了3.9版本的ABP,开始学习,下面记录遇到的问 ...

  5. Android学习笔记_46_Android的intent之间Object、List、List<Object>和全局变量数据的传递(Parcelable Serializable)

    转http://blog.csdn.net/pku_android/article/details/7456305 一.传递List<String>和List<Integer> ...

  6. Restframework框架总结及restful规范

    1. django rest framework框架的作用? 帮助开发者可以快速开发出遵循restful规范的API 2. django rest framework框架都有哪些组件(10)? -版本 ...

  7. 优雅的QSignleton (三) 通过属性器实现Singleton

    接下来介绍,不通过继承的方式实现单例模式.大家都出去嗨了,而我却在家码代码... 代码如下: MonoSingletonProperty.cs namespace QFramework.Example ...

  8. Linux基础 ppt pptx

    引言 以前写过一个讲 Linux 基础的ppt,琢磨着把它分享出来,有需要的请自取. 部分截图如下 下载地址 下载地址1

  9. CF1042C Array Product(贪心,模拟)

    题目描述 You are given an array aa consisting of nn integers. You can perform the following operations w ...

  10. yarn的学习之1-架构

    本文翻译自http://hadoop.apache.org/docs/r2.8.0/hadoop-yarn/hadoop-yarn-site/YARN.html 译注:原文说得有些过于简单的,并且有些 ...