若是關注功能實現,能夠直接看功能實現部分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’