Skip to content
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

Merged
merged 9 commits into from
Jul 8, 2019

Conversation

ankagrawal
Copy link
Collaborator

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.

@codecov-io
Copy link

codecov-io commented Jun 19, 2019

Codecov Report

Merging #1197 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@            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.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 367c57c...2e4e1cb. Read the comment docs.

Copy link
Contributor

@jsjtzyy jsjtzyy left a 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) {
Copy link
Contributor

@jsjtzyy jsjtzyy Jun 21, 2019

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.

Copy link
Collaborator Author

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;
}

/**
Copy link
Contributor

Choose a reason for hiding this comment

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

minor: format this file

Copy link
Collaborator Author

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)) {
Copy link
Contributor

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?

Copy link
Collaborator Author

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}
Copy link
Contributor

Choose a reason for hiding this comment

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

minor: typo in partition

Copy link
Collaborator Author

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()));
Copy link
Contributor

Choose a reason for hiding this comment

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

minor: format this file

Copy link
Collaborator Author

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.

assertCollectionEquals("Partitions returned not as expected", expectedReturnForClassBeingTested,
psh.getWritablePartitions(classBeingTested));
assertInCollection("Partitions returned not as expected", allPartitionIds,
Copy link
Contributor

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.

Copy link
Collaborator Author

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));
Copy link
Contributor

@jsjtzyy jsjtzyy Jun 21, 2019

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?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

sure.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed.

@jsjtzyy
Copy link
Contributor

jsjtzyy commented Jun 24, 2019

@ankagrawal Looks like we need to fix failure in listenCrossColoTest with new changes.

@ankagrawal
Copy link
Collaborator Author

@ankagrawal Looks like we need to fix failure in listenCrossColoTest with new changes.

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
@ankagrawal ankagrawal force-pushed the FixGetwritablePatitionId branch from 3089002 to 7d3c702 Compare June 25, 2019 17:59
@ankagrawal
Copy link
Collaborator Author

@ankagrawal Looks like we need to fix failure in listenCrossColoTest with new changes.

Yeah.. this change for local DC was work in progress. I forgot that push to a branch generates a new review. Sorry about that.

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.

@ankagrawal ankagrawal closed this Jun 25, 2019
@ankagrawal ankagrawal reopened this Jun 25, 2019
List<PartitionId> partitionsInClass = getPartitionsInClass(partitionClass, true);

int workingSize = partitionsInClass.size();
while(workingSize > 0) {
Copy link
Contributor

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 (

Copy link
Collaborator Author

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;
Copy link
Contributor

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?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed.

Copy link
Contributor

@jsjtzyy jsjtzyy left a 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;
}
Copy link
Contributor

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.

Copy link
Contributor

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?

@jsjtzyy jsjtzyy merged commit a24244c into linkedin:master Jul 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants