From 4fc8d9cbd96fb758f59bbc4eb2750d6bfca8c86e Mon Sep 17 00:00:00 2001 From: John Blum Date: Tue, 18 Aug 2020 13:13:39 -0700 Subject: [PATCH] Edit chapter on caching. --- .../src/docs/asciidoc/caching.adoc | 123 ++++++++++-------- 1 file changed, 72 insertions(+), 51 deletions(-) diff --git a/spring-geode-docs/src/docs/asciidoc/caching.adoc b/spring-geode-docs/src/docs/asciidoc/caching.adoc index 7b4eb04c..f17d3f5c 100644 --- a/spring-geode-docs/src/docs/asciidoc/caching.adoc +++ b/spring-geode-docs/src/docs/asciidoc/caching.adoc @@ -115,16 +115,29 @@ Instead, you should use SDG's `@EnableCachingDefinedRegions` on an appropriate S `@Configuration` class. [[geode-caching-provider-look-aside-near-inline]] -=== Look-Aside Caching, Near Caching and Inline Caching +=== Look-Aside Caching, Near Caching, Inline Caching and Multi-Site Caching -Three different types of caching patterns can be applied with Spring when using Apace Geode or {gemfire-name} +Four different types of caching patterns can be applied with Spring when using Apace Geode or {gemfire-name} for your application caching needs. -The 3 primary caching patterns include: +The 4 primary caching patterns include: * _Look-Aside Caching_ * _Near Caching_ * _Inline Caching_ +* _Multi-Site Caching_ + +Typically, when most users think of caching, they are thinking of _Look-Aside Caching_. This is the default caching +pattern applied by _Spring's Cache Abstraction_. + +In a nutshell, _Near Caching_ keeps the data closer to where the data is used thereby improving on performance +due to lower latencies when data is needed (i.e. no network hops). + +Within _Inline Caching_, developers have a choice between synchronous (_Read/Write-Through_) and asynchronous +(_Write-Behind_) configurations depending on the application use case and requirements. + +Within _Multi-Site Caching_, there are _Active-Passive_ and _Active-Active_ arrangements. More details on _Multi-Site +Caching_ will be presented in a later release. [[geode-caching-provider-look-aside-caching]] ==== Look-Aside Caching @@ -218,36 +231,44 @@ in the Region that might have been changed by other clients accessing the same d [[geode-caching-provider-inline-caching]] ==== Inline Caching -The final pattern of caching we'll discuss is _Inline Caching_. +The final pattern of caching we will discuss in this chapter is _Inline Caching_. + +There are two different configurations of _Inline Caching_ that developers can apply to their Spring Boot applications +when using this pattern of caching: Synchronous (_Read/Write-Through_) and Asynchronous (_Write-Behind_). + +NOTE: Asynchronous (currently) only offers write capabilities, from the cache to the backend, external data source. +There is not option to asynchronously and automatically load the cache when the entry value becomes available in the +backend, external data source. + +[[geode-caching-provider-inline-caching-synchronous]] +===== Synchronous Inline Caching When employing _Inline Caching_ and a cache miss occurs, the application service method may still not be invoked -since the a Region can be configured to invoke a loader to load the missing entry from an external data source. +since a Region can be configured to invoke a loader to load the missing entry from an backend, external data source. With {geode-name} and {gemfire-name}, the cache, or using {geode-name}/{gemfire-name} terminology, the Region, can be -configured with a {apache-geode-javadoc}/org/apache/geode/cache/CacheLoader.html[CacheLoader]. This `CacheLoader` is -implemented to retrieve missing values from some external data source, which could be an RDBMS or any other type of +configured with a {apache-geode-javadoc}/org/apache/geode/cache/CacheLoader.html[CacheLoader]. A `CacheLoader` is +implemented to retrieve missing values from an external data source, which could be an RDBMS or any other type of data store (e.g. another NoSQL store like Apache Cassandra, MongoDB or Neo4j). TIP: See the {geode-name} User Guide on {apache-geode-docs}/developing/outside_data_sources/how_data_loaders_work.html[Data Loaders] for more details. -Likewise, an {geode-name} or {gemfire-name} Region can be configured with a -{apache-geode-javadoc}/org/apache/geode/cache/CacheWriter.html[CacheWriter]. A `CacheWriter` is responsible for -writing any entry put into the Region to the backend data store, such as an RDBMS. This is referred to as a -"_write-through_" operations because it is synchronous. If the backend data store fails to be written to then the entry -will not be stored in the Region. This helps to ensure some level of consistency between the backing data store -and the {geode-name} or {gemfire-name} Region. +Likewise, an {geode-name} or {gemfire-name} Region can also be configured with a +{apache-geode-javadoc}/org/apache/geode/cache/CacheWriter.html[CacheWriter]. A `CacheWriter` is responsible for writing +any entry put into the Region to the backend data store, such as an RDBMS. This is referred to as a "_write-through_" +operation because it is synchronous. If the backend data store fails to be updated then the entry will not be stored in +the Region. This helps to ensure some level of consistency between the backend data store and the {geode-name} +or {gemfire-name} Region. -TIP: It is also possible to implement Inline-Caching using an _asynchronous_, _write-behind_ operation by registering -an {apache-geode-javadoc}/org/apache/geode/cache/asyncqueue/AsyncEventListener.html[AsyncEventListener] -on an {apache-geode-javadoc}/org/apache/geode/cache/asyncqueue/AsyncEventQueue.html[AEQ] tied to a server-side Region. +TIP: It is also possible to implement _Inline-Caching_ using _asynchronous_, _write-behind_ operations by registering +an {apache-geode-javadoc}/org/apache/geode/cache/asyncqueue/AsyncEventListener.html[AsyncEventListener] on an +{apache-geode-javadoc}/org/apache/geode/cache/asyncqueue/AsyncEventQueue.html[AEQ] attached to a server-side Region. You should consult the {geode-name} User Guide for more -{apache-geode-docs}/developing/events/implementing_write_behind_event_handler.html[details]. +{apache-geode-docs}/developing/events/implementing_write_behind_event_handler.html[details]. We cover _asynchronous_, +_write-behind_ _Inline Caching_ in the next section. -NOTE: Since SBDG is currently focused on the client-side, _async_, _write-behind_ behavior is not currently covered with -extensive, convenient support, although, it is still very much possible to do. - -The typical pattern of _Inline Caching_ when applied to application code looks like the following: +The typical pattern of _Inline Caching_ when applied to application code looks similar to the following: .Inline Caching Pattern Applied [source,java] @@ -270,15 +291,15 @@ class CustomerService { } ---- -The main difference is, there are no Spring or JSR-107 caching annotations applied to the service methods +The main difference is, there are no Spring or JSR-107 caching annotations applied to the application's service methods and the `CustomerRepository` is accessing {geode-name} or {gemfire-name} directly and NOT the RDBMS. -[[geode-caching-provider-inline-caching-cacheloader-cachewriter]] -===== Implementing CacheLoaders, CacheWriters for Inline Caching +[[geode-caching-provider-inline-caching-synchronous-cacheloader-cachewriter]] +====== Implementing CacheLoaders & CacheWriters for Inline Caching You can use Spring to configure a `CacheLoader` or `CacheWriter` as a bean in the Spring `ApplicationContext` -and then wire it to a Region. Given the `CacheLoader` or `CacheWriter` is a Spring bean like any other bean -in the Spring `ApplicationContext`, you can inject any `DataSource` you like into the Loader/Writer. +and then wire the loader and/or writer to a Region. Given the `CacheLoader` or `CacheWriter` is a Spring bean +like any other bean in the Spring `ApplicationContext`, you can inject any `DataSource` you like into the Loader/Writer. While you can configure client Regions with `CacheLoaders` and `CacheWriters`, it is typically more common to configure the corresponding server-side Region; for example: @@ -296,7 +317,7 @@ class FinancialLoanApplicationServer { @Bean("EligibilityDecisions") PartitionedRegionFactoryBean eligibilityDecisionsRegion( GemFireCache gemfireCache, CacheLoader decisionManagementSystemLoader, - CacheWriter decisionManagemenSystemWriter) { + CacheWriter decisionManagementSystemWriter) { PartitionedRegionFactoryBean eligibilityDecisionsRegion = new PartitionedRegionFactoryBean<>(); @@ -304,7 +325,6 @@ class FinancialLoanApplicationServer { eligibilityDecisionsRegion.setCache(gemfireCache); eligibilityDecisionsRegion.setCacheLoader(decisionManagementSystemLoader); eligibilityDecisionsRegion.setCacheWriter(decisionManagementSystemWriter); - eligibilityDecisionsRegion.setClose(false); eligibilityDecisionsRegion.setPersistent(false); return eligibilityDecisionsRegion; @@ -350,7 +370,7 @@ class DecisionManagementSystemLoader implements CacheLoader entryEvent) { - // Use configured DataSource to save (e.g. INSERT) the entry to the backend data store + // Use configured DataSource to save (e.g. INSERT) the entry value into the backend data store } public void beforeUpdate(EntryEvent entryEvent) { - // Use the configured DataSource to save (e.g. UPDATE or UPSERT) the entry in the backend data store + // Use the configured DataSource to save (e.g. UPDATE or UPSERT) the entry value into the backend data store } public void beforeDestroy(EntryEvent entryEvent) { - // Use the configured DataSource to delete (i.e. DELETE) the entry from the backend data store + // Use the configured DataSource to delete (i.e. DELETE) the entry value from the backend data store } ... @@ -398,8 +418,8 @@ your backend data store (e.g. JDBC, Spring's `JdbcTemplate`, JPA/Hibernate, etc) a `javax.sql.DataSource`. In fact, we will present another, more useful and convenient approach to implementing _Inline Caching_ in the next section. -[[geode-caching-provider-inline-caching-using-spring-data-repositories]] -===== Inline Caching using Spring Data Repositories. +[[geode-caching-provider-inline-caching-synchronous-using-spring-data-repositories]] +====== Inline Caching using Spring Data Repositories Spring Boot for {geode-name} & {gemfire-name} (SBDG) now offers dedicated support and configuration of _Inline Caching_ using Spring Data Repositories. @@ -411,23 +431,23 @@ MongoDB for Documents, Neo4j for Graphs, Elasticsearch for Search, and so on). 2. Use complex mapping strategies (e.g. ORM provided by JPA/Hibernate). -It is our belief that users should be putting data where it is most easily accessible. If you are accessing -and processing Documents, then most likely MongoDB (or Couchbase or another document store) might be -the most logical choice to manage your application's Documents. +It is our belief that users should be storing data where it is most easily accessible. If you are accessing +and processing Documents, then MongoDB, Couchbase or another document store is probably going to be the most logical +choice to manage your application's Documents. However, that does not mean you have to give up {geode-name} or {gemfire-name} in your application/system architecture. -You can leverage each data store for what it is good at. While MongoDB is good at Document handling, {geode-name} +You can leverage each data store for what it is good at. While MongoDB is excellent at handling documents, {geode-name} is a highly valuable choice for consistency, high availability, multi-site, low-latency/high-throughput scale-out -Use Cases. +application use cases. -As such, using {geode-name} and {gemfire-name}'s `CacheLoader/CacheWriter` mechanism provides a integration point -between itself and other data stores to best serve your Use Case and application requirements/needs. +As such, using {geode-name} and {gemfire-name}'s `CacheLoader/CacheWriter` mechanism provides a nice integration point +between itself and other data stores to best serve your application's use case and requirements. -And now, SBDG just made this even easier. +And now, SBDG has just made this even easier. EXAMPLE -Let's say you are using JPA/Hibernate to access (store and retrieve) data in a Oracle Database. +Let's say you are using JPA/Hibernate to access (store and retrieve) data managed in an Oracle Database. Then, you can configure {geode-name} to read/write-through to the backend Oracle Database when performing cache (Region) operations by delegating to a Spring Data (JPA) Repository. @@ -454,18 +474,18 @@ class SpringBootOracleDatabaseApacheGeodeApplication { Out-of-the-box, SBDG provides the `InlineCachingRegionConfigurer` interface. -Given a `Predicate` to express and match the target Region by name along with a Spring Data `CrudRepository`, -the `InlineCachingRegionConfigurer` will configure and adapt the Spring Data `CrudRepository` as a `CacheLoader` -and `CacheWriter` for the Region (e.g. "Customers"), i.e. it enables the Region to use _Inline Caching_. +Given a `Predicate` to express the criteria used to match the target Region by name and a Spring Data `CrudRepository`, +the `InlineCachingRegionConfigurer` will configure and adapt the Spring Data `CrudRepository` as a `CacheLoader` and +`CacheWriter` registered on the Region (e.g. "Customers") to enable _Inline Caching_ functionality. -You simply only need to declare `InlineCachingRegionConfigurer` as a bean in the Spring application context -and make the association between the Region (by name) and the appropriate Spring Data `CrudRepository`. +You simply only need to declare `InlineCachingRegionConfigurer` as a bean in the Spring `ApplicationContext` and make +the association between the Region (by name) and the appropriate Spring Data `CrudRepository`. In this example, we used JPA and Spring Data JPA to store/retrieve the data in the cache (Region) to/from a backend database. But, you can inject any Spring Data Repository for any data store (e.g. Redis, MongoDB, etc) that supports the Spring Data Repository abstraction. -TIP: If you only want to support oneway data access operations when using _Inline Caching_, then you can use either +TIP: If you only want to support one way data access operations when using _Inline Caching_, then you can use either the `RepositoryCacheLoaderRegionConfigurer` for reads or the `RepositoryCacheWriterRegionConfigurer` for writes, instead of the `InlineCachingRegionConfigurer`, which supports both reads and writes. @@ -478,7 +498,7 @@ from the SBDG test suite. A dedicated sample will be provided in a future releas Both {geode-name} and {gemfire-name} 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 +As you can imagine, given that cache entries are stored in-memory, it becomes important to monitor and manage the available memory wisely. After all, by default, both {geode-name} and {gemfire-name} store data in the JVM Heap. Several techniques can be employed to more effectively manage memory, such as using @@ -493,7 +513,8 @@ 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]. While this is well beyond the scope of this document, know that Spring Data for {geode-name} & {gemfire-name} -make all of these {spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[configuration options] simple. +make all of these {spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[configuration options] available +and simple to use. [[geode-caching-provider-disable]] === Disable Caching