Saturday, February 21, 2009

Using Cache Coordination with Toplink

Most of my consulting engagements revolve around two products - Oracle Coherence and Oracle Toplink. While both have Caching component and caching in a distributed environment they are complementary and are built for two entire different purposes. Coherence is built for massive scalability for humongous amount of in memory data while Toplink is for persistence and can pretty much map any domain model with any data model. So the moment you find yourself in a situation where multiple applications need to share the same set of objects or need to be notified of changes in one application to another, a quick call with Oracle Professional services might help. One feature of Toplink that gets a little not so talked about is its ability to coordinate caches across multiple Toplink sessions. If your application is Toplink API driven and requires up to 500/600MB of in memory data some huge performance gains can be achieved using its Cache Coordination. During a recent project I got myself into some challenges while migrating a Toplink9g project and I hope this blog helps for future references.

  1. Cache Synchronization is now called Cache Coordination.
  2. Cache Coordination uses RCM and the old synchronization mechanism has been deprecated.
  3. Do not rely completely on Toplink10g workbench for creating sessions.xml
  4. Migrate to Toplink11g and it's workbench - It will make life much easier.
  5. If migrating 9g to 10g, 10g will work with the 9g's sessions.xml. 10g cache coordination configuration could be a challenge.
  6. Cache coordination is meant for mostly read-only and a low writes.
  7. If requirement is heavy object mutation across multiple instances or heterogeneous applications, consider Coherence.
Following explains how to test Cache coordination on a single machine (Done with 11g):
  • A sample setting for Cache Coordination using RMI
    • Type: RMI
    • Channel: ToplinkCommandChannel
    • Multicast Group Address: 237.14.12.12
    • Multicast Port: 25000
    • Packet Time to Live: 2
    • Announcement Delay: 1000
    • Select Remove Connection on Error
    • Select Synchronous
    • URL for Registry Naming Service: rmi://$HOST:1099
  • Starting rmiregistry
    • rmiregistry.exe -J-Djava.class.path="classes;toplink.jar" -J-Djava.rmi.server.logCalls=true -J-Dsun.rmi.server.logLevel=VERBOSE -J-Dsun.rmi.client.logCalls
  • Following is a simple sample sessions.xml
      <?xml version="1.0" encoding="UTF-8"?>
      <toplink-sessions version="11g (11.1.1.0.0)"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <session xsi:type="server-session">
      <name>Session</name>
      <remote-command>
      <commands>
      <cache-sync>true</cache-sync>
      </commands>
      <transport xsi:type="rmi-transport">
      <send-mode>Synchronous</send-mode>
      <discovery>
      <multicast-group-address>
      237.12.14.12
      </multicast-group-address>
      <multicast-port>25000</multicast-port>
      <announcement-delay>2000</announcement-delay>
      </discovery>
      <rmi-registry-naming-service>
      <url>rmi://$HOST:1099</url>
      </rmi-registry-naming-service>
      </transport>
      </remote-command>
      <event-listener-classes/>
      <profiler>toplink</profiler>
      <logging xsi:type="toplink-log">
      <log-level>all</log-level>
      </logging>
      <primary-project xsi:type="xml">ToplinkRI.xml</primary-project>
      <login xsi:type="database-login">
      <platform-class>
      oracle.toplink.platform.database.oracle.Oracle10Platform
      </platform-class>
      <user-name>username</user-name>
      <password>56F55BD62D7347611874F25952AA55F6</password>
      <sequencing>
      <default-sequence xsi:type="native-sequence">
      <name>Native</name>
      <preallocation-size>10</preallocation-size>
      </default-sequence>
      </sequencing>
      <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
      <connection-url>
      jdbc:oracle:thin:@localhost:1521:XE
      </connection-url>
      <cache-all-statements>true</cache-all-statements>
      <struct-converters/>
      </login>
      <connection-pools>
      <read-connection-pool>
      <name>ReadConnectionPool</name>
      </read-connection-pool>
      <write-connection-pool>
      <name>default</name>
      </write-connection-pool>
      </connection-pools>
      <connection-policy/>
      </session>
      </toplink-sessions>
And thats all you need to run multiple instances of an application on a single box with straight forward RMI driven cache coordination. Change made in one is visible in another JVM and access to that Object will be from a cache instead from an expensive database.

11 comments:

Robert Varga said...

Hi Ashish,

so in Coherence terms, what you described is analogous to a cache server with read/write-through fronting the database, and multiple Toplink clients can connect to this server with RMI instead of storage-disabled nodes connecting over TCMP?

Or is it more like a single-image cache with TopLink JVMs themselves acting analogously to storabe-enabed cache nodes or replicated caches but still fronting the database with write-through?

Best regards,

Robert

ashish said...

No not exactly. Toplink has a feature where multiple instances of an application can share the changes happening in one cache into another one. So in coherence terms it works pretty similar to a replicated cache.

Robert Varga said...

Ok, so similar to the second thing I wrote.

ashish said...

Keep an eye on Toplink11g (it's next version) and its integration with Coherence. Some cool stuff coming out.

hi harsh said...

Hi Ashish,

In case we use JNDI for Naming service, it needs URL of each managed server in its respective deployment's session.xml. Is there any way we can fetch that URL or make a generic entry to session.xml ?

Thanks
Harsh

hi harsh said...

Hi Ashish,

In case we use JNDI for Naming service, it needs URL of each managed server in its respective deployment's session.xml. Is there any way we can fetch that URL or make a generic entry to session.xml ?

Thanks
Harsh

ashish said...

have you tried ANT's tokens that can be replaced at the deployment time. So you don't have to maintain multiple sessions.xml.

hi harsh said...

This idea will need fresh deployment/changes every time server port is changed. Hence, it won't help me.

Is there some way, which can pick up port information by itself ?

ashish said...

Then other option could be to use RemoteCommandManager and build the cache coordination programmatically. The URL can be passed as a runtime value (-D)

Amita said...

Hi Ashish, I cannot use a IP multicast, as it is not allowed in our organization. We deploy our apps on multiple server which have multiple JVMs. We are Toplink 10.1.3. Can you give me some advice on cache synchronixation.
Thanks

ashish said...

Amita,
Multicast is only used if the protocol is RMI. If multicast is disabled you can still use JMS or CORBA.