Add caching.adoc documenting the auto-configuration of Apache Geode or Pivotal GemFire as a caching provider in Spring's Cache Abstraction.
This commit is contained in:
210
spring-geode-docs/src/docs/asciidoc/caching.adoc
Normal file
210
spring-geode-docs/src/docs/asciidoc/caching.adoc
Normal file
@@ -0,0 +1,210 @@
|
||||
[[geode-caching-provider]]
|
||||
== Caching with Apache Geode or Pivotal GemFire
|
||||
|
||||
One of the easiest ways to get started using Apache Geode or Pivotal GemFire in your Spring Boot applications
|
||||
is to use either Apache Geode or Pivotal GemFire as a {spring-framework-docs}/integration.html#cache-store-configuration[_caching provider_]
|
||||
({spring-framework-docs}/integration.html#cache-store-configuration-gemfire[see also]) in {spring-framework-docs}/integration.html#cache[Spring's Cache Abstraction].
|
||||
|
||||
TIP: See the _Spring Data for Apache Geode Reference Guide_ for more details on the
|
||||
{spring-data-geode-docs-html}/#apis:spring-cache-abstraction[support] and {spring-data-geode-docs-html}/#bootstrap-annotation-config-caching[configuration]
|
||||
of Apache Geode or Pivotal GemFire as a _caching provider_ in _Spring's Cache Abstraction_.
|
||||
|
||||
Indeed, caching can be an effective software design pattern to avoid the cost of invoking a potentially,
|
||||
expensive operation when, given the same input, the operation yields the same output every time. Make sure you
|
||||
fully understanding the {spring-framework-docs}/integration.html#cache-strategies[concepts] behind _Spring's Cache Abstraction_
|
||||
before you continue.
|
||||
|
||||
You can also refer to the relevant section on {spring-boot-docs-html}/#boot-features-caching[Caching]
|
||||
in Spring Boot's Reference Guide. Spring Boot even provides _auto-configuration_ support for a few,
|
||||
simple {spring-boot-docs-html}/#_supported_cache_providers[_caching providers_] out-of-the-box.
|
||||
|
||||
However, if you need the proven power of an enterprise-class caching solution, with strong consistency,
|
||||
high availability and multi-site (WAN) capabilities, then you should consider http://geode.apache.org/[Apache Geode]
|
||||
or https://pivotal.io/pivotal-gemfire[Pivotal GemFire]. Additionally, https://pivotal.io/[Pivotal Software, Inc.]
|
||||
offers Pivotal GemFire as a service, known as https://pivotal.io/platform/services-marketplace/data-management/pivotal-cloud-cache[Pivotal Cloud Cache (PCC)],
|
||||
when deploying and running your Spring Boot applications in https://pivotal.io/platform[Pivotal Cloud Foundry (PCF)].
|
||||
|
||||
Spring's {spring-framework-docs}/integration.html#cache-annotations[declarative, annotation-based caching] makes it easy
|
||||
to get started with caching, which is as simple as annotating your application service components with
|
||||
the appropriate annotation.
|
||||
|
||||
TIP: Spring's declarative, annotation-based caching also {spring-framework-docs}/integration.html#cache-jsr-107[supports]
|
||||
JCache (JSR-107) annotations.
|
||||
|
||||
For example, suppose you want to cache the result for determining a person's eligibility when applying for a loan:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Service
|
||||
class LoanApplicationService {
|
||||
|
||||
@Cacheable("EligibilityDecisions", ...)
|
||||
EligibilityDecision processEligility(Person person, TimeSpan timeSpan) {
|
||||
...
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
When the `LoanApplicationService.processEligibility(..)` method is called, Spring's caching infrastructure first consults
|
||||
the "`EligibilityDecisions`" cache to determine if a decision has already been computed for the given `Person`
|
||||
within the given span of time. If eligibility has already been determined, the the existing decision is returned
|
||||
from the cache, otherwise the `processEligibility(..)` method is invoked and the result is cached on return.
|
||||
|
||||
Spring Boot for Apache Geode/Pivotal GemFire _auto-configures_ Apache Geode or Pivotal GemFire as the _caching provider_
|
||||
when either one is declared on the application classpath, and when no other _caching provider_ (e.g. Redis)
|
||||
has been configured.
|
||||
|
||||
If Spring Boot for Apache Geode/Pivotal GemFire detects that another _cache provider_ has already been configured,
|
||||
then neither Apache Geode nor Pivotal GemFire will serve as the _caching provider_. This allows users to configure,
|
||||
e.g. Redis, or another store, as the _caching provider_, and to use Apache Geode or Pivotal GemFire
|
||||
as your application's persistent store.
|
||||
|
||||
To configure the necessary cache Regions to back the caches declared in Spring cache annotations, this is as simple as
|
||||
using Spring Data for Apache Geode/Pivotal GemFire's
|
||||
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegions.html[`@EnableCachingDefinedRegions`] annotation.
|
||||
|
||||
The complete Spring Boot application looks like this:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
package example.app;
|
||||
|
||||
import ...;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableCachingDefinedRegions
|
||||
class LoanApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LoanApplication.class, args);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
TIP: The `LoanApplicationService` is picked up by Spring's classpath component scan since this class is annotated
|
||||
with Spring's `@Service` stereotype annotation.
|
||||
|
||||
[[geode-caching-provider-look-aside-near-inline]]
|
||||
=== Look-Aside Caching, Near Caching and Inline Caching
|
||||
|
||||
==== Look-Aside Caching
|
||||
|
||||
The caching pattern we demonstrated in the example above is a form of
|
||||
https://content.pivotal.io/blog/an-introduction-to-look-aside-vs-inline-caching-patterns[Look-Aside Caching].
|
||||
|
||||
Essentially, the item of interests is searched for in the cache first, before computing a potentially expensive
|
||||
operation, such a IO or network bound request resulting in either a blocking, or latency intensive operation.
|
||||
If the item can be found in the cache (usually, in-memory) then the item is returned without invoking
|
||||
the expensive operation. If the item cannot be found in the cache, then the operation must be invoked. However,
|
||||
the result of the operation is cached for subsequent requests given the same input.
|
||||
|
||||
==== Near Caching
|
||||
|
||||
_Near Caching_ is another form of caching where the cache is collocated with the application. This is useful when
|
||||
the cache is configured using a client/server arrangement.
|
||||
|
||||
We already mentioned that Spring Boot for Apache Geode & Pivotal GemFire <<clientcache-applications.adoc#geode-clientcache-applications, provides>>
|
||||
an _auto-configured_, `ClientCache` instance out-of-the-box, by default. The `ClientCache` instance is most effective
|
||||
when the data access operations, including cache access, is distributed to the servers in a cluster accessed
|
||||
by the client. This enable other cache client applications to access the same data. However, this also means that
|
||||
the application incurs a network hop penalty to evaluate the presence of the item in the cache.
|
||||
|
||||
To help avoid this network cost in a client/server topology, then a local application cache can be established
|
||||
to maintain a subset of the data in the corresponding server-side cache (known as a cache Region in GemFire/Geode)
|
||||
containing only the data of interests to the application. This "local" cache is consulted before forwarding
|
||||
the lookup request to the server.
|
||||
|
||||
Enabling _Near Caching_ when using either Apache Geode or Pivotal GemFire is as simple as changing the Region's
|
||||
(a.k.a. cache) data management policy from `PROXY` (the default) to `CACHING_PROXY`, like so:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@SpringBootApplication
|
||||
@EnableCachingDefinedRegions(clientRegionShortcut = ClientRegionShortcut.CACHING_PROXY)
|
||||
class LoanApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LoanApplication.class, args);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
TIP: The default, client Region data management policy is
|
||||
{apache-geode-javadoc}/org/apache/geode/cache/client/ClientRegionShortcut.html#PROXY[`ClientRegionShortcut.PROXY`].
|
||||
As such, ion data access operations are forwarded immediately to the server.
|
||||
|
||||
==== Inline Caching
|
||||
|
||||
The final form of caching is _Inline Caching_.
|
||||
|
||||
_Inline Caching_ is like _Look-Aside Caching_, but when a cache miss occurs, the application service method may still
|
||||
not get invoked since the cache (Region) is configured to invoke a loader to potentially load the missing entry.
|
||||
|
||||
In Apache Geode and Pivotal GemFire, the cache, or in GemFire/Geode terminology, the Region, can be configured with
|
||||
a {apache-geode-javadoc}/org/apache/geode/cache/CacheLoader.html[CacheLoader]. This `CacheLoader` is implemented
|
||||
to retrieve the missing value from some external data source, which could be a RDBMS or any other type of data source.
|
||||
|
||||
TIP: See the Apache Geode User Guide on {apache-geode-docs}/developing/outside_data_sources/how_data_loaders_work.html[Data Loaders]
|
||||
for more details.
|
||||
|
||||
You can use Spring to configure a `CacheLoader` as a bean in the Spring context and then wire it to the cache Region.
|
||||
Given the `CacheLoader` is a Spring bean, you can inject any `DataSource` you like into the `CacheLoader`.
|
||||
|
||||
While you can configure client Regions with `CacheLoaders`, it is more common to configure the corresponding
|
||||
server-side Region; for example:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@SpringBootApplication
|
||||
@CacheServerApplication
|
||||
class LoanApplicationServer {
|
||||
|
||||
@Bean("EligibilityDecisions")
|
||||
public PartitionedRegionFactoryBean<Object, Object> eligibilityDecisionsRegion(
|
||||
GemFireCache gemfireCache, CacheLoader decisionManagementSystemLoader) {
|
||||
|
||||
PartitionedRegionFactoryBean<?, EligibilityDecision> eligibilityDecisionsRegion =
|
||||
new PartitionedRegionFactoryBean<>();
|
||||
|
||||
eligibilityDecisionsRegion.setCache(gemfireCache);
|
||||
eligibilityDecisionsRegion.setCacheLoader(decisionManagementSystemLoader);
|
||||
eligibilityDecisionsRegion.setClose(false);
|
||||
eligibilityDecisionsRegion.setPersistent(false);
|
||||
|
||||
return eligibilityDecisionsRegion;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public CacheLoader<?, EligibilityDecision> decisionManagementSystemLoader(
|
||||
DataSource dataSource) {
|
||||
|
||||
return new DecisionManagementSystemLoader(dataSource);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
If the configured `CacheLoader` still cannot resolve the value, the the cache lookup operation results in a miss
|
||||
and the application service method will then be invoked.
|
||||
|
||||
[[geode-caching-provider-advanced-configuration]]
|
||||
=== Advanced Caching Configuration
|
||||
|
||||
Both Apache Geode and Pivotal GemFire support additional caching capabilities to manage the entries stored in the cache.
|
||||
|
||||
As you can imagine, given the cache entries are stored in-memory, it becomes important to monitor and manage the
|
||||
available memory wisely. After all, by default, both Apache Geode and Pivotal GemFire store data on the JVM Heap.
|
||||
|
||||
Several techniques can be employed to more effectively manage memory, such as using
|
||||
{apache-geode-docs}/developing/eviction/chapter_overview.html[Eviction], possibly
|
||||
{apache-geode-docs}/developing/storing_data_on_disk/chapter_overview.html[overflowing to disk],
|
||||
configuring both entry _Idle-Timeout (TTI) as well as _Time-To-Live (TTL)_
|
||||
{apache-geode-docs}/developing/expiration/chapter_overview.html[Expiration policies],
|
||||
configuring {apache-geode-docs}/managing/region_compression.html[Compression],
|
||||
and using {apache-geode-docs}/managing/heap_use/off_heap_management.html[Off-Heap], or main memory.
|
||||
|
||||
There are several other strategies that can be used as well, as described in
|
||||
{apache-geode-docs}/managing/heap_use/heap_management.html[Managing Heap and Off-heap Memory].
|
||||
|
||||
This is well beyond the scope of this document, but know that Spring Data for Apache Geode & Pivotal GemFire
|
||||
make all of these {spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[configuration options] simple.
|
||||
@@ -106,3 +106,4 @@ As such, it would be pertinent to begin your Spring Boot education {spring-boot-
|
||||
Finally, we arrive at Spring Boot for Apache Geode & Pivotal GemFire.
|
||||
|
||||
include::clientcache-applications.adoc[]
|
||||
include::caching.adoc[]
|
||||
|
||||
Reference in New Issue
Block a user