Skip to content

Add Caffeine cache layer extension#2417

Closed
drcrallen wants to merge 1 commit intoapache:masterfrom
metamx:caffeineCache
Closed

Add Caffeine cache layer extension#2417
drcrallen wants to merge 1 commit intoapache:masterfrom
metamx:caffeineCache

Conversation

@drcrallen
Copy link
Copy Markdown
Contributor

Tests are all based on #1937

TODO:

  • Reconcile requirement for java8
  • Add some kind of docs (either in extension README.md or in main cache readme)

@drcrallen
Copy link
Copy Markdown
Contributor Author

The MapCache concurrency problems are a pain ( see #1836 ). Having a "local" cache that can be nice and performant would be awesome.

@drcrallen
Copy link
Copy Markdown
Contributor Author

This will fail under java7 tests as

/Users/charlesallen/src/druid/extensions/caffeine-cache/src/main/java/io/druid/client/cache/CaffeineCache.java:[52,61] cannot access java.util.function.Supplier
  class file for java.util.function.Supplier not found

{
private static final Logger log = new Logger(CaffeineCache.class);
private final Cache<String, byte[]> cache;
private final AtomicReference<com.github.benmanes.caffeine.cache.stats.CacheStats> priorStats = new AtomicReference<>(
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would put this extension under client.cache.caffeine so that the package types don't take precedence. Then Droid's CacheStats could be fully qualified in only getStats() and the overall verbosity reduced.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@b-slim
Copy link
Copy Markdown
Contributor

b-slim commented Feb 9, 2016

@drcrallen are we sure that this will fix the locking problems ? if yes can you explain or share some benchmarks ?

@drcrallen
Copy link
Copy Markdown
Contributor Author

@b-slim I have a high degree of confidence this will fix locking issues, but almost zero information on if this offers better latency than the guava cache. Luckily it is in an extension so it is completely optional.

I want to get numbers aside from the general Caffeine benchmarks on the matter, but will not be able to immediately.

@drcrallen
Copy link
Copy Markdown
Contributor Author

@ben-manes One thing I could find a good way to handle was "namespace"s

Does caffeine have any way to use a global retention rule, but divide the keys up into namespaces?

@ben-manes
Copy link
Copy Markdown

No, but it might be possible to build something like that on top. It is a little vague of what that means and how generally useful it is. I've seen it discussed in contexts of other caches, but it was never requested for Guava's.

Namespaces used to be asked for a lot back in memcached's heyday. Most of the time it was to invalidate a bunch of keys together which were inter-related. The solution was to use generational caching (a version number as part of the key) and increment the generation when the data store was updated. That relied on the cache to lazily evict the old keys which wouldn't be used anymore.

Alternatively you could build indexes and rely on locking since this is part of the same process. A CacheWriter could be useful to make insertion / eviction atomic with a separate multimap (namespace to keys).

If namespaces are to make regions to have sub and global thresholds, this is even messier. That's usually to share a cluster of memcached and perform resource accounting (e.g. Google's internal rewrite did this) or have an automatic cache sizing. The former makes no sense here, the latter is very messy in Java where GC masks sizes. Attempts to do it automatically (soft references, heap monitoring, etc) don't work well. Its better to be explicit and move large scale caching outside of the JVM (off-heap, memcached, etc).

So messy and confusing from my side of the fence. I think the useful hooks are exposed for a custom job, though.

@drcrallen
Copy link
Copy Markdown
Contributor Author

@ben-manes the big thing for use in druid is that the data queries have the underlying data segment as part of the cache key. As such, if the segment is no longer present on a node (in the case of using local cache) then that node will no longer receive queries for that segment, so any sort of LRU-like eviction policy should favor destroying those no-longer-used keys.

The current methodology in this PR is similar to the generational approach you described, but the existing cache keys are scanned and invalidated in a best-effort manner. It could just fall back to lazy eviction if performance is a concern for actively scanning the keys.

@drcrallen
Copy link
Copy Markdown
Contributor Author

Thanks for the insight.

@ben-manes
Copy link
Copy Markdown

If you know when a segment is no longer present then you could maintain an index as described above. Then when the segment is dropped you invalidate all of the associated keys. This could be done racy (depending on eviction to cleanup) or atomically (a bit of locking) depending on your preference. The atomic approach might use a CacheWriter (synchronous) or RemovalListener (asynchronous). The complexity to do it "correctly" and discard data proactively may not turn into a performance win, though.

@fjy
Copy link
Copy Markdown
Contributor

fjy commented Feb 11, 2016

This has transient failures in the new UT. Please please try to reduce transient failures.

@drcrallen
Copy link
Copy Markdown
Contributor Author

@fjy failures in java7 UT are not transient. See master comment

@gianm
Copy link
Copy Markdown
Contributor

gianm commented Feb 17, 2016

@drcrallen IMO the best way to resolve the java7 thing is to have this not be in the druid repo, but be in a different repo and be labeled as requiring java8.

@drcrallen
Copy link
Copy Markdown
Contributor Author

I have moved this over to https://github.com/metamx/druid-cache-caffeine since it requires java8

@drcrallen drcrallen closed this Feb 19, 2016
@drcrallen drcrallen deleted the caffeineCache branch February 19, 2016 01:49
@binlijin
Copy link
Copy Markdown
Contributor

👍

seoeun25 pushed a commit to seoeun25/incubator-druid that referenced this pull request Jan 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants