Caching With Spring - Spring I/O Barcelona 2016

Caching With Spring - Spring I/O Barcelona 2016

Caching is relevant for a wide range of business applications and there is a huge variety of products in the market, ranging from easy to adopt local heap based caches to powerful distributed data grids. This talk addresses advanced usage of Spring’s caching abstractions such as integrating a cache provider that is not integrated by the default Spring Package.

In addition, I will also give an overview of the JCache Specification and its adoption in the Spring ecosystem. Finally, the presentation will also address several best practices for integrating various caching solutions into enterprise grade applications that don’t have the luxury of having „eventual consistency“ as a non-functional requirement.

21a532a137b506128914478ac521fc8b?s=128

Michael Plöd

May 19, 2016
Tweet

Transcript

  1. Caching in Spring Michael Plöd - innoQ Germany @bitboss

  2. I will talk about Caching Types / Topologies Best Practices

    for Caching in Enterprise Applications Caching with Spring JCache and Spring I will NOT talk about Latency / Synchronization discussion What is the best caching product on the market HTTP / Database Caching Caching in JPA, Hibernate or other ORMs
  3. CACHES Types of 
 Places for Local Cache, Data Grid,

    Document Store, JPA First Level Cache, JPA Second Level Cache, Hybrid Cache Database, Heap, HTTP Proxy, Browser, Prozessor, Disk, Off Heap, Persistence-Framework, Application
  4. Business-Applications !=
 Twitter / Facebook & co.

  5. Which data shall I cache? Where shall I cache? Which

    cache shall I use? Which impact does it have on my infrastructure How about data- consistency How do I introduce caching? How about caching in Spring?
  6. 1 Know your topology

  7. Local In-Memory JVM Cache

  8. Clustered JVM Cache JVM Cache JVM Cache JVM Cache

  9. Which data shall I cache? Where shall I cache? Which

    cache shall I use? Which impact does it have on my infrastructure How about data- consistency How do I introduce caching? How about caching in Spring?
  10. JVM JVM JVM JVM Clustered - with sync Cache Cache

    Cache Cache Invalidation Replication
  11. 2 Avoid real replication where possible

  12. Cache Cache Cache Cache #1 PUT (Insert) PUT (Insert) #1

    #1 PUT (Insert) PUT (Insert) #1 Invalidation - Option 1
  13. Cache Cache Cache Cache #1 #1 PUT (Update) #1 inv

    #1 #1 Invalidation - Option 1
  14. Cache Cache Cache Cache #1 PUT (Insert) PUT (Insert) #1

    #1 PUT (Insert) PUT (Insert) #1 Invalidation - Option 2
  15. Cache Cache Cache Cache #1 #1 #1 #1 PUT (Insert)

    PUT (Update) #1 Replication
  16. As of now every cache could potentially hold every data

    which consumes heap memory
  17. Big Heap ?

  18. Which data shall I cache? Where shall I cache? Which

    cache shall I use? Which impact does it have on my infrastructure How about data- consistency How do I introduce caching? How about caching in Spring?
  19. 3 Avoid big heaps just for caching

  20. Big heap leads to long major GCs Application Data Cache

    32 GB
  21. Small caches are a bad idea! Many evictions, fewer hits,

    no „hot data“.
 
 This is especially critical for replicating caches.
  22. 4 Use a distributed cache for big amounts of data

  23. Distributed Caches JVM JVM JVM JVM Cache Node 1 Cache

    Node 2 Cache Node 3
  24. 1 Customer #23 Customer #30 Customer #27 Customer #32 2

  25. 1 2 Customer #23 Customer #30 Customer #27 Customer #32

    BACKUP #27 BACKUP #32 BACKUP #23 BACKUP #30 Data is being distributed and backed up
  26. 1 2 Customer #23 Customer #30 Customer #27 Customer #32

    BACKUP #27 BACKUP #32 BACKUP #23 BACKUP #30 3
  27. 3 1 2 Customer #23 Customer #30 Customer #27 Customer

    #32 BACKUP #27 BACKUP #32 BACKUP #23 BACKUP #30 4
  28. 4 3 1 2 Customer #23 Customer #30 Customer #27

    Customer #32 BACKUP #27 BACKUP #32 BACKUP #23 BACKUP #30
  29. A distributed cache leads to smaller heaps, more capacity and

    is easy to scale Application Data Cache 2 - 4 GB … Cache
  30. Which data shall I cache? Where shall I cache? Which

    cache shall I use? Which impact does it have on my infrastructure How about data- consistency How do I introduce caching? How about caching in Spring?
  31. 5 Make sure that only suitable data gets cached

  32. The best cache candidates are read- mostly data, which are

    expensive to obtain
  33. If you urgently must cache write-intensive data make sure to

    use a distributed cache and not a replicated or invalidating one
  34. Which data shall I cache? Where shall I cache? Which

    cache shall I use? Which impact does it have on my infrastructure How about data- consistency How do I introduce caching? How about caching in Spring?
  35. 6 Only use existing cache implementations

  36. NEVER write your own cache implementation EVER

  37. CACHE
 Implementations Infinispan, EHCache, Hazelcast, Couchbase, Memcache, OSCache, SwarmCache, Xtreme

    Cache, Apache DirectMemory Terracotta, Coherence, Gemfire, Cacheonix, WebSphere eXtreme Scale, Oracle 12c In Memory Database
  38. Which data shall I cache? Where shall I cache? Which

    cache shall I use? Which impact does it have on my infrastructure How about data- consistency How do I introduce caching? How about caching in Spring?
  39. 7 Mind the security gap

  40. Application „CRM“ „Host“ DB Security Security Security Cache CRM Data

    SAP Data DB Data ? Mind security when reading data from the cache
  41. I <3 Spring Bot censored I’m at a Spring conference

    
 and this guy is 40 slides in and hasn’t yet mentioned Spring even if he advertised
  42. 8 Abstract your cache provider

  43. public Account retrieveAccount(String accountNumber) { Cache cache = ehCacheMgr.getCache(„accounts“); Account

    account = null; Element element = cache.get(accountNumber); if(element == null) { //execute some business logic for retrieval //account = result of logic above cache.put(new Element(accountNumber, account)); } else { account = (Account)element.getObjectValue(); } return account; } Tying your code to a cache provider is bad practice
  44. public Account retrieveAccount(String accountNumber) { Cache cache = ehCacheMgr.getCache(„accounts“); Account

    account = null; Element element = cache.get(accountNumber); if(element == null) { //execute some business logic for retrieval //account = result of logic above cache.put(new Element(accountNumber, account)); } else { account = (Account)element.getObjectValue(); } return account; } Try switching from EHCache to Hazelcast You will have to adjust these lines of code to the Hazelcast API
  45. public Account retrieveAccount(String accountNumber) { Cache cache = ehCacheMgr.getCache(„accounts“); Account

    account = null; Element element = cache.get(accountNumber); if(element == null) { //execute some business logic for retrieval //account = result of logic above cache.put(new Element(accountNumber, account)); } else { account = (Account)element.getObjectValue(); } return account; } You can’t switch cache providers between environments EHCache is tightly coupled to your code
  46. public Account retrieveAccount(String accountNumber) { Cache cache = ehCacheMgr.getCache(„accounts“); Account

    account = null; Element element = cache.get(accountNumber); if(element == null) { //execute some business logic for retrieval //account = result of logic above cache.put(new Element(accountNumber, account)); } else { account = (Account)element.getObjectValue(); } return account; } You mess up your business logic with infrastructure This is all caching related code without any business relevance
  47. <cache:annotation-driven cache-manager="ehCacheManager"/> <!-- EH Cache local --> <bean id="ehCacheManager" 


    class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="ehcache"/> <bean id="ehcache" 
 class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="/ehcache.xml"/> @Cacheable("Customers") public Customer getCustomer(String customerNumber) { … } Introducing Spring’s cache abstraction @Configuration
 @EnableCaching
 public class CacheConfiguration implements CachingConfigurer { ... }
  48. Spring’s Caching Annotations Annotation Description @Cacheable Demarcates cachable methods, can

    read and write to the cache(s) @CacheEvict Demarcates methods that perform cache eviction, that is methods that act as triggers for removing data from the cache. @CachePut Updates the cache with the annotated method’s return value. Will always execute the method. @Caching Allows multiple nested @Cacheable, @CacheEvict and @CachePut annotations to be used on the same method @CacheConfig Class-level annotation that allows to share the cache names, the custom KeyGenerator, the custom CacheManager and finally the custom CacheResolver. Does not enable caching.
  49. Default Key Generation Strategy @Cacheable("Customers") public Customer getCustomer(String customerNumber) {

    … } @Cacheable("CustomerList") public List<Customer> listCustomers(int start, int count) { … } @Cacheable("MonthlyReport") public Report getMonthlyReport() { … } customerNumber SimpleKey containing
 start and count SimpleKey.EMPTY Key Annotation
  50. public class MyOwnKeyGenerator implements KeyGenerator { @Override public Object generate(Object

    target, Method method, Object... params) { if (params.length == 0) { return new SimpleKey("EMPTY"); } if (params.length == 1) { Object param = params[0]; if (param != null && !param.getClass().isArray()) { return param; } } return new SimpleKey(params); } } You need a custom default KeyGenerator? <cache:annotation-driven cache-manager="hazelcastCacheManager" 
 keyGenerator="myOwnKeyGenerator" />
  51. SpEL in Caching Annotations @Cacheable("concerts", key="#location.id") public List<Concert> findConcerts(Location location)

    @Cacheable("concerts", key="T(someType).hash(#location)") public List<Concert> findConcerts(Location location) @Cacheable("concerts", 
 condition="#location.city == 'Dallas')",
 unless="#location.outOfBusiness") public List<Concert> findConcerts(Location location) Key: id of location Effect Annotation @CachePut("locations", key="#result.id") public Location saveLocation(Location location) Key: hashCode of location Conditional Caching if Location
 is in Dallas and operating Key: generated id of result
  52. I have multiple Caches
 and Cache Managers! @Cacheable("concerts", cacheManager="hazelCastCacheManager") public

    List<Concert> findConcerts(Location location) @Cacheable("bands", cacheManager="gemfireCacheManager")) public List<Band> listBand(int start, int count) @Cacheable("bands", cacheResolver="myOwnCacheResolver")) public List<Band> listBand(int start, int count) Programmatic resolution through an implementation of the CacheResolver Interface Manual Assignment Manual Assignment
  53. public class MyOwnCacheResolver extends AbstractCacheResolver { @Autowired
 public MyOwnCacheResolver(CacheManager cacheManager)

    {
 super(cacheManager);
 }
 
 protected Collection<String> getCacheNames(CacheOperationInvocationContext<?> context) { return getCacheNames(context.getTarget().getClass()); } private getCacheNames(Class<?> businessServiceClass) {
 ...
 } } Working with CacheResolvers @Cacheable("bands", cacheResolver="myOwnCacheResolver")) public List<Band> listBand(int start, int count)
  54. You can use your own custom Annotations @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Cacheable("concerts",

    key="id") public @interface DefaultConcertCacheable { } @DefaultConcertCacheable public Concert getConcert(Long id)
  55. Spring 4.x is the first commerically supported container with JCache

    (JSR-107) Support! That’s years ahead of any JEE Server
  56. Spring vs JCache Annotations Spring JCache Description @Cacheable @CacheResult Similar,

    but @CacheResult can cache Exceptions and force method execution @CacheEvict @CacheRemove Similar, but @CacheRemove supports eviction in the case of Exceptions @CacheEvict
 (removeAll=true) @CacheRemoveAll Same rules as for @CacheEvict vs @CacheRemove @CachePut @CachePut Different semantic: cache content must be annotated with @CacheValue. JCache brings Exception caching and caching before or after method execution @CacheConfig @CachePut Identical
  57. Except for the dependencies JCache API and spring-context- support no

    further steps need to be taken to enable JCache Annotations in Spring Applications
  58. How do I disable caching for Unit Tests? <bean id="cacheManager"

    class="org.springframework.cache.support.CompositeCacheManager"> <property name="cacheManagers"> <list> <ref bean="guavaCache"/> <ref bean="ehCache"/> </list> </property> <property name="fallbackToNoOpCache" value="true"/> </bean>
  59. Spring I/O 2016 THANK YOU!
 
 Michael Plöd @bitboss

  60. THANKS 
 Michael Plöd 
 @bitboss
 https://slideshare.net/mploed