若是关注功能实现,能够直接看功能实现部分java
一个宗旨---不常变的稳定而经常使用的node
缓存并不全是优势,缺点很明显,缓存有时不是最新的数据。redis
这是一个跨Sqlsession级虽的缓存,是mapper级别的,也就是能够多个sqlsession访问同一个mapper时生效spring
关键字 | 解读 |
---|---|
eviction | 缓存回收策略 |
flushInterval | 刷新时间间隔,单位毫秒 |
size | 引用数目,表明缓存最多能够存多少对象 |
readOnly | 是否只读默认false 若是True全部的sql返回的是一个对象,性能高并发安全性底,若是false返回的是序列化后的副本,安全高效率底 |
WEAK 弱引用 更积极的移除移除基于垃圾回收器状态和弱引用规则的对象sql
<!-- 开启二级缓存 --> <setting name="cacheEnabled" value="true"/> <select id="" resultMap="" useCache="false"> <update id="" parameterType="" flushCache="false" />
手动执行sqlsession.clearCache()apache
<!-- 集成了lettuce的链接方式也能够用jedis方式看本身建议用集成的说明稳定些 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- 序列化 --> <dependency> <groupId>de.javakaffee</groupId> <artifactId>kryo-serializers</artifactId> </dependency> <!-- 链接池 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!-- 自定义获取Bean --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <!-- 断言判断,正式环境中可使用 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency>
spring: redis: lettuce: pool: max-active: 8 max-wait: -1ms max-idle: 8 min-idle: 0 #集群的方式 # sentinel: # master: mymaster # nodes: 192.168.15.154:6379 database: 0 host: 192.168.15.154 port: 6379 # MyBatis Config properties mybatis: type-aliases-package: mapper-locations: classpath:mapper/*.xml configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl cache-enabled: true
private static final long serialVersionUID =-1L;
/** * @author lyy * @description * @date 2019/9/2 */ public class RedisCache implements Cache { private static final Logger logger = LoggerFactory.getLogger(RedisCache.class); private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); // cache instance id private final String id; private RedisTemplate redisTemplate; // redis过时时间 private static final long EXPIRE_TIME_IN_MINUTES = 30; 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); logger.debug("Put query result to redis"); } catch (Throwable t) { logger.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(); logger.debug("Get cached query result from redis"); return opsForValue.get(key); } catch (Throwable t) { logger.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); logger.debug("Remove cached query result from redis"); } catch (Throwable t) { logger.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; }); logger.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 = ApplicationContextHolder.getBean("redisTemplate"); } return redisTemplate; } }
/** * @author lyy * @description * @date 2019/9/2 */ @Component public class ApplicationContextHolder implements ApplicationContextAware, DisposableBean { private static final Logger logger = LoggerFactory.getLogger(ApplicationContextHolder.class); private static ApplicationContext applicationContext; public static ApplicationContext getApplicationContext() { if (applicationContext == null) { throw new IllegalStateException( "'applicationContext' property is null,ApplicationContextHolder not yet init."); } return applicationContext; } /** * * 根据bean的id来查找对象 * * @param id * * @return * */ public static Object getBeanById(String id) { checkApplicationContext(); return applicationContext.getBean(id); } /** * * 经过名称获取bean * * @param name * * @return * */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) { checkApplicationContext(); Object object = applicationContext.getBean(name); return (T) object; } /** * * 根据bean的class来查找对象 * * @param c * * @return * */ @SuppressWarnings("all") public static <T> T getBeanByClass(Class<T> c) { checkApplicationContext(); return (T) applicationContext.getBean(c); } /** * * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型. * 若是有多个Bean符合Class, 取出第一个. * * @param cluss * * @return * */ public static <T> T getBean(Class<T> cluss) { checkApplicationContext(); return (T) applicationContext.getBean(cluss); } /** * * 名称和所需的类型获取bean * * @param name * * @param cluss * * @return * */ public static <T> T getBean(String name, Class<T> cluss) { checkApplicationContext(); return (T) applicationContext.getBean(name, cluss); } public static <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException { checkApplicationContext(); return applicationContext.getBeansOfType(type); } /** * 检查ApplicationContext不为空. */ private static void checkApplicationContext() { if (applicationContext == null) { throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义ApplicationContextHolderGm"); } } @Override public void destroy() throws Exception { checkApplicationContext(); } /** * 清除applicationContext静态变量 */ public static void cleanApplicationContext() { applicationContext = null; } @Override public void setApplicationContext(ApplicationContext context) throws BeansException { //checkApplicationContext(); applicationContext = context; logger.info("holded applicationContext,显示名称:" + applicationContext.getDisplayName()); } }
@CacheNamespace(implementation = RedisCache.class)
<cache type="***.RedisCache"> <property name="eviction" value="LRU"/> <property name="flushInterval" value="60000000"/> <property name="size" value="2048"/> <property name="readOnly" value="false"/> </cache>
# Examples: # # bind 192.168.1.100 10.0.0.1 bind 0.0.0.0
File -> Settings -> Inspections -> Serialization issues -> Serialization class without ‘serialVersionUID’