本片文章续《Spring Boot 入门(九):集成Quartz定时任务》。本文主要基于redis实现了mybatis二级缓存。较redis缓存,mybaits自带缓存存在缺点(自行谷歌)。本文是基于docker安装redis主从模式。

1.redis安装

(1)首先安装redis集群模式,建立redis目录,并编写主从模式docker-compose.yml文件

 version: '3.1'
services:
master:
image: redis
container_name: redis-master
ports:
- 6379:6379 slave1:
image: redis
container_name: redis-slave-1
ports:
- 6380:6379
command: redis-server --slaveof redis-master 6379 slave2:
image: redis
container_name: redis-slave-2
ports:
- 6381:6379
command: redis-server --slaveof redis-master 6379

(2).启动 docker-compose up -d

(3).建立sentinel文件,并编写docker-compose.yml文件

 version: '3.1'
services:
sentinel1:
image: redis
container_name: redis-sentinel-1
ports:
- 26379:26379
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
volumes:
- ./sentinel1.conf:/usr/local/etc/redis/sentinel.conf sentinel2:
image: redis
container_name: redis-sentinel-2
ports:
- 26380:26379
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
volumes:
- ./sentinel2.conf:/usr/local/etc/redis/sentinel.conf sentinel3:
image: redis
container_name: redis-sentinel-3
ports:
- 26381:26379
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
volumes:
- ./sentinel3.conf:/usr/local/etc/redis/sentinel.conf

从模式需要sentinel的conf文件,我创建了3个容器,所以这里需要3份(sentinel1.conf sentinel2.conf sentinel3.conf),内容是一模一样

 port 26379
dir /tmp
sentinel monitor mymaster 217.0.0.1 6379 2
sentinel down-after-milliseconds rmaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes

(4).启动:docker-compose up -d

(5).验证redis是否已经成功启动

进入容器:docker exec -it redis-sentinel-1 /bin/bash

连接redis:redis-cli -p 26379

如下图,表示启动成功

也可以通过桌面客户端查看是否启动成功,如图,我使用的RedisDesktopManager客户端

 这里有个问题可以思考:传统的redis集群,即cluster,也有主从模式,现在为什么大家都选择sentinel主从模式?

2.编写RedisCache工具类

网上一大堆,根据自己需要选择合适的utils(有的utils中方法很全)

 package com.learn.hello.system.utils;

 import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; /**
* @ClassName RedisCache
* @Deccription 通过redis实现mybaits的二级缓存
* @Author DZ
* @Date 2020/1/12 22:41
**/
@Slf4j
public class RedisCache implements Cache { private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final String id; // cache instance id
private RedisTemplate redisTemplate; private static final long EXPIRE_TIME_IN_MINUTES = 30; // redis过期时间 public RedisCache(String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
} @Override
public String getId() {
return id;
} /**
* Put query result to redis
*
* @param key
* @param value
*/
@Override
public void putObject(Object key, Object value) {
try {
RedisTemplate redisTemplate = getRedisTemplate();
ValueOperations opsForValue = redisTemplate.opsForValue();
opsForValue.set(key, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);
log.debug("Put query result to redis");
} catch (Throwable t) {
log.error("Redis put failed", t);
}
} /**
* Get cached query result from redis
*
* @param key
* @return
*/
@Override
public Object getObject(Object key) {
try {
RedisTemplate redisTemplate = getRedisTemplate();
ValueOperations opsForValue = redisTemplate.opsForValue();
log.debug("Get cached query result from redis");
return opsForValue.get(key);
} catch (Throwable t) {
log.error("Redis get failed, fail over to db", t);
return null;
}
} /**
* Remove cached query result from redis
*
* @param key
* @return
*/
@Override
@SuppressWarnings("unchecked")
public Object removeObject(Object key) {
try {
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.delete(key);
log.debug("Remove cached query result from redis");
} catch (Throwable t) {
log.error("Redis remove failed", t);
}
return null;
} /**
* Clears this cache instance
*/
@Override
public void clear() {
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.execute((RedisCallback) connection -> {
connection.flushDb();
return null;
});
log.debug("Clear all the cached query result from redis");
} /**
* This method is not used
*
* @return
*/
@Override
public int getSize() {
return 0;
} @Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
} private RedisTemplate getRedisTemplate() {
if (redisTemplate == null) {
redisTemplate = SpringContextHolder.getBean("redisTemplate");
}
return redisTemplate;
}
}

3.在接口类增加redis缓存注解

@CacheNamespace(implementation = RedisCache.class)

例如:

 @CacheNamespace(implementation = RedisCache.class)
public interface RoleMapper extends MyMapper<Role> {
List<Role> selectByCondition(ModelMap modelMap); Role selectById(int id); List<Role> selectAllRole();
}

这里也可以直接在MyMapper父接口中增加注解,这样,所有的接口就不需要单独增加这个注解(根据业务需要自行素选择)。

4.配置application.yml

 spring:
redis:
# 哨兵模式推荐使用lettuce作为客户端,弃用jedis
lettuce:
# 连接池配置
pool:
# 连接池中的最小空闲连接,默认 0
min-idle: 0
# 连接池中的最大空闲连接,默认 8
max-idle: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制),默认 -1ms
max-wait: -1ms
# 连接池最大连接数(使用负值表示没有限制),默认 8
max-active: 8
# 集群模式
# cluster:
# nodes: 192.168.1.12:6379,192.168.1.12:6380,192.168.1.12:6381
# 哨兵模式
sentinel:
master: mymaster
nodes: 192.168.1.12:26379,192.168.1.12:26380,192.168.1.12:26381
 mybatis:
mapper-locations: classpath:mapper/*.xml
# 此配置的作用:xml中不用写实体类的全路径
type-aliases-package: com.learn.hello.modules.entity
# 查询的null字段也返回
configuration:
call-setters-on-nulls: true
# 开启二级缓存
cache-enabled: true

5.效果

当进行CURD操作时,相关的检索sql语句就会缓存到redis,如图:

当再次对相关数据进行CRUD时,就会走缓存

Spring Boot 入门(十):集成Redis哨兵模式,实现Mybatis二级缓存的更多相关文章

  1. Spring Boot 如何快速集成 Redis 哨兵?

    上一篇:Spring Boot 如何快速集成 Redis? 前面的分享栈长介绍了如何使用 Spring Boot 快速集成 Redis,上一篇是单机版,也有粉丝留言说有没有 Redis Sentine ...

  2. Springboot2.x集成Redis哨兵模式

    Springboot2.x集成Redis哨兵模式 说明 Redis哨兵模式是Redis高可用方案的一种实现方式,通过哨兵来自动实现故障转移,从而保证高可用. 准备条件 pom.xml中引入相关jar ...

  3. 7、Spring Boot 2.x 集成 Redis

    1.7 Spring Boot 2.x 集成 Redis 简介 继续上篇的MyBatis操作,详细介绍在Spring Boot中使用RedisCacheManager作为缓存管理器,集成业务于一体. ...

  4. 搞懂分布式技术14:Spring Boot使用注解集成Redis缓存

    本文内容参考网络,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutor ...

  5. Logstash2.3.4趟坑之集成Redis哨兵模式

    最新在使用Lostash2.3.4收集数据的时候,在读取redis数据的时候,报了如下的一个异常: 异常如下 Pipeline aborted due to error {:exception=> ...

  6. Spring Boot入门系列(六)如何整合Mybatis实现增删改查

    前面介绍了Spring Boot 中的整合Thymeleaf前端html框架,同时也介绍了Thymeleaf 的用法.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/z ...

  7. Spring Boot 入门系列(二十三)整合Mybatis,实现多数据源配置!

    d之前介绍了Spring Boot 整合mybatis 使用注解方式配置的方式实现增删改查以及一些复杂自定义的sql 语句 .想必大家对spring boot 项目中,如何使用mybatis 有了一定 ...

  8. Spring Boot 入门(十一):集成 WebSocket, 实时显示系统日志

    以前面的博客为基础,最近一篇为Spring Boot 入门(十):集成Redis哨兵模式,实现Mybatis二级缓存.本篇博客主要介绍了Spring Boot集成 Web Socket进行日志的推送, ...

  9. Spring Boot 入门(十三):集成Hasor的Dataway模块,干掉后台,自动配置接口

    终于出湖北了,封闭2个月,家里没电脑,感觉好久没自主撸代码啊啊啊啊啊啊啊啊啊啊啊啊啊. 连接上篇文章Spring Boot 入门(十二):报表导出,对比poi.jxl和esayExcel的效率,继续从 ...

随机推荐

  1. springmvc单Redis实例实现分布式锁(解决锁超时问题)

    一.前言 关于redis分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完的问题, 这样会导致: A线程超时时间设为10s(为了解决死锁问题 ...

  2. vue创建脚手架 cil

    1.检查环境是否安装好了!node -vnpm -vnpm install cnpm -g --registry=https://registry.npm.taobao.orgcpm -v (版本与n ...

  3. spring boot + thymeleaf 乱码问题

    spring boot + thymeleaf 乱码问题 hellotrms 发布于 2017/01/17 15:27 阅读 1K+ 收藏 0 答案 1 开发四年只会写业务代码,分布式高并发都不会还做 ...

  4. 有趣的一行 Python 代码

    https://mp.weixin.qq.com/s/o9rm4tKsJeEWyqQDgVEQiQ https://mp.weixin.qq.com/s/G5F_GaUGI0w-kugOZX145g ...

  5. vue 弹窗时 监听手机返回键关闭弹窗(页面不跳转)

    [注]:  popstate 事件 a.当活动历史记录条目更改时,将触发popstate事件. b.如果被激活的历史记录条目是通过对history.pushState()的调用创建的,或者受到对his ...

  6. tensorflow在文本处理中的使用——TF-IDF算法

    代码来源于:tensorflow机器学习实战指南(曾益强 译,2017年9月)——第七章:自然语言处理 代码地址:https://github.com/nfmcclure/tensorflow-coo ...

  7. Linux 内核SBus连接

    当大部分计算机配备有 PCI 或 ISA 接口总线, 大部分老式的基于 SPARC 的工作站使用 SBus 来连接它们的外设. SBus 使一个非常先进的设计, 尽管它已出现很长时间. 它意图是处理器 ...

  8. 【t044】弗洛伊德

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 弗洛伊德是一个大牛!给一个有向图G,他有n个结点,现在请你求出对于他的每一对结点(x,y),从x出发走 ...

  9. C# dotnet 获取整个局域网的 ip 地址

    局域网可以使用的 IP 地址有很多,我写了一段代码用来枚举所有可以用的 ip 地址 小伙伴都知道,局域网可以使用的 IP 范围如下 A类地址:10.0.0.0 - 10.255.255.255 B类地 ...

  10. geoip ip2region2 with spark

    上一篇文章中 我使用 maxmind的免费库开发了一个waterdrop的 插件,测试数据发现,国内的有些市级还是不准确,而且香港并不是显示中国,这就不友好了. 找了一下,发下 ip2region 这 ...