本地Cache系统简易设计
为什么使用缓存?降低数据库的访问压力。
提高查询效率。
改善用户体验。
你都了解哪些缓存?数据库内置缓存(DBA修改)。
数据层缓存(由持久层框架决定,例如mybatis)
业务层缓存(由业务层框架以及第三缓存产品决定:本地缓存+分布式缓存)
浏览器缓存(Cache-Control)
设计缓存都应该考虑什么问题?存储结构:使用什么结构存储数据?(数组,链表,散列存储-哈希存储)
淘汰算法:有限容量(LRU,FIFO,.....),不限容量(GC)
并发安全:保证线程安全。
任务调度:每隔多长时间清理一下缓存。
日志记录:是否命中?(命中率)
缓存系统设计基础
缓存标准定义package com.cy.java.cache;
/\*\* Cache接口设计\*/
public interface Cache {
public void putObject(Object key,Object value);
public Object getObject(Object key);
public Object removeObject(Object key);
public void clear();
public int size();
}
简易Cache实现场景应用:存储数据量比较小(因为没有考虑淘汰机制)
没有线程共享(一个线程的内部缓存)
缓存对象生命周期比较短package com.cy.java.cache;
import java.util.HashMap;
import java.util.Map;
/**负责真正存储数据的一个对象,将数据存储到一个map中*/
public class PerpetualCache implements Cache {
/** 特点:线程不安全,key不允许重复,不能保证key的顺序 */
private Map cache=new HashMap<>();
@Override
public void putObject(Object key, Object value) {
cache.put(key, value);
}
@Override
public Object getObject(Object key) {
return cache.get(key);
}
@Override
public Object removeObject(Object key) {
return cache.remove(key);
}
@Override
public void clear() {
cache.clear();
}
@Override
public int size() {
return cache.size();
}
@Override
public String toString() {
return cache.toString();
}
public static void main(String\[\] args) {
Cache cache=new PerpetualCache();
cache.putObject("A", 100);
cache.putObject("B", 200);
cache.putObject("C", 300);
System.out.println(cache);
cache.removeObject("D");
cache.clear();
System.out.println(cache.size());
}
}
构建线程安全Cache对象场景应用:并发环境package com.cy.java.cache;
/**线程安全的cache对象*/
public class SynchronizedCache implements Cache{
private Cache cache;
public SynchronizedCache(Cache cache) {
this.cache=cache;
}
@Override
public synchronized void putObject(Object key, Object value) {
cache.putObject(key, value);
}
@Override
public synchronized Object getObject(Object key) {
// TODO Auto-generated method stub
return cache.getObject(key);
}
@Override
public synchronized Object removeObject(Object key) {
// TODO Auto-generated method stub
return cache.removeObject(key);
}
@Override
public synchronized void clear() {
cache.clear();
}
@Override
public synchronized int size() {
return cache.size();
}
@Override
public String toString() {
return cache.toString();
}
public static void main(String\[\] args) {
SynchronizedCache cache=
new SynchronizedCache(new PerpetualCache());
cache.putObject("A", 100);
cache.putObject("B", 200);
cache.putObject("C", 300);
System.out.println(cache);
}
}
思考:对于SynchronizedCache 有什么优势,劣势?
支持日志记录的Cache实现package com.cy.java.cache;
/** 用于记录命中率的日志cache*/
public class LoggingCache implements Cache {
private Cache cache;
/**记录请求次数*/
private int requests;
/**记录命中次数*/
private int hits;
public LoggingCache(Cache cache) {
this.cache=cache;
}
@Override
public void putObject(Object key, Object value) {
cache.putObject(key, value);
}
@Override
public Object getObject(Object key) {
requests++;
Object obj=cache.getObject(key);
if(obj!=null)hits++;
System.out.println("Cache hit Ratio : "+hits\*1.0/requests);
return obj;
}
@Override
public Object removeObject(Object key) {
return cache.removeObject(key);
}
@Override
public void clear() {
cache.clear();
}
@Override
public int size() {
return cache.size();
}
@Override
public String toString() {
// TODO Auto-generated method stub
return cache.toString();
}
public static void main(String\[\] args) {
SynchronizedCache cache=
new SynchronizedCache(
new LoggingCache(
new PerpetualCache()));
cache.putObject("A", 100);
cache.putObject("B", 200);
cache.putObject("C", 300);
System.out.println(cache);
cache.getObject("D");
cache.