-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HBASE-24459 Move the locateMeta logic from AsyncMetaRegionTableLocato… #2095
HBASE-24459 Move the locateMeta logic from AsyncMetaRegionTableLocato… #2095
Conversation
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
db19115
to
ef5b91b
Compare
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left few comments, nice patch.
hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java
Show resolved
Hide resolved
hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistry.java
Outdated
Show resolved
Hide resolved
public static CompletableFuture<List<HRegionLocation>> getAllMetaRegionLocations( | ||
boolean excludeOfflinedSplitParents, | ||
CompletableFuture<ClientMetaService.Interface> getStubFuture, | ||
AtomicReference<ClientMetaService.Interface> stubRef, | ||
RpcControllerFactory rpcControllerFactory, int callTimeoutMs) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to above methods, we can use generics here also:
public static <T extends ClientMetaService.Interface> CompletableFuture<List<HRegionLocation>> getAllMetaRegionLocations(
boolean excludeOfflinedSplitParents, CompletableFuture<T> getStubFuture,
AtomicReference<T> stubRef, RpcControllerFactory rpcControllerFactory, int callTimeoutMs) {
&
public static<T extends ClientMetaService.Interface> void tryClearMasterStubCache(IOException error,
T currentStub, AtomicReference<T> stub) {
Being Utils class, this might suit well, thought?
But if you feel this is overkill, we are good without that change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class is IA.Private so I think we could do this later when we really have the requirement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, that is fine.
hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java
Show resolved
Hide resolved
hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
Outdated
Show resolved
Hide resolved
hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
Outdated
Show resolved
Hide resolved
hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
Outdated
Show resolved
Hide resolved
hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
Show resolved
Hide resolved
hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
Show resolved
Hide resolved
hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaLocationCache.java
Outdated
Show resolved
Hide resolved
hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestMetaRegionLocationCache.java
Show resolved
Hide resolved
hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionRegistry.java
Show resolved
Hide resolved
hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistry.java
Show resolved
Hide resolved
hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistry.java
Outdated
Show resolved
Hide resolved
Function<RpcChannel, T> stubMaker, String type) { | ||
return getOrFetch(stub, stubMakeFuture, () -> { | ||
CompletableFuture<T> future = new CompletableFuture<>(); | ||
addListener(registry.getActiveMaster(), (addr, error) -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I liked @saintstack's idea in the design doc where we can ask active master for the list of available masters and load balance the RPCs. I think that can be used both here (to randomize the master we are talking to) and in master registry to always maintain a fresh list of masters and only use the initial list of masters a seed input.
(I can quickly add that feature if everyone is okay with it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. Can file another issue for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
try { | ||
if (cache != null) { | ||
locs = cache.locateMeta(HConstants.EMPTY_BYTE_ARRAY, RegionLocateType.CURRENT); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need the else part? It looks like the cache runs on all masters ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The design is when master becomes active, we will serve the requests by the local master region dreictly, so we will set cache to null after we successfully initialize the master local region. This is important as backup masters will also use the getAllMetaRegionLocations method to sync from active master.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah got it, I missed that part in the first iteration, I think you could roll that logic into the cache to keep the lifecycle simple (since the cache already has access to the master and we can check if master.isActive()). That way all the callers only use the cache and we can avoid the logic in finishMasterInitialization logic.
Also as discussed in the design doc, would be nice to have an actual versioned cache that avoids round trips if nothing changes (for the future). The 1s pull seems a bit aggressive but is fine as a stop-gap I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, will try to do this as a follow on. Maybe need to introduce another method for doing this, as the return value should have a way tell the upper layer there is no change, and also we should not have the excludeOfflineSplitParent option for this method, otherwise the semantice will be confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And on the cache stuff, at least we need to stop the chore after switching to active master? And for active master, we will not get from cache any more, still using the cache will be a bit confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Serving from NavigableMap should be faster than fetch from local Region? For this reason would we want to do like @bharathv suggests (can be follow-on)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What @bharathv mean is we can reuse the cache interface to simpilify the code, not for performance. After switching to active master we should serve the requests with local region, as we do not want to keep a cache at active master which could be stale?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was talking performance. Why would a cache on active Region be stale? Why would it not be updated on write the Region?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now the cache is running as a side logic besides the core. Making it always sync with the local region will mess up the code when updating local region, especially that the local region is not for storing root. Since we could also set the family to in memory, I do not think the performance will be much better so I do not think it is worth to also introduce a cache for active master. No big gain but the code will be much complicated.
hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaLocationCache.java
Outdated
Show resolved
Hide resolved
|
||
@Override | ||
protected void chore() { | ||
AsyncClusterConnection conn = master.getAsyncClusterConnection(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: conn reference can be cached once
hbase-server/src/main/java/org/apache/hadoop/hbase/master/MetaLocationCache.java
Show resolved
Hide resolved
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few comments, core logic seems good enough.
public static final HBaseClassTestRule CLASS_RULE = | ||
HBaseClassTestRule.forClass(TestMetaFixerNoCluster.class); | ||
|
||
private static Configuration CONF = HBaseConfiguration.create(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: final ?
hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMetaLocationCache.java
Outdated
Show resolved
Hide resolved
import org.junit.Test; | ||
import org.junit.experimental.categories.Category; | ||
|
||
@Category({ MasterTests.class, MediumTests.class }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are dealing with Mocks only, this can be SmallTests
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, we have sleep in the tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, MediumTests
is fine since we have sleep.
|
||
private static Configuration CONF = HBaseConfiguration.create(); | ||
|
||
private static ChoreService CHORE_SERVICE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: we can assign value right here and keep this static final
|
||
private static ChoreService CHORE_SERVICE; | ||
|
||
private static byte[] SPLIT = Bytes.toBytes("a"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: final
if (conn != null) { | ||
addListener(conn.getAllMetaRegionLocations(fetchTimeoutMs), (locs, error) -> { | ||
if (error != null) { | ||
LOG.warn("Failed to fetch all meta region locations from active master", error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOG.error
might fit well? Also, what if this chore keeps getting error multiple times? That could mean due to some issue with RPC call, backup masters will serve stale data? Should we rather make this a high priority issue and stop backup masters if we get error say 30-60 times in a consecutive manner?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be a follow on I think. Agree that if active master is down for a long time, we should avoid flooding the log file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we can take it up on follow-up Jira.
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
patch seems fine to me pending one suggestion to refactor the if else logic around cache (if thats acceptable to you).
try { | ||
if (cache != null) { | ||
locs = cache.locateMeta(HConstants.EMPTY_BYTE_ARRAY, RegionLocateType.CURRENT); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah got it, I missed that part in the first iteration, I think you could roll that logic into the cache to keep the lifecycle simple (since the cache already has access to the master and we can check if master.isActive()). That way all the callers only use the cache and we can avoid the logic in finishMasterInitialization logic.
Also as discussed in the design doc, would be nice to have an actual versioned cache that avoids round trips if nothing changes (for the future). The 1s pull seems a bit aggressive but is fine as a stop-gap I guess.
💔 -1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
9cb6635
to
f249b0b
Compare
…r to ConnectionRegistry
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
💔 -1 overall
This message was automatically generated. |
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry (#2095) Signed-off-by: Viraj Jasani <[email protected]> Signed-off-by: Bharath Vissapragada <[email protected]>
…r to ConnectionRegistry