Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[Geekout] Distributed Caching With Jcache And Beyond

[Geekout] Distributed Caching With Jcache And Beyond

Do you need more performance from your Java applications? Is latency causing you a stress? If so, let’s look at JCache, the Java caching API. JCache (JSR 107) is a vendor-neutral caching specification for Java. No need for proprietary non-standard caching solutions in Java land anymore. This code-driven session demonstrates how to integrate JCache into your Java applications.
In this talk, Viktor will cover:
How distributed caching works in general.
Capabilities of JCache API.
Use cases, best practices and the future of JCache.
As a bonus, you will see how JCache support already integrated into many popular open source frameworks!

Viktor Gamov

June 09, 2016
Tweet

More Decks by Viktor Gamov

Other Decks in Technology

Transcript

  1. •Performance •Offload expensive parts of your architecture •Scale up –

    get the most out of one machine •Scale out – add more capacity with more machines •Usually very fast and easy to apply Cache is good for…
  2. Business Application (instance 2) Local cache Business Application (instance 1)

    Service Service Service RDBMS Mainframe MongoDB NoSQL REST Local cache
  3. public interface Cache<K, V> { void put(K key, V value);

    V putIfAbsent(K key, V value); V get(K key); long size(); }
  4. public class LocalCache<Integer, Company> implements Cache<Integer, Company> { ConcurrentMap<Integer, Company>

    storage = new ConcurrentHashMap<>(); @Override public void put(Integer key, Company value) { this.storage.put(key, value); } ... }
  5. public class LocalCache<Integer, Company> implements Cache<Integer, Company> { ConcurrentMap<Integer, Company>

    storage = new ConcurrentHashMap<>(); @Override public void put(Integer key, Company value) { this.storage.put(key, value); } ... }
  6. LocalCache<Integer, String> myCache = new LocalCache<>(); // 20 MB String

    value= new String(new char[10000000]); Runtime runtime = Runtime.getRuntime(); int keyCount = 0; int mb = 1024 * 1024; while (true) { myCache.put(keyCount, value); keyCount++; System.out.printf("Unique Puts = %s keyCount : Free Memory (MB) = %s\n", keyCount, runtime.freeMemory() / mb); }
  7. Unique Puts = 1919785 keyCount : Free Memory (MB) =

    2 Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded LocalCache<Integer, String> myCache = new LocalCache<>(); // 20 MB String value= new String(new char[10000000]); Runtime runtime = Runtime.getRuntime(); int keyCount = 0; int mb = 1024 * 1024; while (true) { myCache.put(keyCount, value); keyCount++; System.out.printf("Unique Puts = %s keyCount : Free Memory (MB) = %s\n", keyCount, runtime.freeMemory() / mb); }
  8. import javax.cache.Caching; import javax.cache.configuration.MutableConfiguration; MutableConfiguration<String, Integer> config = new MutableConfiguration<>();

    config.setStoreByValue(true) .setTypes(String.class, Integer.class) .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(TEN_SEC)); Caching.getCachingProvider().getCacheManager().createCache("test", config);
  9. import javax.cache.Caching; import javax.cache.configuration.MutableConfiguration; MutableConfiguration<String, Integer> config = new MutableConfiguration<>();

    config.setStoreByValue(true) .setTypes(String.class, Integer.class) .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(TEN_SEC)); Caching.getCachingProvider().getCacheManager().createCache("test", config);
  10. import javax.cache.Caching; import javax.cache.configuration.MutableConfiguration; MutableConfiguration<String, Integer> config = new MutableConfiguration<>();

    config.setStoreByValue(true) .setTypes(String.class, Integer.class) .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(TEN_SEC)); Caching.getCachingProvider().getCacheManager().createCache("test", config);
  11. import javax.cache.Cache; import javax.cache.Caching; Cache<Integer, String> myCache = Caching.getCache("test"); //

    20 MB String value= new String(new char[10000000]); Runtime runtime = Runtime.getRuntime(); int keyCount = 0; int mb = 1024 * 1024; while (true) { myCache.put(keyCount, value); keyCount++; System.out.printf("Unique Puts = %s keyCount : Free Memory (MB) = %s\n", keyCount, runtime.freeMemory() / mb); }
  12. import javax.cache.Cache; import javax.cache.Caching; Cache<Integer, String> myCache = Caching.getCache("test"); //

    20 MB String value= new String(new char[10000000]); Runtime runtime = Runtime.getRuntime(); int keyCount = 0; int mb = 1024 * 1024; while (true) { myCache.put(keyCount, value); keyCount++; System.out.printf("Unique Puts = %s keyCount : Free Memory (MB) = %s\n", keyCount, runtime.freeMemory() / mb); }
  13. import javax.cache.Cache; import javax.cache.Caching; Cache<Integer, String> myCache = Caching.getCache("test"); //

    20 MB String value= new String(new char[10000000]); Runtime runtime = Runtime.getRuntime(); int keyCount = 0; int mb = 1024 * 1024; while (true) { myCache.put(keyCount, value); keyCount++; System.out.printf("Unique Puts = %s keyCount : Free Memory (MB) = %s\n", keyCount, runtime.freeMemory() / mb); }
  14. java.util.Map Key-Value Based API Supports Atomic Updates Entries Don’t Expire

    Entries Aren’t Evicted Entries Stored On-Heap Store-By-Reference javax.cache.Cache Key-Value Based API Supports Atomic Updates Entries May Expire Entries May Be Evicted Supports Observation (ie: Listeners) Supports Integration (ie: Loaders/Writers) Store-By-Value and Store-By-Reference Entry Processors Annotations Entries Stored Anywhere (ie: topologies) Statistics and Management
  15. public class MyCacheEntryListener implements CacheEntryCreatedListener<String, String> { public void onCreated(

    Iterable<CacheEntryEvent<String, String>> events) throws CacheEntryListenerException { for (CacheEntryEvent event : events) { log("Created : " + event.getKey() + " with value : " + event.getValue()); } } }
  16. Business Application Service Service Service RDBMS Mainframe MongoDB NoSQL REST

    Scaling JCACHE read through cache write through cache
  17. import javax.cache.integration.CacheLoader; import javax.cache.integration.CacheLoaderException; public class MyCacheLoader implements CacheLoader<String, String>

    { public String load(String key) throws CacheLoaderException { return getCapitalsDao().get(key); } public Map<String, String> loadAll(Iterable<? extends String> keys) throws CacheLoaderException { // Iterate the keys and maybe batch load from a DB, // a Filesystem or some other System completely. Map<String, String> result = new HashMap<>(); keys.forEach(key -> { result.put(key, getCapitalsDao().get(key)); }); return result; } ... }
  18. package javax.cache.integration; public interface CacheWriter<K, V> { void write(Cache.Entry<? extends

    K, ? extends V> entry) throws CacheWriterException; void writeAll(Collection<Cache.Entry<? extends K, ? extends V>> entries) throws CacheWriterException; void delete(Object key) throws CacheWriterException; void deleteAll(Collection<?> keys) throws CacheWriterException; }
  19. public class AppConfig { public static interface CityService { public

    String getCity(); } @Bean public CityService getService() { return new CityService() { @Override public String getCity() { // slow code goes here! return result; } }; } }
  20. import javax.cache.annotation.CacheResult; import org.springframework.cache.annotation.EnableCaching; @Configuration @EnableCaching public class AppConfig{ public

    static interface CityService { @CacheResult(cacheName = "city") public String getCity(); } @Bean public CityService getService() { return new CityService() { @Override public String getCity() { // slow code goes here! return result; } }; } }
  21. import javax.cache.annotation.CacheResult; import org.springframework.cache.annotation.EnableCaching; @Configuration @EnableCaching public class AppConfig{ public

    static interface CityService { @CacheResult(cacheName = "city") public String getCity(); } @Bean public CityService getService() { return new CityService() { @Override public String getCity() { // slow code goes here! return result; } }; } }
  22. JCache With Java EE • Java EE - Application can

    use JCache • Java EE 8 - JCache added to EE8 - Add JCache Annotations. Payara and TomEE provide support - Other integration possibilities: •ejb timer store •jbatch store •JPA
  23. Great for early stages of rapid application development and iteration

    and for OEM. Necessary for scale-up or scale-out deployments – decouples upgrading of clients and cluster for long term TCO Embedded Mode Node 1 Applications Java API Client-Server Mode Node 3 Java API Applications .Net API Applications C++ API Applications Node 2 Node 1 Node 2 Applications Java API Node 3 Applications Java API Topologies
  24. CachingProvider cachingProvider = Caching.getCachingProvider(); CacheManager cacheManager = cachingProvider.getCacheManager(); Cache<Object, Object>

    cache = cacheManager.getCache("test"); ICache<Object, Object> unwrappedCache = cache.unwrap(ICache.class);
  25. ICache<Integer, String> unwrappedCache = cache.unwrap(ICache.class); ICompletableFuture<String> future = unwrappedCache.getAndPutAsync(1, "value");

    future.andThen(new ExecutionCallback<String>() { public void onResponse(String response) { System.out.println("Previous value: " + response); } public void onFailure(Throwable t) { t.printStackTrace(); } });
  26. public static class CustomCacheMergePolicy implements CacheMergePolicy { @Override public Object

    merge(String cacheName, CacheEntryView mergingEntry, CacheEntryView existingEntry) { if (mergingEntry.getValue() instanceof Integer) { return mergingEntry.getValue(); } return null; } }
  27. ICache iCache1 = cache1.unwrap(ICache.class); iCache1.addPartitionLostListener(new CachePartitionLostListener() { @Override public void

    partitionLost(CachePartitionLostEvent cachePartitionLostEvent) { System.out.println(cachePartitionLostEvent); } });
  28. JCache 1.1 • CDDL GPL with Class Path Exception License

    to the spec API or UPL. • Errata • TCK Challenges • Very Close – should be Summer 2016
  29. JCache 2.0 • Enterprise Features - Transactions - Annotations Integration

    for EE - Servlet 4.0 Integration / Session Caching • Core - Java 8 - Java 9 Modularity - Async API - Distributed java.util.stream - Basic cache profile: - listener, -integration, - EntryProcessor.