论坛首页 Java版 企业应用

Remote Cache, Transaction

浏览 17407 次
该帖已经被评为精华帖
作者 正文
最后更新时间:2006-09-11
1. Remote Cache

Remote Cache 是对应于Local Cache来说的。
Key or Value 需要序列化,需要内部网络通信。

Remote Cache 可分为 中心Cache,和Cluster Cache。

Cluster Cache的一个要点是,只是remove的时候,传播 invalidate事件。
这样只需要在 update 的时候,进行传播。
好处是,读取的时候,比起中心cache,就少了一布内部网络通信。
坏处是,命中率比memcache低,因为memory是分开的。update多的时候,需要传播 remove/invalidate事件。

2. ORM, Transaction.
Cache通常用于ORM中。人们通常考虑Cache 和 DB 的同步,甚至事务。其实不用考虑到那么细粒度。
比如,Cache 的 Read Committed 没有必要保证,可以允许一定的read committed。
原因很简单。即使是保证了read commited隔离级别的db 操作,都无法解决数据库事务并发冲突问题。只能依靠应用程序层的 悲观锁 和 乐观锁 来解决。
所以,严格保证Cache 的 Read Committed 没有意义。

至于Cache 和 DB Transaction 是否应该成为一个原子操作,统一为一个Transaction。这也只是一个概念上的事情。就看时间点如何纪录。
而且,处于和上面同样的道理,保证这个transaction也没有意义.

3. My Idea.
lightor中,我是这么处理Cache的。

首先,根本不考虑 Read Commited。甚至采用 Copy On Write 这样的方式,鼓励 Read Dirty, 增加命中率。

其次,cache模型非常简单,比map还要简单,根本不考虑时间锁之类的东西。
cluster mode中只需要传播一个 remove 事件。这个可以用底层open source cache 的实现直接支持。

再次,为了增强对 remote cache (中心cache, cluster cache)的支持,cache 实现中,都有大粒度调用方式的支持。这些支持是任何cache都没有考虑的。
比如,get(key),remove(key),
如果这个key,是一个 object[], collection,那么返回值也是一个collection。
这样,如果远程访问这个cache 的时候,一次通信可以完成很多工作。避免多次通信。
putAll( pairs ) 方法也是这样。
这种大粒度调用方式的实现,对于实现关联Cache非常有意义。
   
最后更新时间:2006-08-04
引用
Remote Cache 是对应于Local Cache来说的。
Key or Value 需要序列化,需要内部网络通信。

忘了从哪看的。 如果Key or Value 通过XStream等”协议“转换,也可以不用序列化吧。

引用
Cluster Cache的一个要点是,只是remove的时候,传播 invalidate事件。
这样只需要在 update 的时候,进行传播。

add的时候? 难道各个节点cache内容不一样?或者各个节点本来就不一样?

还有:
http://forum.javaeye.com/viewtopic.php?t=1603
http://forum.javaeye.com/viewtopic.php?t=8850

cache被你们搞得越来越复杂了。能给大伙个完美的通知机制就好了。
   
0 请登录后投票
最后更新时间:2006-08-04
zkj_beyond 写道
引用
Remote Cache 是对应于Local Cache来说的。
Key or Value 需要序列化,需要内部网络通信。

忘了从哪看的。 如果Key or Value 通过XStream等”协议“转换,也可以不用序列化吧。

引用
Cluster Cache的一个要点是,只是remove的时候,传播 invalidate事件。
这样只需要在 update 的时候,进行传播。

add的时候? 难道各个节点cache内容不一样?或者各个节点本来就不一样?

还有:
http://forum.javaeye.com/viewtopic.php?t=1603
http://forum.javaeye.com/viewtopic.php?t=8850

cache被你们搞得越来越复杂了。能给大伙个完美的通知机制就好了。


update, delete, insert 等任何导致缓存数据过期的操作,都调用 cache.remove。然后传播这个事件。
osCache,jboss cache, swarm cache(?) 都有这样的选项 -- 只传播remove/invalidation 事件。

通知机制一般来说用jgroups。也有采用jms, rmi, socket client/server 等中心发散方式的。

:D 这两个link跳到 commit了。

关于select 是否需要事务。经过以前的具体使用经验,我已经回答过了。不过,很不起眼。

http://forum.javaeye.com/viewtopic.php?p=62961#62961
引用

有一种很少发生的情况, select 只读之后,也需要commit。
下面三种情况都同时满足:

1. Local Transaction.
没有用到 JTA, XA, 不是Global Transaction.

2. 用了连接池,而且connection close不自动调用commit。
这个时候,close只是把 connection 放回到 pool中,并没有真正关闭。下次还可能被取出重用。

3. Transaction Isolation Level = Serializable
大多数情况下,Transaction Isolation Level = Read Committed. 这个时候,select 之后,不需要调用commit 释放资源 (当时快照等)。
某些情况下,Transaction Isolation Level = Serializable. 这个时候,select之后,需要调用commit 释放资源 (当时快照等)。
如果这个connection 没有commit 就放回到connection pool,那么,会有两个后果,
(1) 这个connection 将一直持有数据库资源 (当时快照等)。
(2) 这个connection 被取出来重用的时候,也只能读取 数据库当时快照的数据,而读取不到 最新的数据(比如,其它connection commit 的数据)。


Webapp 没有采用Transaction Isolation Level = Serializable 的。
connection pool也几乎都是 commit connection的。

所以,从这个道理来说,select 只读之后,几乎不需要commit。
   
0 请登录后投票
最后更新时间:2006-08-04
我觉得还是robbin推荐的memcached这个东西好,简单实用。再也不用关心cache在cluster环境中(multiJVM)或multiClassloader环境中的复制或invalidate通知机制了。(个人感觉memcached就是一个逻辑上集中的cache server)

另外,springmodule提供的cache module声明式cache管理也是可以借鉴的。但是我看了她的源代码,似乎并不如我所想那么好。以method及parameter作为key我感觉实现太简陋了。有人熟悉springcachemodule吗?不知道是否有我说的这个问题或者有更好的解决方案?
   
0 请登录后投票
最后更新时间:2006-08-04
sorphi 写道
我觉得还是robbin推荐的memcached这个东西好,简单实用。再也不用关心cache在cluster环境中(multiJVM)或multiClassloader环境中的复制或invalidate通知机制了。(个人感觉memcached就是一个逻辑上集中的cache server)

另外,springmodule提供的cache module声明式cache管理也是可以借鉴的。但是我看了她的源代码,似乎并不如我所想那么好。以method及parameter作为key我感觉实现太简陋了。有人熟悉springcachemodule吗?不知道是否有我说的这个问题或者有更好的解决方案?


是的,把问题越简化,就越可靠。

其实memcached简单封装一下,用起来超简单,看看我的封装:

CacheManager是一个接口类,定义Cache操作:
http://cvs.javaeye.com/cgi-bin/viewcvs.cgi/petstore/src/com/javaeye/petstore/manager/CacheManager.java?rev=1.2&cvsroot=openeye&content-type=text/vnd.viewcvs-markup
CacheManagerMemCachedImpl是用memcached封装的实现类:
http://cvs.javaeye.com/cgi-bin/viewcvs.cgi/petstore/src/com/javaeye/petstore/manager/impl/CacheManagerMemCachedImpl.java?rev=1.1&cvsroot=openeye&content-type=text/vnd.viewcvs-markup

这个CacheManager的spring配置:
http://cvs.javaeye.com/cgi-bin/viewcvs.cgi/petstore/etc/spring/manager-beans.xml?rev=1.2&cvsroot=openeye&content-type=text/vnd.viewcvs-markup

然后使用的时候就很简单了,通过spring容器拿到CacheManager,就用好了,完全不用管memcached的配置和API,例如:

http://cvs.javaeye.com/cgi-bin/viewcvs.cgi/petstore/src/com/javaeye/petstore/action/LoginAction.java?rev=1.3&cvsroot=openeye&content-type=text/vnd.viewcvs-markup

http://cvs.javaeye.com/cgi-bin/viewcvs.cgi/petstore/src/com/javaeye/petstore/interceptor/LoginInterceptor.java?rev=1.3&cvsroot=openeye&content-type=text/vnd.viewcvs-markup
中被注释掉那部分。

仔细观察这个Action和Interceptor,其实这就是使用HttpSession,或者使用memcached替换掉HttpSession的示例代码,我当初做压力测试的时候写的。具体的cache key可以用uuid生成,然后写到cookie里面,每次从request里面获得(而不是像那那么偷懒,直接拿sessionID用)

更进一步,可以自己再写一个Hibernate 二级Cache的memcached实现类,那么就可以彻底用memcached替换掉所有JVM内部状态了,从而实现了SNA架构。什么分布式Cahce,什么Cache同步,都让他们见鬼去吧,呵呵。
   
0 请登录后投票
最后更新时间:2006-08-04
thanks Robbin。这么详细的demo。

不过,怎么不是Ruby 版本的? :D

memcached支持多种语言client。

来看看
http://www.whalin.com/memcached/javadocs/com/danga/MemCached/MemCachedClient.html

里面考虑的比较周全。
提供了 getMulti(),  flushAll() 等大粒度调用方法。可以减少网络通信次数。

-----------

我的那个贴子提到了 中心Cache,也是因为关注 Robbin 介绍 memcached的结果。

JPA team的讨论结果是,提供多种方案,让用户自己选择。

memcached 中心cache,Cluster Cache都要提供的。

memcached 中心cache相对比较简单。只要简单包装,不需要配置multicast。

难度就在于cluster cache的良好支持。所以,这方面考虑的比较多。
   
0 请登录后投票
最后更新时间:2006-08-04
引用
update, delete, insert 等任何导致缓存数据过期的操作,都调用 cache.remove。然后传播这个事件。
osCache,jboss cache, swarm cache(?) 都有这样的选项 -- 只传播remove/invalidation 事件。


节点之间操作需要同步吗?
httpSession这种Cluster部署可能不会出现大问题。
但cache就不少说了。

引用
好处是,读取的时候,比起中心cache,就少了一布内部网络通信。

传播remove/invalidation 事件不需要网络通信吗?

引用
jms, rmi, socket client/server


这些应该是缓存框架自带的吧!


反正我们现在local cache。remote cache没经验,学习一下。
   
0 请登录后投票
最后更新时间:2006-08-04
zkj_beyond 写道
引用
update, delete, insert 等任何导致缓存数据过期的操作,都调用 cache.remove。然后传播这个事件。
osCache,jboss cache, swarm cache(?) 都有这样的选项 -- 只传播remove/invalidation 事件。


节点之间操作需要同步吗?
httpSession这种Cluster部署可能不会出现大问题。
但cache就不少说了。


cache remove, clear操作需要同步。 为了清除过期数据。
cache get, put 不需要同步。
put不用同步的原因很简单。大部分cache 文档里面都有说明。
如果cache里面不存在某个key,从数据库取就可以了。

zkj_beyond 写道

引用
好处是,读取的时候,比起中心cache,就少了一布内部网络通信。

传播remove/invalidation 事件不需要网络通信吗?


传播remove/invalidation 事件需要网络通信。
不过这个问题问的驴头不对马嘴。:D

"好处是,读取的时候,比起中心cache,就少了一布内部网络通信。"
是说,get 操作(读取)的时候,不需要多一步内部网络通信。

remove/invalidation 不是读取操作(get操作),当然需要网络传播。

原贴中写的比较清楚了。
引用

Cluster Cache的一个要点是,只是remove的时候,传播 invalidate事件。
这样只需要在 update 的时候,进行传播。
好处是,读取的时候,比起中心cache,就少了一布内部网络通信。
坏处是,命中率比memcache低,因为memory是分开的。update多的时候,需要传播 remove/invalidate事件。


zkj_beyond 写道

引用
jms, rmi, socket client/server

这些应该是缓存框架自带的吧!


是cache框架自带的。
通过cache框架的配置文档和代码,可以看出它们提供了各种cluster同步机制。
   
0 请登录后投票
最后更新时间:2006-08-04
buaawhl 写道
thanks Robbin。这么详细的demo。

不过,怎么不是Ruby 版本的? :D

memcached支持多种语言client。

来看看
http://www.whalin.com/memcached/javadocs/com/danga/MemCached/MemCachedClient.html

里面考虑的比较周全。
提供了 getMulti(),  flushAll() 等大粒度调用方法。可以减少网络通信次数。

-----------

我的那个贴子提到了 中心Cache,也是因为关注 Robbin 介绍 memcached的结果。

JPA team的讨论结果是,提供多种方案,让用户自己选择。

memcached 中心cache,Cluster Cache都要提供的。

memcached 中心cache相对比较简单。只要简单包装,不需要配置multicast。

难度就在于cluster cache的良好支持。所以,这方面考虑的比较多。


几个问题,集中cache通过timeout机制来控制,脏读的几率是不是会比cluster cache的大?

集中cache会导致,所有的put和get都产生一次remoting,这也是不小的开销。

另外,集中cache减少了集群的容错性。

命中率,我认为当到达某个稳定状态后,两者是一样的。只是开始时,集中cache的会高些。
   
0 请登录后投票
最后更新时间:2006-08-04
partech 写道

几个问题,集中cache通过timeout机制来控制,脏读的几率是不是会比cluster cache的大?

集中cache会导致,所有的put和get都产生一次remoting,这也是不小的开销。

另外,集中cache减少了集群的容错性。


集中cache 也可以明确地用代码来 delete, flush 过期数据。
而且只需要传播一个点,不用传播多个点,过期数据的可能性反而比较小。

我猜想,
集中cache 也可以配置到多个 cluster node上。
client 使用的时候,还是可以只访问一个 公用cluster ip 。

所有的put和get都产生一次remoting,这个是主要问题。
不过,据说 网络通信overhead只有 1ms。

关于命中率。我猜想,主要和内存有关。
集中cache起作用的一般只有一个计算机的内存(除了failover)。所有的put都放到同一个内存。命中率就会高。
分布式内存,同样的数据读取,就需要多次put。

到了最后,不需要读取新的数据了,可能会稳定。两者可能差不多。
不过,不需要读取新的数据的情况也不是很多。
   
0 请登录后投票
论坛首页 Java版 企业应用

跳转论坛:
JavaEye推荐