STORM-2204 Adding caching capabilities in HBaseLookupBolt#1783
STORM-2204 Adding caching capabilities in HBaseLookupBolt#1783ambud wants to merge 8 commits intoapache:masterfrom ambud:master
Conversation
revans2
left a comment
There was a problem hiding this comment.
I like the idea. I realize that everything seems to revolve around the guava cache, although there are alternatives to it, and I would prefer that we use one of the alternatives that has less issues with backwards compatibility.
| @@ -1,92 +1,92 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
There was a problem hiding this comment.
Could you please revert the spacing back to how it was before? Almost every single line changed for what appears to be no reason.
There was a problem hiding this comment.
That's happened because of my IDE. I would recommend adding the POM-Sort plugin to make sure this is auto fixed when the build runs.
I took a crack at that a few months ago: https://github.com/srotya/srotya-parent/blob/master/pom.xml
| <groupId>org.apache.storm</groupId> | ||
| <version>2.0.0-SNAPSHOT</version> | ||
| <relativePath>../../pom.xml</relativePath> | ||
| </parent> |
There was a problem hiding this comment.
Why remove the parent? This allows us to keep a lot of dependency versions in sync so we have more confidence that there are not version conflicts when someone has a topology that includes multiple different sub-pieces
There was a problem hiding this comment.
Parent is still there; I believe that is formatting from the IDE causing this.
external/storm-hbase/pom.xml
Outdated
|
|
||
| <artifactId>storm-hbase</artifactId> | ||
| <properties> | ||
| <hbase.version>1.1.0</hbase.version> |
There was a problem hiding this comment.
The version of hbase should be coming from the parent pom, not being set here. Like I said in the previous comment, we want the parent pom to keep the dependency versions in sync between all of the sub projects.
There was a problem hiding this comment.
Oh wait never mind I just saw this was brought over from the original code. You can leave it, but it would still be nice to fix.
external/storm-hbase/pom.xml
Outdated
| <dependency> | ||
| <groupId>com.google.guava</groupId> | ||
| <artifactId>guava</artifactId> | ||
| <version>20.0</version> |
There was a problem hiding this comment.
We really should be using the version of guava in the parent pom. And guava always bites people (they really don't like to maintain compatibility) so if we can avoid using it, I would really prefer to do that.
There was a problem hiding this comment.
Agree with the backwards, what are your thoughts on alternatives.
There was a problem hiding this comment.
I have not really used too many alternatives, So I did a search
https://duckduckgo.com/?q=guava+cache+alternatives&t=ffab&ia=qa
Both https://cache2k.org/ and http://www.ehcache.org/ look interesting, but I have not actually used any of them
|
|
||
| protected OutputCollector collector; | ||
|
|
||
| protected transient OutputCollector collector; |
There was a problem hiding this comment.
Why is this transient? I don't see us accessing it from multiple threads, and especially not changing it on multiple threads?
There was a problem hiding this comment.
Transient is for serializability errors, I am not sure why it didn't error out in earlier when people tried to use this code.
Since Storm serializes the Bolt code for deployment this should be marked as transient.
There was a problem hiding this comment.
You are right I got confused by the two. Thanks for pointing that out :)
| private HBaseValueMapper rowToTupleMapper; | ||
| private HBaseProjectionCriteria projectionCriteria; | ||
| private transient LoadingCache<byte[], Result> cache; | ||
| private transient boolean cacheEnabled; |
There was a problem hiding this comment.
Why are these transient? The bolt is not multi-threaded.
There was a problem hiding this comment.
Transient is for serializability, not to be confused with volatile.
| @@ -40,51 +48,85 @@ | |||
| * | |||
| */ | |||
| public class HBaseLookupBolt extends AbstractHBaseBolt { | |||
There was a problem hiding this comment.
Please don't use tab characters for indentation. We are still working on the exact style guides, but we try to keep the style that is currently in the file and it was using spaces before and I expect the style guide to include spaces instead of tabs.
There was a problem hiding this comment.
Moved to spaces, if this is still a blocked; I will try to reapply the patch to the original file and then update the commits.
| this.collector.reportError(e); | ||
| this.collector.fail(tuple); | ||
| } | ||
| } |
There was a problem hiding this comment.
There appears to be a lot of overlap in the code here, between the cache version and the non-cache version. It would really be nice to at least combine most of this. Alternatively we might want to use inheritance in some way to avoid the branching on the cacheEnabled config at all.
… managed dependency
|
Overall it looks fine to me now. I am still a bit concerned about guava as a dependency, but beyond that it seems like a great addition to the bolt. |
|
I agree it's still better to not relying on Guava since storm-core is shading Guava but external modules are not. @ben-manes I guess you're the author of Caffeine. Could you introduce Caffeine? |
|
Forgot to comment for other side. It looks great. |
|
I was a co-author of Guava's cache, too. Guava had originally considered soft references an ideal caching scheme, since they offer great concurrency and GC is for memory management. That evolved from Java 8 provided an excuse to start from scratch. Caffeine is much faster and packs in even more features. I also spent time exploring eviction policies, which led to co-authoring a paper on a new technique called TinyLFU. That has a near optimal hit rate, low memory footprint, and amortized O(1) overhead. This is done by tracking frequency in a popularity sketch. The same concurrency model in CLHM and Guava is used (inspired by a write-ahead log), which allows for concurrent O(1) reads and writes. The HighScalability article provides an overview of the algorithms that I use. |
|
Overall looks good to me. My major concern is that on-heap caches(like Guava cache, Ehcache) might cause bad GC situations. I didn't use Caffeine in the past, maybe is a candidate. |
|
Caffeine sounds like a great alternative to Guava and also seems to address some GC concerns. @vesense I agree storing any large amount of data on heap will impact GC, we do that all the time with all of the queues that we have. I think for the most part as long as GC is tuned properly for the topology, we don't get a lot of full GCs causing promotion in the cache, and TTL in the cache is not too long it will be fine. If we do run into serious GC issues we can then look at off heap cacheing. |
|
@revans2 Yes, we can find a balance between high rate of cache hits and full GCs. I'm OK for adding a built-in cache if we set parameters carefully. |
|
@vesense it is off by default so it would be enabled/tuned on a per topology basis. |
|
@revans2 @vesense @ben-manes Thanks for the valuable feedback, I am looking into integration with Caffeine. Should have a new commit soon. @revans2 Indeed the intention is to have the cache tuned based on topology. The ideal use case is where caching actually makes sense and certain keys may have a higher hit frequency then others. Ideally this bolt should be used with FieldGrouping when caching is enabled so cache misses minimal. Something to be kept in mind is distribution of keys (executor balancing). |
|
+1 |
| @Override | ||
| public Result load(byte[] rowKey) throws Exception { | ||
| Get get = hBaseClient.constructGetRequests(rowKey, projectionCriteria); | ||
| LOG.debug("Cache miss for key:"+new String(rowKey)); |
There was a problem hiding this comment.
@ambud
It would be better to use Cache miss for key: {} instead of +. After fixing this, you can squash commits into one.
|
One thing to consider is that Caffeine seems to require Java 8, which means that this patch can't be shipped to 1.x version line. Do we want to keep using Guava for 1.x branch? |
|
Nope. Sorry, since your compilation target is 1.8 I hadn't thought you'd need that. |
|
So should I revert back my changes; seems like the build is currently failing; additional tests pushed by upstream? |
|
@revans2 What do you think about this? I'm in favor of adopting Caffeine, and I'm even OK to use Caffeine to master and Guava to 1.x. |
|
@HeartSaVioR I also am find with Caffeine and even Caffeine on 1.x (assuming it is off by default) |
|
+1 the code looks fine to me. |
|
@ambud Two things more to address:
Thanks in advance! |
|
Should fail, e.g. Class version error. |
|
+1, but I agree with @HeartSaVioR that the new cache configuration options need to be documented before this is merged. |
Adding configuration docs to README
|
Added documentation to readme file. Fixed the debug logging by using isDebugEnabled checks Are we going to use Guava caching implementation for 1.x? @HeartSaVioR @revans2 |
|
@ambud I'm OK to use Guava for 1.x. IMHO it would be better to provide complete set of features for guaranteed environment (JDK version) instead of leaving 'warn' to documentation. |
|
Caffeine is JDK 8 only so won't work for 1.x, since JDK 7 compilation will be tested. |
|
@ambud |
|
Sure thing, I will add the Guava patch code originally added for this to 1.x and 0.10.x branches |
|
+1 for merging to master after updating |
|
I guess guava is OK for 1.x. I would prefer to see it shaded if we do go with Guava, but I am only a -0 if it is not shaded. |
|
OK. Since we have other modules which depends on Guava, it might be better to have a rule and apply all of them. +1 to shade Guava on external modules if possible. |
|
Can we merge this? @HeartSaVioR @revans2 @vesense I will need to open another pull request for 1.x branch. |
|
1.x branch PR #1810 |
|
Can we merge this @revans2 @HeartSaVioR @vesense ? |
|
@ambud Sorry for the delay response. Before we merge this in, can you replace all the tab space to white space? |
|
Done @vesense |
|
Thanks @ambud Squashed and merged into master. And I added you as the contributor. |
|
Thank you @vesense. Could we merge the 1.x pull request as well? |
|
@ambud I'll wait for other committers to vote for it before merging into 1.x-branch. And this may take some time. |
https://issues.apache.org/jira/browse/STORM-2204