Oracle Coherence 内存网格

第 9 章 — 内存集群与数据库的互操作

 

作者:金辉 (Oracle)


右箭头 第 1 章 — 漫说内存网格
右箭头 第 2&3 章 — 安装和配置开发环境
右箭头 第 4 章 — 开始第一个 Coherence 程序
右箭头 第 5 章 — 在 Coherence 中使用 POF 对象
右箭头 第 6 章 — 分布式内存集群的数据灌注、查询和统计
右箭头 第 7 章 — 监听器处理内存集群中变化的对象
右箭头 第 8 章 — 使用 ZFS 加密
右箭头 第 9 章 — 内存集群与数据库的互操作
右箭头 第 10 章 — Coherence 内存集群的安全访问
右箭头 第 11 章 — 基于内存集群的事件处理

本章,你将学到使用如下 API

  • Coherence CacheStore
  • ContinuousQueryCache、IdentityExtractor
  • 和 Filter APIs

In this exercise you will create these items:

  • 创建一个 NamedCache 实例用来 put 和 get 条目数据;
  • 缓存配置文件定义缓存名称、类型和名称模式;
  • 一个 Java 类能够连接数据存取数据;
  • 数据库缓存类。

9.1 介绍

 

一个 Coherence 缓存可以作为数据库和客户应用之间的中介,集合大量的数据对象。数据库数据能够被加载到缓存里,为不同应用提供服务。因此,Coherence 缓存能够帮助减轻数据库压力,并提高更快的数据访问能力。

Coherence 缓存通过隔离数据库和数据复制,提供高可用性。当数据库是可用的时候,缓存所做的修改将同步回数据库。即使数据库或应用服务器节点不可用,数据更新仍然通过延迟加载和延迟写入机制提供可靠写入和故障恢复的数据一致性保障。

Coherence 缓存提供的分布式处理能力不仅仅是基于跨应用服务器集群的节点,同时也能基于缓存的数据,这是因为数据的修改可以基于数据对象。

Coherence 同时还提供基于事件的处理,监控缓存中数据对象的状态,并触发调用其他流程比如启动 BPEL 流程。

Coherence 支持不同类型的缓存:

复制缓存:数据在集群内每个节点上复制。因为数据需要在每个节点上复制,这类缓存有更快的读取速度,但是不适合有更新操作的环境中。还有一个缺点是,复制缓存需要大量的内存。

复制(或分区)缓存:数据被分布(负载均衡)到不同节点上,通过数据在集群不同节点内的复制,提供数据访问的容错能力。

Coherence 实现不同的服务类型,有集群服务、分布式缓存服务和复制缓存服务,不同类型的缓存,应用都使用相同的API来存取数据。

缓存的配置描述用来配置缓存,根节点是 cache-config。缓存的名字和名字模式映射到在 caching-scheme-mapping 里定义的缓存类型。缓存类型定义在 caching-schemes 里,初步介绍见下表

缓存类型 描述
distributed scheme 定义一个集群节点中保持数据的分布是缓存
replicated scheme 定义一个在整个集群节点中都复制数据的复制缓存
read-write-backing-map scheme 定义映射 — 缓存持久化,比如持久化到关系数据库的映射
external scheme 定义外置缓存,比如磁盘
class scheme 定义客户化的缓存实现,需要实现 java.util.Map 接口

 

9.2 创建缓存应用

 

本章介绍如何创建和运行从 Coherence 存取数据的应用。

9.2.1 创建一个构造缓存的应用

 

1.    在 Eclipse 里创建工程

 

a)    在 JPA perspective 中创建 JPA 项目,取名为 chapter09_Interaction。配置过程如第 8 章。

b)    JPA Project

项目名称 chapter09_Interaction
JPA Version 2.0
Configutation Chapter08_JPAConfiguration

 

c)    Java:默认

d)    Java Fact:

Platform EclipseLink 2.4.x/2.5.x
JPA 实现 09-figure-01
Connection 09-figure-02

 

e)    Coherence

09-figure-03

f)    点击结束

09-figure-04

2.    创建 Java 类:CoherenceCache。包含 main 方法。

 

a)    Import 主要的 java 包

import com.tangosol.net.CacheFactory; 
import com.tangosol.net.NamedCache;

 

b)    创建 Cache 实例,使用

NamedCache cache = CacheFactory.getCache ( "VirtualCache");

 

c)    一个 NamedCache 是集群中跨节点的 java.util.Map 实例。增加缓存条目使用 put 方法

cache.put (key, "Hello Cache");

 

d)    从缓存总获得数据条目用 get 方法

System.out.println((String)cache.get("hello"));

 

package com.oracle.handson.chapter09;

import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;

public class CoherenceCache {
	NamedCache cache;

	public CoherenceCache() {
	}

	public void putCache() {
		cache = CacheFactory.getCache("VirtualCache");
		String key = "hello";
		cache.put(key, "Hello Cache");
	}

	public void retrieveCache() {
		System.out.println((String) cache.get("hello"));
	}
	public static void main(String[] args) {
		CoherenceCache cache = new CoherenceCache();
		cache.putCache();
		cache.retrieveCache();
	}
}

9.2.2 创建一个缓存配置文件

 

在项目工程里,将 coherence-cache-config.xml 更名为 cache-config.xml。 然后打开这个文件。在这个文件中:

  • 用 caching-scheme-mapping 里的 cache-mapping 单元定义缓存名称和名字模式映射。
  • 映射缓存名称 VirtualCache 的类型到 distributed-eclipselink。
  • 使用 distributed-scheme 定义分布式缓存的 schema,使用 EclipseLinkJPA 服务。

如下内容复制到 cache-config.xml 文件中。

<?xml version="1.0"?>

<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
	
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config coherence-cache-config.xsd">
	
   <caching-scheme-mapping>
		
      <cache-mapping>
			
         <cache-name>VirtualCache</cache-name>
			
         <scheme-name>distributed-eclipselink</scheme-name>
		
      </cache-mapping>
	
   </caching-scheme-mapping>
	
   <caching-schemes>
		
      <!-- Default Distributed caching scheme. -->
		
      <distributed-scheme>
			
         <scheme-name>distributed-eclipselink</scheme-name>
			
         <service-name>EclipseLinkJPA</service-name>
			
         <backing-map-scheme>
				
            <class-scheme>
					
               <scheme-ref>default-backing-map</scheme-ref>
				
            </class-scheme>
			
         </backing-map-scheme>
			
         <autostart>true</autostart>
		
      </distributed-scheme>
		
      <class-scheme>
			
         <scheme-name>default-backing-map</scheme-name>
			
         <class-name>com.tangosol.util.SafeHashMap</class-name>
		
      </class-scheme>
	
   </caching-schemes>

</cache-config>


9.2.3 为应用创建运行配置

 

为这个应用创建一个运行配置文件。

1.    右键 CoherenceCache.java,Run As->Run Configurations。

 

复制 chapter08CacheServer,更名为 chapter09CacheServer。对个别配置项目进行相应修改

name chapter09CacheServer
Project chapter09_Interaction
Main Class com.oracle.handson.chapter09.CoherenceCache
Coherence 配置
Topology:配置文件 cache-config.xml
Topology:Local storage Enabled(cache server)
Cluster Port 3155
Classpath
09-figure-05

 

9.2.4 创建缓存服务器启动配置

 

为 chapter09_Interaction project 工程创建启动配置。

1.    右键 chapter09_Interaction 工程,选择属性 (Properties)。

 

Java Build Path-> Order and Export 选卡
初始状态  09-figure-06
配置完成:
确保都被选中
 09-figure-07

 

2.    复制第 9 章的 chapter09CacheServer 启动配置,更名为 chapter09CacheServer02 并编辑

 

Main选卡  09-figure-08
Coherence  09-figure-09
Classpath  09-figure-10
Common  09-figure-11

 

9.2.5 运行缓存创建应用

 

运行 CoherenceCache

1.    停止所有运行的缓存服务器

 

2.    运行 chapter09CacheServer02

 

3.    右键点击 CoherenceCache.java,点运行->Run Configurations。选择 chapter09CacheServer。

 

09-figure-12 

9.3 创建一个数据库缓存应用

 

In this section, create a cache backed by Oracle Database. This is also referred to as an Oracle Database cache.

在本节中,创建由 Oracle 数据库支持的高速缓存。这也称为一个 Oracle 数据库缓存。

  1. Create an Oracle Database Cache
  2. Create a Class to Define a Custom Cache Store
  3. Modify the Cache Configuration File
  4. Create a Class to Construct the Database Cache
  5. Run the Database Cache Application

9.3.1 创建数据库

 

运行 Oracle Database Express Edition 所带的 SQL*Plus a 创建 Oracle 数据库缓存。

建库建表  09-figure-13

 

9.3.2 新建类定义客户缓存库

 

写个 Java 类,联接数据库查询数据

1.    新建 Java类:DBCacheStore。

09-figure-14

具体代码见 chapter09_ Interaction\src\com.oracle.handson.chapter09. DBCacheStore

09-figure-15

9.3.3 修改缓存配置文件

 

修改早先的 cache-config.xml。建立缓存与数据库的连接,用客户化的 Java 类实现 com.tangosol.net.cache.CacheLoader 或 com.tangosol.net.cache.CacheStore 接口,用来定义 cachestore-scheme 单元。

原先的 cache-config.xml 复制重命名为 cache-config93.xml。

09-figure-16

在这个配置文件中,需要:

定义缓存名称模式 DBBacked*, which is mapped to a distributed caching scheme distributed-db-backed.
指定 CacheStore 在使用分布式方式时,定义,实现了 CacheStore接口。
Specified the CacheStore scheme in the distributed scheme using the class coherence.DBCacheStore, which implements the CacheStore interface.
CacheStore 是一个指定应用的适配器,用来连接一个缓存到基本数据源。CacheStore 的实现通过使用一个数据访问机制来获取数据源(例如,Hibernate、Toplink Essentials、JPA、application-specific JDBC calls、another application、mainframe、another cache, 等)。CacheStore 知道如何创建一个 java 对象来实现从数据源检索数据,映射和写一个对象到数据源,从数据源擦出一个对象。数据源连接策略和数据源-应用-对象的映射信息是针对数据源架构,应用程序类布局,和操作环境。因此,映射信息必须由应用开发者来提供,以 CacheStore 实现的形式。
指定 CacheStore 的 INIT 参数 Specified for the DBCacheStore class an init parameter for the database table that is at the back end of the cache. The table name is specified in the init-param element. The DBCacheStore class performs database operations such as reading and writing cache entries.
  Specified a read-write-backing-map-scheme as the backing map. This scheme defines a backing map, which provides a size-limited cache of a persistent store. Here, by setting the write-delay-seconds parameter to 0, you specify the write-through mechanism. backing map是服务端数据结构,持有真实数据。

 

为了完成数据源的缓存,Coherence 支持 Read-Through、Write-Through、Refresh-Ahead and Write-Behind 缓存。下表是 Coherence 支持的读写缓存。

缓存策略 说明
read-through A cache entry is read into a cache from the database when required and made available to an application.
当应用程序想缓存请求一条 entry,例如 key x,并且 x 不在缓存中,Coherence 会自动委托给 CacheStore,请求它来从基础数据源中加载 x。如果 x 在数据源中存在,CacheStore 加载它,返回给Coherence,然后 Coherence 将它放在缓存中为将来使用,最后返回 x 给请求它的应用程序的代码。
write-through Updates to cache entries are synchronized with the database without a delay.
当应用程序更新一条在缓存中的数据(是调用 put(...)来改变缓存 entry),直到 Coherence 运行了 CacheStore 并成功存储数据到基础数据源才算操作完成。这个完全不会提升写的性能,因为你仍然使用有延时的方式写数据源。提升写的性能建议使用 Write-Behind Cache 功能。
refresh-ahead Cache entries are refreshed periodically.
允许开发者配置缓存,能够在它失效之前自动的、异步的从 cache loader 重载最近访问过的缓存条目。结果是一个平凡被访问的条目进入缓存后,应用程序没有感觉到对于一个千载的减慢 cache store 的读取的影响,当这个条目由于过期而重新加载时。异步的属性只会在足够接近它的国企时间时候被访问时触发--如果对象在它的过期时间之后,Coherence 会从 cache store 执行同步的读取来刷新他的值。
write-behind Updates to cache entries are asynchronously written to a database after a delay specified in the write-delay-seconds element in the cache configuration file.
修改缓存条目是在配置的延迟值后异步的写入数据源,可能是 10 秒,20 分钟,一天,一个星期或者是更久。注意,这个只用于对缓存的插入和更新。缓存条目从数据源移除是同步的。Write-Behind 缓存,Coherence 维护者一个需要在数据源执行更新的 write-behind 数据队列。当应用程序更新缓存中的 X,X 被添加在 write-behind 队列(如果不存在;否则就替换它),然后在指定的 write-behind 延迟以后,COherence 调用了 CacheStore,用最新的 X 的状态来更新基础数据源,注意 write-behind 延迟是相对于第一个一系列的修改--换句话说,在数据源的数据从未落后于缓存超过 wirte-behind 延迟的这个时间。
应用程序提升了性能,因为用户不用等待数据写入基础数据源。(数据延迟写入,并且通过其他线程)
应用程序经历了彻底降低数据库的负载:由于减少了大量的读和写操作,数据库的负载也是同样。和其他缓存方法一样,通过缓存,读取变少了。写,这个通常是最昂贵的操作,也减少了,因为针对同一个对象的多个变化使用 write-behind 是合并并且只写一次到数据源 ("write-coalescing")。此外,对多个缓存条目的写可能被合并成一个数据库事务 ("write-combining")。如果用 CacheStore.storeAll() 方法。
应用程序多少有点隔绝数据库失效的情况:Write-Behind 特性能够被这样配置,失败的写入导致对象重新被请求写。如果应用程序正在使用的数据时在 Coherence 的缓存里,那么应用程序能够继续操作,而不用数据库是 up 状态的。使用 Coherence Partitioned Cache,这很容易做到,只要将所有的缓存分区到所有的 participating cluster 节点(开启了 local-storage),允许庞大的缓存。
线性可扩展:要应用程序处理更多的并发用户,你只需要增加 cluster 的节点即可;影响数据库的负载可以用增加 write-behind 间隔来调节。

 

9.3.4 创建类来构造数据库缓存

 

创建类,用来添加条目,查询,和返回条目。见下方法内的具体实现:

createCache()

addEntry()

retrieveEntry()

eraseEntry()

queryCache().

09-figure-21

具体代码见 chapter09_ Interaction\src\com.oracle.handson.chapter09. DatabaseCache

09-figure-17

  • A NamedCache object is created using the getCache method of the CacheFactory class in the createCache method.

    NamedCache cache = CacheFactory.getCache("DBBackedCache");
  • The DBBackedCache matches the cache pattern DBBacked* and is, therefore, mapped to a distributed caching scheme distributed-db-backed in the cache-config.xml file. Add a cache entry using the put() method of the NamedCache object.

    cache.put(new String("catalog3"), new String("Tuning Grid Management"));
  • Because the write-through mechanism is used, the new cache entry gets synchronized with the database; a new row is added to the CATALOG table. Comment out all the methods except the createCache and addEntry methods.
  • When the put method is invoked, the store method, which maps the new cache entry to the database table CATALOG using JDBC, gets invoked in the DBCacheStore class. The output from the Coherence application is displayed in the Log window and a new cache entry is added. The output shows that the operational configuration deployment descriptor is loaded, the cache configuration is loaded, a new cluster is created, and the DistributedCache service has joined the cluster.
  • The new cache entry can be removed with the remove method of the NamedCache object.

    cache.remove(new String("catalog3"));
  • Bulk uploading of cache entries is performed using the putAll method.
  • A cache entry is retrieved using the get method of the NamedCache object. For example, retrieving the cache entry for ID catalog1:

    System.out.println((String) cache.get("catalog1"));
  • When the get() method is invoked, the load method, which retrieves database table data using JDBC, gets invoked in the DBCacheStore class.
  • Bulk retrieval is performed using the getAll method of the NamedCache object.
  • Coherence supports searching for cache entries based on a search criteria using filters. Coherence filters are available in the com.tangosol.util.filter package. In Oracle Coherence Enterprise Edition and Grid Edition, indexes can be added to the Coherence cache to improve performance. You query the database cache using a LikeFilter filter, which matches cache entries with a specified pattern. To query a database cache, the cache entries must be created before querying, and the cache entries must be retrieved into the cache using the get() or getAll() method before a query using a filter can be performed. Therefore, you can retrieve database data and create a collection of cache entries using the getAll() method.

    HashSet hashSet=new HashSet(); 
    hashSet.add(new String("catalog1")); 
    hashSet.add(new String("catalog2")); 
    hashSet.add(new String("catalog3")); 
    Map map=cache.getAll(hashSet);
    
  • Create a LikeFilter filter to search for cache entries starting with Tuning.

    Filter filter = new LikeFilter(IdentityExtractor.INSTANCE, "Tuning%", '\\', true);
  • Query the database cache using the entrySet() method with the LikeFilter filter.

    Set results = cache.entrySet(filter);
  • Iterate over the results of the query. Display the key and value of the cache entries that are retrieved.

    for (Iterator i = results.iterator(); i.hasNext();) 
       {
       Map.Entry e = (Map.Entry) i.next();
       System.out.println("Catalog ID: "+e.getKey() + ", Title: "+e.getValue());
       }
    
  • Coherence supports continuous query using the com.tangosol.net.cache.ContinuousQueryCache class. A continuous query is a query that is kept up-to-date using a continuous query cache. In a ContinuousQueryCache, the results of a query are updated using event listeners on events that could change the results of the query. Create a ContinuousQueryCache object using the NamedCache object and the LikeFilter object.

    ContinuousQueryCache queryCache = new ContinuousQueryCache(cache, filter);
  • Create a result set by using the entrySet() method.

    Set results = queryCache.entrySet(filter);

9.3.5 运行数据库缓存应用

 

按如下步骤运行数据库缓存应用:

1.    停止所有运行的缓存服务器。

2.    新建并运行缓存服务器运行配置。

原配置 新配置
chapter09CacheServer 复制并更名为 chapter09CacheServer03
cache-config.xml 变更为 cache-config93.xml

 

然后点击运行。

3.    为数据库缓存应用创建配置,并运行。

配置项目 配置信息
运行配置名称 chapter09CacheClientDatabaseCache
Main Class com.oracle.handson.chapter09.DatabaseCache
缓存配置文件 cache-config93.xml
Local storage Disabled (cache client)
Cluster port 3155
Classpath  09-figure-18

 

然后点击运行

4.    运行结果如下图:

应用缓存程序输出

09-figure-19

运行数据库命令

09-figure-20

关于作者

 niehao

金辉,在 Oracle 负责云和中间件产品的资深售前顾问和团队经理,有十多年的中间件和项目管理经验,专注在企业云构建,企业集成解决方案领域,熟悉业内主要的 SOA 集成产品。参加过北京马拉松和 TNF50 越野比赛。你可以通过邮件 arthur.jin@oracle.com 与他联系。