diff --git a/spring-geode-docs/src/docs/asciidoc/caching.adoc b/spring-geode-docs/src/docs/asciidoc/caching.adoc new file mode 100644 index 00000000..19441d4b --- /dev/null +++ b/spring-geode-docs/src/docs/asciidoc/caching.adoc @@ -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 <> +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 eligibilityDecisionsRegion( + GemFireCache gemfireCache, CacheLoader decisionManagementSystemLoader) { + + PartitionedRegionFactoryBean eligibilityDecisionsRegion = + new PartitionedRegionFactoryBean<>(); + + eligibilityDecisionsRegion.setCache(gemfireCache); + eligibilityDecisionsRegion.setCacheLoader(decisionManagementSystemLoader); + eligibilityDecisionsRegion.setClose(false); + eligibilityDecisionsRegion.setPersistent(false); + + return eligibilityDecisionsRegion; + } + + + @Bean + public CacheLoader 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. diff --git a/spring-geode-docs/src/docs/asciidoc/index.adoc b/spring-geode-docs/src/docs/asciidoc/index.adoc index 5679e2f2..daca7c83 100644 --- a/spring-geode-docs/src/docs/asciidoc/index.adoc +++ b/spring-geode-docs/src/docs/asciidoc/index.adoc @@ -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[]