-
Notifications
You must be signed in to change notification settings - Fork 275
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
Improve GetWritablePartitionIds Performance for PUT Requests #1197
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1197 +/- ##
=========================================
Coverage 83.62% 83.62%
Complexity 57 57
=========================================
Files 6 6
Lines 348 348
Branches 38 38
=========================================
Hits 291 291
Misses 45 45
Partials 12 12 Continue to review full report at Codecov.
|
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.
Will take a look at testing soon.
(Please format all the files)
List<PartitionId> partitionsInClass = getPartitionsInClass(partitionClass, true); | ||
|
||
int workingSize = partitionsInClass.size(); | ||
while(true) { |
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.
How about changing this to while (workingSize > 0)
and remove if-statement at line 424.
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.
fixed.
@@ -405,6 +406,42 @@ void updatePartitions(Collection<? extends PartitionId> allPartitions, String lo | |||
return healthyWritablePartitions.isEmpty() ? writablePartitions : healthyWritablePartitions; | |||
} | |||
|
|||
/** |
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.
minor: format this 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.
fixed.
if(partitionsToExclude == null || partitionsToExclude.size() == 0 || !partitionsToExclude.contains(selected)) { | ||
if (selected.getPartitionState() == PartitionState.READ_WRITE) { | ||
anyWritablePartition = selected; | ||
if(areAllReplicasForPartitionUp(selected)) { |
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 remember during offline discussion, you even proposed to only check if local replicas are up. Will we try that in the future PR?
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.
fixed,
* getWritablePartitionIds. | ||
* @param partitionClass the partition class whose writable partitions are required. Can be {@code null} | ||
* @param partitionsToExclude A list of partitions that should be excluded from consideration. | ||
* @return A writable parition id object. Can be {@code null} |
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.
minor: typo in partition
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.
fixed.
public PartitionId getRandomWritablePartition(String partitionClass, List<PartitionId> partitionsToExclude) { | ||
List<? extends PartitionId> partitions = getWritablePartitionIds(partitionClass); | ||
partitions.removeAll(partitionsToExclude); | ||
return partitions.isEmpty()?null:partitions.get(ThreadLocalRandom.current().nextInt(partitions.size())); |
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.
minor: format this 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.
fixed. I am assuming that you meant formatting for line 128.
ambry-clustermap/src/main/java/com.github.ambry.clustermap/ClusterMapUtils.java
Show resolved
Hide resolved
ambry-clustermap/src/main/java/com.github.ambry.clustermap/ClusterMapUtils.java
Outdated
Show resolved
Hide resolved
ambry-clustermap/src/main/java/com.github.ambry.clustermap/CompositeClusterManager.java
Show resolved
Hide resolved
assertCollectionEquals("Partitions returned not as expected", expectedReturnForClassBeingTested, | ||
psh.getWritablePartitions(classBeingTested)); | ||
assertInCollection("Partitions returned not as expected", allPartitionIds, |
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 message should be Random partition returned not as expected
if you want to make it consistent in this test.
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.
fixed.
assertInCollection("Partitions returned not as expected", allPartitionIds, | ||
psh.getRandomWritablePartition(null, null)); | ||
assertNull("Partitions returned not as expected", | ||
psh.getRandomWritablePartition(classBeingTested, null)); |
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.
This method contains some duplicated assertions. For example: line241-248, line255-262, line268-275 and line289-296. How about moving them to a separate method and simplify this test?
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.
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.
fixed.
@ankagrawal Looks like we need to fix failure in |
Yeah.. this change for local DC was work in progress. I forgot that push to a branch generates a new review. Sorry about that. |
…t latency by not iterating through all the partitions. Add a method getRandomWritablePartition to ClusterMap and add its implementation to HelixClusterManager, StaticClusterManager and CompositeClusterManager.
Improve get random partition logic
3089002
to
7d3c702
Compare
The new tests have passed without any changes. I guess this was an intermitted issue. We should keep an eye if this listenCrossColo test fails again, and root-cause this. |
List<PartitionId> partitionsInClass = getPartitionsInClass(partitionClass, true); | ||
|
||
int workingSize = partitionsInClass.size(); | ||
while(workingSize > 0) { |
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.
Looks like formatting is still off. Should have space between while/if and (
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.
fixed all the formatting errors.
anyWritablePartition = selected; | ||
if(areAllLocalReplicasForPartitionUp(selected, localDatacenterName)) { | ||
selectedPartition = selected; | ||
break; |
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't we just return selected here?
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.
fixed.
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.
Mostly looks good to me. One minor comment regarding improvement on checking state of local replicas.
logger.debug("Replica [{}] on {} {} is down", replica.getPartitionId().toPathString(), | ||
replica.getDataNodeId().getHostname(), replica.getMountPath()); | ||
return false; | ||
} |
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 think you can maintain a Map inside PartitionSelectionHelper
, which will be populated during initialization. The Map keeps each partition and a list of its local replicas, i.e Map<PartitionId, List<ReplicaId>>
.
The benefit is, when this method is called, it only needs to check 3 replicas directly rather than 12 replicas in worst case.
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.
@ankagrawal, did you want to make this change or should I merge the PR?
For each PUT request, instead of looping through all the partitions, and instead of checking replica states of all the partitions before selecting a random partition for put; this change gets a partition at random, and then checks if it is writable and if it’s replicas are available. The motivation for this change is present at https://docs.google.com/document/d/1DWXlUD1fxYkvVekl6tNFsxA7l_eaQrhb6-ht1rIb4G0/edit?ts=5d0ab0d1#
NOTE: For CompositeClusterManager, we need metrics for comparing HelixClusterManager state and StaticClusterManager state. Since the CompositeClusterManager is used only during migrations, this change trades-off PUT latency during migration for the additional metrics. Hence, for HelixClusterManager, getting a writable partition for PUT involves getting all the partitions and checking each partition's replica state, before selecting a writable partition at random.