-
Notifications
You must be signed in to change notification settings - Fork 25.6k
[Zen2] Move ClusterState fields to be persisted to ClusterState.MetaData #35625
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
Conversation
|
Pinging @elastic/es-distributed |
DaveCTurner
left a comment
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 good. It is a little sad that building these cluster states gets so much more verbose in places, and there's a few places where I'm not sure we're using the builders quite right yet. I left a selection of small comments/requests.
| resolvedNodes = resolveNodesAndCheckMaximum(request, currentState); | ||
|
|
||
| final Builder builder = ClusterState.builder(currentState); | ||
| CoordinationMetaData.Builder builder = CoordinationMetaData.builder(currentState.coordinationMetaData()); |
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.
For consistency, could this be final please?
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.
|
|
||
| public VotingConfiguration getLastAcceptedConfiguration() { | ||
| return lastAcceptedConfiguration; | ||
| public CoordinationMetaData.VotingConfiguration getLastAcceptedConfiguration() { |
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 we could just import VotingConfiguration rather than qualifying it like this.
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.
| setLastAcceptedState(ClusterState.builder(lastAcceptedState) | ||
| .lastCommittedConfiguration(lastAcceptedState.getLastAcceptedConfiguration()) | ||
| .build()); | ||
| final CoordinationMetaData cmd = CoordinationMetaData.builder(lastAcceptedState.coordinationMetaData()) |
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: cmd reads as "command" to me. Could we just give it the full type name coordinationMetaData?
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.
| builder.lastAcceptedConfiguration(votingConfiguration); | ||
| builder.lastCommittedConfiguration(votingConfiguration); | ||
| final CoordinationMetaData coordinationMetaData = CoordinationMetaData.builder() | ||
| .term(currentState.term()) |
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.
currentState.term() is 0 here, so I think this isn't required. But I also wonder if it'd be better to say CoordinationMetaData.builder(currentState.coordinationMetaData()) in the line above to be clear that we're updating the existing metadata rather than starting afresh.
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.
| return builder(currentState) | ||
| .lastAcceptedConfiguration(votingConfiguration) | ||
| .lastCommittedConfiguration(votingConfiguration).build(); | ||
| .metaData(MetaData.builder() |
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 discards the metadata in the cluster state (except it copies the coordination metadata over)
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.
| new ClusterState.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false)))); | ||
| metaBuilder.lastAcceptedConfiguration( | ||
| new CoordinationMetaData.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, 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.
Oops I missed the voting tombstones here. Could you add one?
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.
| private ClusterState.Builder randomVotingConfiguration(ClusterState clusterState) { | ||
| private ClusterState.Builder randomCoordinationMetaData(ClusterState clusterState) { | ||
| ClusterState.Builder builder = ClusterState.builder(clusterState); | ||
| CoordinationMetaData.Builder metaBuilder = CoordinationMetaData.builder(); |
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.
You need to put this builder into the other builder, otherwise it's just discarded.
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.
| } | ||
| } | ||
| clusterState = builder.incrementVersion().term(randomLong()).build(); | ||
| clusterState = builder.incrementVersion().build(); |
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 test asserts that various parts of the coordination metadata are equal. I think it should now just assert that the whole thing is equal.
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.
| if (in.getVersion().onOrAfter(Version.V_7_0_0)) { | ||
| coordinationMetaData = new CoordinationMetaData(in); | ||
| } else { | ||
| coordinationMetaData = CoordinationMetaData.EMPTY_META_DATA; |
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.
Depending on how we plan to do rolling upgrades, this may or may not be safe, and might need backporting. We're not sure yet. Could you leave a // TODO check that this is safe here so we know to revisit it later 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.
|
Ah yes and there's another place where we assert the literal JSON representation of the cluster state: |
|
@DaveCTurner thanks for the diligent review! I've made changes that you're asking for. Ready for the next pass. |
DaveCTurner
left a comment
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.
LGTM, I left three further suggestions.
However I am not too sure about XContent parsing so would like @ywelsch to look over that part specifically.
| return (long)termAndConfigs[0]; | ||
| } | ||
|
|
||
| private static VotingConfiguration lastCommittedConfig(Object[] termAndConfig) { |
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.
Could you add @SuppressWarnings("unchecked") to this method?
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.
| return new VotingConfiguration(new HashSet<>(nodeIds)); | ||
| } | ||
|
|
||
| private static VotingConfiguration lastAcceptedConfig(Object[] termAndConfig) { |
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.
Could you add @SuppressWarnings("unchecked") to this method?
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.
|
|
||
| public CoordinationMetaData build() { | ||
| return new CoordinationMetaData(term, lastCommittedConfiguration, lastAcceptedConfiguration, | ||
| Collections.unmodifiableSet(new HashSet<>(votingTombstones))); |
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 that I see all this in one place, I see that in VotingConfiguration we copy the set and wrap it in Collections.unmodifiableSet in the constructor whereas here I did it in the builder. Could you move it to within the constructor like with VotingConfiguration?
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'm done with the changes. Waiting for @ywelsch to take a look at |
ywelsch
left a comment
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've left some smaller comments. I would like for this PR to implement toXContent/fromXContent for the voting tombstones as well.
server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java
Show resolved
Hide resolved
|
|
||
| @Override | ||
| public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
| return builder |
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 you add an example to the PR description how the new toXContent will look like?
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.
Done
server/src/main/java/org/elasticsearch/cluster/coordination/CoordinationMetaData.java
Outdated
Show resolved
Hide resolved
server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java
Outdated
Show resolved
Hide resolved
...ava/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java
Outdated
Show resolved
Hide resolved
ywelsch
left a comment
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.
LGTM
Today we have a way to atomically persist global
MetaDataandIndexMetaDatato disk when newClusterStateis received. All otherClusterStatefields are not persisted.However, there are other parts of
ClusterStatethat should bepersisted, namely:
versionis changed frequently, other fields are not. We decidedto group
term,lastCommittedConfiguration,lastAcceptedConfigurationandvotingTombstonesintoCoordinationMetaDataclass and makeCoordinationMetaDataa fieldinside
MetaData.MetaData.toXContentandMetaData.fromXContentshould take care ofCoordinationMetaData.versionstays as a top level field inClusterStateand will bepersisted as part of
Manifestin a follow-up PR.Also
MetaData.isGlobalStateEqualsshould be extended to includecoordinationMetaDatain comparison.This PR favors to expose getters, such as
getTermdirectly inClusterStateto avoid massive code changes.An example of CoordinationMetaState.toXContent: