redis mysql mybatis_Spring + MySQL + Mybatis + Redis【二级缓存】

本文介绍了如何在Windows环境下安装Redis,包括下载、启动、测试缓存操作,以及配置文件详解。接着,文章展示了如何基于Spring Data Redis实现Redis缓存,并在MyBatis中配置二级缓存,包括RedisCache类的实现和相关配置文件的设置。最后,通过测试案例演示了缓存的使用。
摘要由CSDN通过智能技术生成

一、Redis环境

Redis 官网 :http://redis.io/

windows下载:https://github.com/dmajkic/redis/downloads

1、文件解压缩

261439a39afcaad571195d45a7cb184c.png

2、启动Redis服务器

dd42e7db4a4ce8aa7c7d35f015141933.png

3、启动Redis客户端

d28197794c0f931efc6168b4b2f40449.png

4、测试Redis缓存

redis-cli.exe -h 127.0.0.1 -p 6379

set keytest valuestest 根据key、value加入缓存

get keytest 根据key获取值

flushall 清空所有缓存

1cbcee203a04c7eae3ad4e27f84bcc49.png

5、设置Redis密码

956c68dd85f7f2d81a831bde26189e7a.png

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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的静态注入

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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全局开启二级缓存

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值