JBossCache-TreeCache体验
TreeCache是一种结构化的、基于复制的事务缓存。TreeCache是JBoss应用服务器中集群服务—包括JNDI集群、HTTP和EJB的Sesssion集群、JMS集群—的基础框架。其可以单独使用,可以集成到JBossAS应用,也可以集成到其他的应用服务器上。TreeCache是一种树状结构,每个节点拥有一个名字和多个或者没有子节点,除跟节点没有子节点其他节点有且只有一个父母节点,可以通过路径名来访问子节点(FQN:Full Qualified Name),在一个TreeCache中可以存在多棵树,,即可以有多个根节点。当应用于分布式环境时,由于TreeCache是基于复制的,每个子节点的值必须是可序列化的。
在下面中,将通过例子来了解TreeCache的功能及其配置,使用JBossCache1.4和JDK5.0。首先是一个最基本使用TreeCache的程序例子并配置一个TreeCache的配置骨架(各种常用的配置可参见jboss-cache-dist-1.4.0.CR1版本的etc目录,如下各种配置参考也可见该目录下的范例配置,以下不再强调),见下:
1
TreeCache tree
=
new
TreeCache();
2 tree.setClusterProperties( " treecache.xml " [img] / images / wink.gif[ / img];
3 tree.createService();
4 tree.startService();
5 tree.put( " /a/b/c " , " name " , " Ben " [img] / images / wink.gif[ / img];
6 tree.put( " /a/b/c/d " , " uid " , new Integer( 322649 ));
7 Integer tmp = (Integer) tree.get( " /a/b/c/d " , " uid " [img] / images / wink.gif[ / img];
8 tree.remove( " /a/b " [img] / images / wink.gif[ / img];
9 tree.stopService();
10 tree.destroyService();
11
2 tree.setClusterProperties( " treecache.xml " [img] / images / wink.gif[ / img];
3 tree.createService();
4 tree.startService();
5 tree.put( " /a/b/c " , " name " , " Ben " [img] / images / wink.gif[ / img];
6 tree.put( " /a/b/c/d " , " uid " , new Integer( 322649 ));
7 Integer tmp = (Integer) tree.get( " /a/b/c/d " , " uid " [img] / images / wink.gif[ / img];
8 tree.remove( " /a/b " [img] / images / wink.gif[ / img];
9 tree.stopService();
10 tree.destroyService();
11
treecache.xml:
1
<
server
>
2 < mbean code ="org.jboss.cache.TreeCache"
3 name ="jboss.cache:service=TreeCache" >
4 < depends > jboss:service=Naming </ depends >
5 < depends > jboss:service=TransactionManager </ depends >
6 < attribute name ="ClusterName" > TreeCache-Cluster </ attribute >
7 < attribute name ="ClusterConfig" >
8 < config >
9 < UDP mcast_addr ="228.1.2.3" mcast_port ="48866"
10 ip_ttl ="64" ip_mcast ="true"
11 mcast_send_buf_size ="150000" mcast_recv_buf_size ="80000"
12 ucast_send_buf_size ="150000" ucast_recv_buf_size ="80000"
13 loopback ="false" />
14 < PING timeout ="2000" num_initial_members ="3"
15 up_thread ="false" down_thread ="false" />
16 < MERGE2 min_interval ="10000" max_interval ="20000" />
17 < FD_SOCK />
18 < VERIFY_SUSPECT timeout ="1500"
19 up_thread ="false" down_thread ="false" />
20 < pbcast .NAKACK gc_lag ="50" retransmit_timeout ="600,1200,2400,4800"
21 max_xmit_size ="8192" up_thread ="false" down_thread ="false" />
22 < UNICAST timeout ="600,1200,2400" window_size ="100" min_threshold ="10"
23 down_thread ="false" />
24 < pbcast .STABLE desired_avg_gossip ="20000"
25 up_thread ="false" down_thread ="false" />
26 < FRAG frag_size ="8192"
27 down_thread ="false" up_thread ="false" />
28 < pbcast .GMS join_timeout ="5000" join_retry_timeout ="2000"
29 shun ="true" print_local_addr ="true" />
30 < pbcast .STATE_TRANSFER up_thread ="true" down_thread ="true" />
31 </ config >
32 </ attribute >
33 </ mbean >
34 </ server >
2 < mbean code ="org.jboss.cache.TreeCache"
3 name ="jboss.cache:service=TreeCache" >
4 < depends > jboss:service=Naming </ depends >
5 < depends > jboss:service=TransactionManager </ depends >
6 < attribute name ="ClusterName" > TreeCache-Cluster </ attribute >
7 < attribute name ="ClusterConfig" >
8 < config >
9 < UDP mcast_addr ="228.1.2.3" mcast_port ="48866"
10 ip_ttl ="64" ip_mcast ="true"
11 mcast_send_buf_size ="150000" mcast_recv_buf_size ="80000"
12 ucast_send_buf_size ="150000" ucast_recv_buf_size ="80000"
13 loopback ="false" />
14 < PING timeout ="2000" num_initial_members ="3"
15 up_thread ="false" down_thread ="false" />
16 < MERGE2 min_interval ="10000" max_interval ="20000" />
17 < FD_SOCK />
18 < VERIFY_SUSPECT timeout ="1500"
19 up_thread ="false" down_thread ="false" />
20 < pbcast .NAKACK gc_lag ="50" retransmit_timeout ="600,1200,2400,4800"
21 max_xmit_size ="8192" up_thread ="false" down_thread ="false" />
22 < UNICAST timeout ="600,1200,2400" window_size ="100" min_threshold ="10"
23 down_thread ="false" />
24 < pbcast .STABLE desired_avg_gossip ="20000"
25 up_thread ="false" down_thread ="false" />
26 < FRAG frag_size ="8192"
27 down_thread ="false" up_thread ="false" />
28 < pbcast .GMS join_timeout ="5000" join_retry_timeout ="2000"
29 shun ="true" print_local_addr ="true" />
30 < pbcast .STATE_TRANSFER up_thread ="true" down_thread ="true" />
31 </ config >
32 </ attribute >
33 </ mbean >
34 </ server >
其中ClusterConfig配置在前面JavaGroups的介绍详细介绍,其它配置比较简单,需要进一步了解请参见TreeCache文档。
一、Cache分类
TreeCache按功能分为三类:本地(Local)Cache、复制(Replication)Cache和失效(Invalidation)Cache。本地Cache只应用于本地环境,后两个Cache可应用于分布式环境,其中,在分布式环境中,复制Cache当一个Cache实例的一个节点值发生变化时会将变化复制到其它实例中,而失效Cache是当一个Cache实例的一个节点值发生变化时会将其它实例的相应节点的值设为空,让其重新去获得该值,可通过这种方式缓存大对象以减少在实例中复制对象的代价。分布式Cache(复制和失效Cache)又分为两种,同步(REPL_ASYNC)和异步(REPL_SYNC),同步Cache是在一个Cache实例做修改时,等待变化应用到其它实例后才返回,而异步Cache是在一个Cache实例做修改时,即刻返回。其配置见下:
1
<!--
2 Valid modes are LOCAL
3 REPL_ASYNC
4 REPL_SYNC
5 INVALIDATION_ASYNC
6 INVALIDATION_SYNC
7 -->
8 < attribute name ="CacheMode" > REPL_SYNC </ attribute >
9
2 Valid modes are LOCAL
3 REPL_ASYNC
4 REPL_SYNC
5 INVALIDATION_ASYNC
6 INVALIDATION_SYNC
7 -->
8 < attribute name ="CacheMode" > REPL_SYNC </ attribute >
9
二、事务和并行(Transaction And Concurrent)
TreeCache是一种事务Cache,与JDBC一样,其包括两方面内容:锁和隔离级别。锁分为悲观锁和乐观锁,当使用悲观锁时,分为五个隔离级别,分别是SERIALIZABLE、REPEATABLE_READ (default)、READ_COMMITTED、READ_UNCOMMITTED和NONE,隔离级别逐步减弱。乐观锁也叫版本锁,其对数据进行操作时,将其复制到临时区,操作之后将版本与原有数据比较,如果一致则将递增版本并写回,如果不一致则回滚,由于乐观锁仅在复制出数据和提交数据时对数据加锁,所以并行度更高,但如果写操作比较频繁地话则容易出现冲突导致回滚。TreeCache默认使用悲观锁。使用TreeCache时,需要使用容器提供的事务管理器,一般使JBossTransactionManagerLookup和GenericTransactionManagerLookup,前者应用于JBOSS服务器,后者应用于其他服务器,也可使用DummyTransactionManagerLookup用于测试。如上介绍的配置如下:
1
<
attribute
name
="NodeLockingScheme"
>
OPTIMISTIC
</
attribute
>
2 < attribute name ="IsolationLevel" > REPEATABLE_READ </ attribute >
3 < attribute name ="TransactionManagerLookupClass" > org.jboss.cache.DummyTransactionManagerLookup </ attribute >
4
5
2 < attribute name ="IsolationLevel" > REPEATABLE_READ </ attribute >
3 < attribute name ="TransactionManagerLookupClass" > org.jboss.cache.DummyTransactionManagerLookup </ attribute >
4
5
三、逐出策略(Eviction Policy)
由于内存数量的局限,不可能将所有的Cache数据存放在内存中,但使用内存达到一定极限时,会将部分数据清除出内存,保存到其它持久媒质中,定义的什么时候清除、如何清除的策略就是逐出策略。自定义一个逐出策略需要实现org.jboss.cache.eviction.EvictionPolicy、org.jboss.cache.eviction.EvictionAlgorithm、
org.jboss.cache.eviction.EvictionQueue 和org.jboss.cache.eviction.EvictionConfiguration四个接口,系统提供了LRU(Least recently used,最近最少使用)、LFU(Least Frequently Used最不经常使用)、FIFO(First In First Out先进先出)、MRU(Most Recently Used最近最经常使用)四种实现,详细参见org.jboss.cache.eviction包的源代码。配置如下:
1
<
attribute
name
="EvictionPolicyConfig"
>
2 < config >
3 < attribute name ="wakeUpIntervalSeconds" > 5 </ attribute >
4 < region name ="/_default_" >
5 < attribute name ="maxNodes" > 5000 </ attribute >
6 < attribute name ="timeToLiveSeconds" > 1000 </ attribute >
7 </ region >
8 < region name ="/org/jboss/data"
9 policyClass ="org.jboss.cache.eviction.FIFOPolicy" >
10 < attribute name ="maxNodes" > 5000 </ attribute >
11 </ region >
12 < region name ="/test/" policyClass ="org.jboss.cache.eviction.MRUPolicy" >
13 < attribute name ="maxNodes" > 10000 </ attribute >
14 </ region >
15 < region name ="/maxAgeTest/" >
16 < attribute name ="maxNodes" > 10000 </ attribute >
17 < attribute name ="timeToLiveSeconds" > 8 </ attribute >
18 < attribute name ="maxAgeSeconds" > 10 </ attribute >
19 </ region >
20 </ config >
21 </ attribute >
22
四、Cache加载
2 < config >
3 < attribute name ="wakeUpIntervalSeconds" > 5 </ attribute >
4 < region name ="/_default_" >
5 < attribute name ="maxNodes" > 5000 </ attribute >
6 < attribute name ="timeToLiveSeconds" > 1000 </ attribute >
7 </ region >
8 < region name ="/org/jboss/data"
9 policyClass ="org.jboss.cache.eviction.FIFOPolicy" >
10 < attribute name ="maxNodes" > 5000 </ attribute >
11 </ region >
12 < region name ="/test/" policyClass ="org.jboss.cache.eviction.MRUPolicy" >
13 < attribute name ="maxNodes" > 10000 </ attribute >
14 </ region >
15 < region name ="/maxAgeTest/" >
16 < attribute name ="maxNodes" > 10000 </ attribute >
17 < attribute name ="timeToLiveSeconds" > 8 </ attribute >
18 < attribute name ="maxAgeSeconds" > 10 </ attribute >
19 </ region >
20 </ config >
21 </ attribute >
22
由于逐出策略的存在,那么当我们重新需要获得一个原来在缓存中但确由内存原因被逐出的数据时,就需要定义一种加载策略,使地可以重新找回数据,同时,Cache加载也肩负在将数据逐出时将数据保存到持久媒质的责任。
根据将数据保存媒质的不同,Cache加载包括FileCacheLoader、JDBCCacheLoader等等,可以同时使用多种加载器来灵活定制加载策略。例见下:
1
<
attribute
name
="CacheLoaderConfiguration"
>
2 < config >
3 < passivation > false </ passivation >
4 < preload > / </ preload >
5 < shared > true </ shared >
6 < cacheloader >
7 < class > org.jboss.cache.loader.ClusteredCacheLoader </ class >
8 < properties >
9 timeout=1000
10 </ properties >
11 < async > true </ async >
12 < fetchPersistentState > false </ fetchPersistentState >
13 ignoreModifications>false </ ignoreModifications >
14 < purgeOnStartup > false </ purgeOnStartup >
15 </ cacheloader >
16 < cacheloader >
17 < class > org.jboss.cache.loader.JDBCCacheLoader </ class >
18 < properties >
19 cache.jdbc.table.name=jbosscache
20 cache.jdbc.table.create=true
21 cache.jdbc.table.drop=true
22 cache.jdbc.table.primarykey=jbosscache_pk
23 cache.jdbc.fqn.column=fqn
24 cache.jdbc.fqn.type=varchar(255)
25 cache.jdbc.node.column=node
26 cache.jdbc.node.type=longblob
27 cache.jdbc.parent.column=parent
28 cache.jdbc.driver=com.mysql.jdbc.Driver
29 cache.jdbc.url=jdbc:mysql://localhost:3306/jbossdb
30 cache.jdbc.user=root
31 cache.jdbc.password=
32 </ properties >
33 < async > true </ async >
34 < fetchPersistentState > false </ fetchPersistentState >
35 < purgeOnStartup > false </ purgeOnStartup >
36 </ cacheloader >
37 </ config >
38 </ attribute >
39
2 < config >
3 < passivation > false </ passivation >
4 < preload > / </ preload >
5 < shared > true </ shared >
6 < cacheloader >
7 < class > org.jboss.cache.loader.ClusteredCacheLoader </ class >
8 < properties >
9 timeout=1000
10 </ properties >
11 < async > true </ async >
12 < fetchPersistentState > false </ fetchPersistentState >
13 ignoreModifications>false </ ignoreModifications >
14 < purgeOnStartup > false </ purgeOnStartup >
15 </ cacheloader >
16 < cacheloader >
17 < class > org.jboss.cache.loader.JDBCCacheLoader </ class >
18 < properties >
19 cache.jdbc.table.name=jbosscache
20 cache.jdbc.table.create=true
21 cache.jdbc.table.drop=true
22 cache.jdbc.table.primarykey=jbosscache_pk
23 cache.jdbc.fqn.column=fqn
24 cache.jdbc.fqn.type=varchar(255)
25 cache.jdbc.node.column=node
26 cache.jdbc.node.type=longblob
27 cache.jdbc.parent.column=parent
28 cache.jdbc.driver=com.mysql.jdbc.Driver
29 cache.jdbc.url=jdbc:mysql://localhost:3306/jbossdb
30 cache.jdbc.user=root
31 cache.jdbc.password=
32 </ properties >
33 < async > true </ async >
34 < fetchPersistentState > false </ fetchPersistentState >
35 < purgeOnStartup > false </ purgeOnStartup >
36 </ cacheloader >
37 </ config >
38 </ attribute >
39
我们将通过定制如上的配置信息以更有效地使用JBossCache。详细情况可参考JBoss TreeCache参考文档和范例。