这两日对Cache研究了一点,读了一些源代码,自己也写了点code,借此假期也算是休闲加学习了。
什么时候用Cache?
在系统中,如果要考虑系统的性能,我们最好都使用Cache,在各个层次上都用上Cache,这样的话可以尽最大程度的减少数据库的压力。估计现在的系统都在分层,vo,po,do(domain object);我们可以把这些东西能缓存的都缓存起来,当然要根据具体系统具体分析(Cache多长时间,Cache多少东西)。
Tip:公司的系统中,由于用一台数据库,数据库的压力一直都是一个很大的问题,timeout,too many connection,等问题应接不暇。
怎么用Cache?
估计每个公司都有自己的Cache framework,简单的就是几个类,麻烦的可以做个小的framework去包装已有的opensource的cache provider。很多opensource的cache provider(例如:oscahe,ehcache)都对性能进行了优化,所以肯定性能比Map好很多,但是肯定不能拿过来就用,那样的话每次调用的时候太过于麻烦,写很多的类,很多的方法。所以说包装是很重要的,建议包装成一个Bus一样的东西(CacheBus,叫做CacheManager比较好),这样的话就可以在各个层次都向上面写和读了。
Tip: Cache就是key value,我们只要能写好key-value怎么写都可以的。这样也让系统变得简单实用(更能体现OO)
Cache Provider
Oh,这方面太多东西了,oscache(貌似停止开发了),ehcache(被terracotta收购了,前途不错),treecache(jbosstreecache大而全),memecached(很火了很久),nosql相关的东西(couchdb,mongodb)。Oh...不能忘记Map
其实用什么都可以,关键是用好,一般的解决方案很简单,既然你要在系统中用Cache并且想风风火火的用一下,那就来个二级Cache,第一级用本地Cache(速度快,但是东西不能太多),第二级,用memcached (能存放大的东东,便宜)。第一级Cache上3分钟(自己要调试确定时间),自动收割到第二级Cache中。
什么在第一级Cache中永远存活? 小的,永远都要用的,例如用户信息,Site信息,一些template等。
特别强调一下
nosql 这方面mongodb和couchdb做的很好,在document相关的东西,可以缓存到这里面,例如:系统要在半天后发一封邮件,这封邮件所有的数据现在内存中都有,比较大的东东。到时候再去太复杂,太浪费内存了。怎么办呢? 放在一级缓存肯定不合适,放在二级缓存,要存活半天呀,太浪费时间了,存在数据库里面,增加压力,也不是很好,NOSQL的mongodb和couchdb就可以解决这个问题,这个schemaless的数据库,可以让你轻松的存任何的东西(性能不错)。(自己要优化一下代码)
举例:
Annotation
@Documented
@java.lang.annotation.Target(value={java.lang.annotation.ElementType.TYPE})
@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
public @interface CacheIt {
//Provide the cacheProvider which will be use to cache the object which is just used to replace the xml configuration.
public String cacheProvider();
//Used to define how long the cache need to be provide
public long cacheDuration();
//The level of the cache, define, level1, level2 (If there is level2 defination in the annotation, the cache will be kick to level2 after the timeout in the level1)
public int cacheLevel();
}
一个VO的configuration
@CacheIt(cacheProvider="com.javaeye.wmwm.cache.impl.HashMapCacheProvider", cacheDuration=10000, cacheLevel=1)
public class TestVo {
@Identifier
public String key;
public String test;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getTest() {
return test;
}
之后写一个CacheManager
public class CommonCacheManager implements CacheManager {
/**
* Cache the object into the cache.
* <p> the provider is defined in the annotation in the related Vo/PO/DO
* <p> the key is annotated by the <code>Identifier</code>.
* @param object represents the input objects which needs to be cached.
*/
public void cache(Object object) {
Cache cache = CachePool.getInstance().loadCache(object.getClass());
Object key = new CacheKeyFinder().find(object);
cache.put(key, object);
}
public Object load(Class<?> clazz, Object key) {
Cache cache = CachePool.getInstance().loadCache(clazz);
return cache.get(key);
}
}