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

refactor(storage): maintain sub_level id order #18915

Closed
wants to merge 12 commits into from

Conversation

zwang28
Copy link
Contributor

@zwang28 zwang28 commented Oct 15, 2024

I hereby agree to the terms of the RisingWave Labs, Inc. Contributor License Agreement.

What's changed and what's your intention?

This PR reverts #18886, then resolves the same issue by maintaining a new field max_sub_level_id in HummockVersion.
It has advantage of keeping the non-decreasing order of sub_level_id, in contrast to #18886.

Checklist

  • I have written necessary rustdoc comments
  • I have added necessary unit tests and integration tests
  • I have added test labels as necessary. See details.
  • I have added fuzzing tests or opened an issue to track them. (Optional, recommended for new SQL features Sqlsmith: Sql feature generation #7934).
  • My PR contains breaking changes. (If it deprecates some features, please create a tracking issue to remove them in the future).
  • All checks passed in ./risedev check (or alias, ./risedev c)
  • My PR changes performance-critical code. (Please run macro/micro-benchmarks and show the results.)
  • My PR contains critical fixes that are necessary to be merged into the latest release. (Please check out the details)

Documentation

  • My PR needs documentation updates. (Please use the Release note section below to summarize the impact on users)

Release note

If this PR includes changes that directly affect users or other significant modifications relevant to the community, kindly draft a release note to provide a concise summary of these changes. Please prioritize highlighting the impact these changes will have on users.

@zwang28 zwang28 requested review from Li0k and wenym1 October 15, 2024 06:07
@zwang28 zwang28 marked this pull request as ready for review October 15, 2024 06:07
.latest_version()
.max_sub_level_id
.map(|id| id + 1)
.unwrap_or(FIRST_SUB_LEVEL_ID),
Copy link
Collaborator

Choose a reason for hiding this comment

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

To be backward compatible, should we init the max_sub_level_id on meta startup to be the actual max sub-level id and we use the max_sub_level_id field only for the new sublevel's id?

Copy link
Contributor Author

@zwang28 zwang28 Oct 15, 2024

Choose a reason for hiding this comment

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

To be backward compatible, should we init the max_sub_level_id on meta startup

This has been done in src/storage/hummock_sdk/src/version.rs

Copy link
Contributor Author

@zwang28 zwang28 Oct 15, 2024

Choose a reason for hiding this comment

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

Therefore, reaching line 169 indicates that the version is indeed a fresh new one.

Alternatively we can make the in-mem HummockVersion:: max_sub_level_id u64 directly instead of Option<64>, in order to avoid such unwrap_or whenever reading max_sub_level_id.

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 it's ok for now, the newly introduced fields keep the Option restrictions.

When line 169 is reached, the sub_level will no longer exist in the compaciton group, so it is correct to use FIRST_SUB_LEVEL_ID for initialisation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we use the max_sub_level_id field only for the new sublevel's id

True, it's a bug. Thanks.

@@ -764,6 +759,14 @@ impl HummockVersion {
&version_delta.state_table_info_delta,
&changed_table_info,
);

// The max_sub_level_id may have been increased, e.g. during commit_epoch or merge_group.
Copy link
Contributor

Choose a reason for hiding this comment

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

We should max with self.max_sub_level_id and otherwise it will be reset to 0 when all data are clean.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Thanks.

@@ -883,7 +886,7 @@ impl HummockVersion {
)
});

group_split::merge_levels(left_levels, right_levels);
group_split::merge_levels(left_levels, right_levels, self.max_sub_level_id);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if it's better to maintain a per-compaction group max_sub_level_id instead of a global one, and then we don't need to pass the global one here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm open to either option. @Li0k

Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer global uniqueness, for me at the moment this sub level id has no more semantics. So globally unique is more concise.

Copy link
Contributor

@Li0k Li0k left a comment

Choose a reason for hiding this comment

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

Rest LGTM, thanks for the quick fix

.latest_version()
.max_sub_level_id
.map(|id| id + 1)
.unwrap_or(FIRST_SUB_LEVEL_ID),
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 it's ok for now, the newly introduced fields keep the Option restrictions.

When line 169 is reached, the sub_level will no longer exist in the compaciton group, so it is correct to use FIRST_SUB_LEVEL_ID for initialisation.

@@ -883,7 +886,7 @@ impl HummockVersion {
)
});

group_split::merge_levels(left_levels, right_levels);
group_split::merge_levels(left_levels, right_levels, self.max_sub_level_id);
Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer global uniqueness, for me at the moment this sub level id has no more semantics. So globally unique is more concise.

@zwang28 zwang28 marked this pull request as draft October 15, 2024 10:02
@zwang28

This comment was marked as resolved.

@zwang28 zwang28 marked this pull request as ready for review October 15, 2024 10:39
.latest_version()
.max_sub_level_id
.map(|id| id + 1)
.unwrap_or(FIRST_SUB_LEVEL_ID);
Copy link
Collaborator

Choose a reason for hiding this comment

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

For extra safety, I suggest we fill in max_sub_level_id using Epoch::now() if it is None on meta startup (in load_meta_store_state_impl) after all existing deltas are applied. In this case, we can make sure max_sub_level_id is larger than any previously generated sub level id.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes this should be the correct way.
Previously I didn't consider the delta replay for backward-compatibility. Backward compatibility shouldn't be done during pb deserialization.

Copy link
Contributor Author

@zwang28 zwang28 Oct 17, 2024

Choose a reason for hiding this comment

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

Refactored:

  • In-mem max_sub_level_id's type is u64 instead of Option now.
  • backward compatibility is ensured during load_meta_store_state_impl.

@Li0k

@zwang28 zwang28 requested review from Li0k and hzxa21 October 17, 2024 12:38
@zwang28
Copy link
Contributor Author

zwang28 commented Oct 18, 2024

I prefer #18893 to this PR.

  • feat(meta): commit epoch in separate group delta #18893 removes summarize_group_deltas.
  • The problem with summarize_group_deltas is it loses the order of events inside a delta. e.g. previously in apply_version_delta, GroupConstruct/GroupMerge is hard coded to always be applied before IntraLevel. I think such assumption of order in apply_version_delta increases the risk of bug, e.g. in case one day there is a [IntraLevel, GroupMerge, IntraLevel] delta, the hard coded order becomes incorrect.
  • We can always apply this PR anytime when non-decreasing order of sub_level_id is required in the future.

WDYT @hzxa21 @Li0k @wenym1

@zwang28 zwang28 closed this Oct 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants