|
该帖已经被评为精华帖
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间: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非常有意义。 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间: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被你们搞得越来越复杂了。能给大伙个完美的通知机制就好了。 |
|
| 返回顶楼 | |
|
最后更新时间: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。 |
|
| 返回顶楼 | |
|
最后更新时间:2006-08-04
我觉得还是robbin推荐的memcached这个东西好,简单实用。再也不用关心cache在cluster环境中(multiJVM)或multiClassloader环境中的复制或invalidate通知机制了。(个人感觉memcached就是一个逻辑上集中的cache server)
另外,springmodule提供的cache module声明式cache管理也是可以借鉴的。但是我看了她的源代码,似乎并不如我所想那么好。以method及parameter作为key我感觉实现太简陋了。有人熟悉springcachemodule吗?不知道是否有我说的这个问题或者有更好的解决方案? |
|
| 返回顶楼 | |
|
最后更新时间: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同步,都让他们见鬼去吧,呵呵。 |
|
| 返回顶楼 | |
|
最后更新时间: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的良好支持。所以,这方面考虑的比较多。 |
|
| 返回顶楼 | |
|
最后更新时间: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没经验,学习一下。 |
|
| 返回顶楼 | |
|
最后更新时间: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同步机制。 |
|
| 返回顶楼 | |
|
最后更新时间: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的会高些。 |
|
| 返回顶楼 | |
|
最后更新时间: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。 到了最后,不需要读取新的数据了,可能会稳定。两者可能差不多。 不过,不需要读取新的数据的情况也不是很多。 |
|
| 返回顶楼 | |










