Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Business-Applications !=
 Twitter / Facebook & co.

Slide 5

Slide 5 text

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?

Slide 6

Slide 6 text

1 Know your topology

Slide 7

Slide 7 text

Local In-Memory JVM Cache

Slide 8

Slide 8 text

Clustered JVM Cache JVM Cache JVM Cache JVM Cache

Slide 9

Slide 9 text

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?

Slide 10

Slide 10 text

JVM JVM JVM JVM Clustered - with sync Cache Cache Cache Cache Invalidation Replication

Slide 11

Slide 11 text

2 Avoid real replication where possible

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

Cache Cache Cache Cache #1 #1 PUT (Update) #1 inv #1 #1 Invalidation - Option 1

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

Cache Cache Cache Cache #1 #1 #1 #1 PUT (Insert) PUT (Update) #1 Replication

Slide 16

Slide 16 text

As of now every cache could potentially hold every data which consumes heap memory

Slide 17

Slide 17 text

Big Heap ?

Slide 18

Slide 18 text

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?

Slide 19

Slide 19 text

3 Avoid big heaps just for caching

Slide 20

Slide 20 text

Big heap leads to long major GCs Application Data Cache 32 GB

Slide 21

Slide 21 text

Small caches are a bad idea! Many evictions, fewer hits, no „hot data“.
 
 This is especially critical for replicating caches.

Slide 22

Slide 22 text

4 Use a distributed cache for big amounts of data

Slide 23

Slide 23 text

Distributed Caches JVM JVM JVM JVM Cache Node 1 Cache Node 2 Cache Node 3

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

A distributed cache leads to smaller heaps, more capacity and is easy to scale Application Data Cache 2 - 4 GB … Cache

Slide 30

Slide 30 text

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?

Slide 31

Slide 31 text

5 Make sure that only suitable data gets cached

Slide 32

Slide 32 text

The best cache candidates are read- mostly data, which are expensive to obtain

Slide 33

Slide 33 text

If you urgently must cache write-intensive data make sure to use a distributed cache and not a replicated or invalidating one

Slide 34

Slide 34 text

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?

Slide 35

Slide 35 text

6 Only use existing cache implementations

Slide 36

Slide 36 text

NEVER write your own cache implementation EVER

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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?

Slide 39

Slide 39 text

7 Mind the security gap

Slide 40

Slide 40 text

Application „CRM“ „Host“ DB Security Security Security Cache CRM Data SAP Data DB Data ? Mind security when reading data from the cache

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

8 Abstract your cache provider

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

@Cacheable("Customers") public Customer getCustomer(String customerNumber) { … } Introducing Spring’s cache abstraction @Configuration
 @EnableCaching
 public class CacheConfiguration implements CachingConfigurer { ... }

Slide 48

Slide 48 text

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.

Slide 49

Slide 49 text

Default Key Generation Strategy @Cacheable("Customers") public Customer getCustomer(String customerNumber) { … } @Cacheable("CustomerList") public List listCustomers(int start, int count) { … } @Cacheable("MonthlyReport") public Report getMonthlyReport() { … } customerNumber SimpleKey containing
 start and count SimpleKey.EMPTY Key Annotation

Slide 50

Slide 50 text

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?

Slide 51

Slide 51 text

SpEL in Caching Annotations @Cacheable("concerts", key="#location.id") public List findConcerts(Location location) @Cacheable("concerts", key="T(someType).hash(#location)") public List findConcerts(Location location) @Cacheable("concerts", 
 condition="#location.city == 'Dallas')",
 unless="#location.outOfBusiness") public List 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

Slide 52

Slide 52 text

I have multiple Caches
 and Cache Managers! @Cacheable("concerts", cacheManager="hazelCastCacheManager") public List findConcerts(Location location) @Cacheable("bands", cacheManager="gemfireCacheManager")) public List listBand(int start, int count) @Cacheable("bands", cacheResolver="myOwnCacheResolver")) public List listBand(int start, int count) Programmatic resolution through an implementation of the CacheResolver Interface Manual Assignment Manual Assignment

Slide 53

Slide 53 text

public class MyOwnCacheResolver extends AbstractCacheResolver { @Autowired
 public MyOwnCacheResolver(CacheManager cacheManager) {
 super(cacheManager);
 }
 
 protected Collection getCacheNames(CacheOperationInvocationContext> context) { return getCacheNames(context.getTarget().getClass()); } private getCacheNames(Class> businessServiceClass) {
 ...
 } } Working with CacheResolvers @Cacheable("bands", cacheResolver="myOwnCacheResolver")) public List listBand(int start, int count)

Slide 54

Slide 54 text

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)

Slide 55

Slide 55 text

Spring 4.x is the first commerically supported container with JCache (JSR-107) Support! That’s years ahead of any JEE Server

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

Except for the dependencies JCache API and spring-context- support no further steps need to be taken to enable JCache Annotations in Spring Applications

Slide 58

Slide 58 text

How do I disable caching for Unit Tests?

Slide 59

Slide 59 text

Spring I/O 2016 THANK YOU!
 
 Michael Plöd @bitboss

Slide 60

Slide 60 text

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