Play 框架初探之缓存
Play 提供两种缓存方式:
-
JVM 内存缓存
-
使用Memcached 缓存
Play 的CacheImpl 接口( 不知道为什么如此命名) 中提供了safeDelete ,safeAdd ,incr,decr 等高级操作接口,但是两种机制内部实现却大有区别。
方式一基于JVM 内存的缓存方案通过重度封装Ehcache 来做内存缓存,Ehcache 的优点之一是引用非常简单。尽管Cache 是线程安全的,但是是对于set 和get 操作没有内置的timeout 接口,对于incr 和decr 操作需要手动处理并发,总的来说还是需要外层封装代码做不少工作。
// 实现increase需要手动处理并发
public synchronized long incr(String key, int by) {
Element e = cache.get(key);
if (e == null) {
return -1;
}
long newValue = ((Number) e.getValue()).longValue() + by;
Element newE = new Element(key, newValue);
newE.setTimeToLive(e.getTimeToLive());
cache.put(newE);
return newValue;
}
方式二使用Memcached 作为缓存实现,轻度封装了spyMemcached 来连接Memcached, 。spyMemcached 的初始化比较繁琐,但是其使用nio 和concurrent 包的一些机制,存取速度比同类的客户端要快。最重要的一点是spyMemcached 提供了丰富的操作接口,Play 不需要做额外的并发控制处理。
// 客户端提供了increase接口
public long incr(String key, int by) {
return client.incr(key, by, 0);
}
// 异步的safeAdd
public boolean safeAdd(String key, Object value, int expiration) {
Future<Boolean> future = client.add(key, expiration, value, tc);
try {
return future.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
future.cancel(false);
}
return false;
}
总的来说,Play的缓存机制非常简单,选用了存取速度快但是稳定性欠妥的spyMemcached作为Memcached客户端,所以轻量、敏捷是Play所注重的