-
Notifications
You must be signed in to change notification settings - Fork 455
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
[dbnode] Avoid loading blocks in memory for namespaces with snapshots disabled during bootstrapping #3919
[dbnode] Avoid loading blocks in memory for namespaces with snapshots disabled during bootstrapping #3919
Changes from 3 commits
d8f27d0
4b27532
28ceb75
c4535ae
7f2a91f
e205a44
692bbe4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -188,19 +188,23 @@ func (b bootstrapProcess) Run( | |
} | ||
namespaceDetails := make([]NamespaceDetails, 0, len(namespaces)) | ||
for _, namespace := range namespaces { | ||
ropts := namespace.Metadata.Options().RetentionOptions() | ||
idxopts := namespace.Metadata.Options().IndexOptions() | ||
dataRanges := b.targetRangesForData(at, ropts) | ||
indexRanges := b.targetRangesForIndex(at, ropts, idxopts) | ||
firstRanges := b.newShardTimeRanges( | ||
dataRanges.firstRangeWithPersistTrue.Range, | ||
namespace.Shards, | ||
var ( | ||
ropts = namespace.Metadata.Options().RetentionOptions() | ||
idxopts = namespace.Metadata.Options().IndexOptions() | ||
dataRanges = b.targetRangesForData(at, ropts, namespace.ReadOnly) | ||
indexRanges = b.targetRangesForIndex(at, ropts, idxopts, namespace.ReadOnly) | ||
firstRanges = b.newShardTimeRanges( | ||
dataRanges.firstRangeWithPersistTrue.Range, | ||
namespace.Shards, | ||
) | ||
) | ||
|
||
namespacesRunFirst.Namespaces.Set(namespace.Metadata.ID(), Namespace{ | ||
Metadata: namespace.Metadata, | ||
Shards: namespace.Shards, | ||
DataAccumulator: namespace.DataAccumulator, | ||
Hooks: namespace.Hooks, | ||
ReadOnly: namespace.ReadOnly, | ||
DataTargetRange: dataRanges.firstRangeWithPersistTrue, | ||
IndexTargetRange: indexRanges.firstRangeWithPersistTrue, | ||
DataRunOptions: NamespaceRunOptions{ | ||
|
@@ -215,23 +219,24 @@ func (b bootstrapProcess) Run( | |
}, | ||
}) | ||
secondRanges := b.newShardTimeRanges( | ||
dataRanges.secondRangeWithPersistFalse.Range, namespace.Shards) | ||
dataRanges.secondRange.Range, namespace.Shards) | ||
namespacesRunSecond.Namespaces.Set(namespace.Metadata.ID(), Namespace{ | ||
Metadata: namespace.Metadata, | ||
Shards: namespace.Shards, | ||
DataAccumulator: namespace.DataAccumulator, | ||
Hooks: namespace.Hooks, | ||
DataTargetRange: dataRanges.secondRangeWithPersistFalse, | ||
IndexTargetRange: indexRanges.secondRangeWithPersistFalse, | ||
ReadOnly: namespace.ReadOnly, | ||
DataTargetRange: dataRanges.secondRange, | ||
IndexTargetRange: indexRanges.secondRange, | ||
DataRunOptions: NamespaceRunOptions{ | ||
ShardTimeRanges: secondRanges.Copy(), | ||
TargetShardTimeRanges: secondRanges.Copy(), | ||
RunOptions: dataRanges.secondRangeWithPersistFalse.RunOptions, | ||
RunOptions: dataRanges.secondRange.RunOptions, | ||
}, | ||
IndexRunOptions: NamespaceRunOptions{ | ||
ShardTimeRanges: secondRanges.Copy(), | ||
TargetShardTimeRanges: secondRanges.Copy(), | ||
RunOptions: indexRanges.secondRangeWithPersistFalse.RunOptions, | ||
RunOptions: indexRanges.secondRange.RunOptions, | ||
}, | ||
}) | ||
namespaceDetails = append(namespaceDetails, NamespaceDetails{ | ||
|
@@ -248,7 +253,7 @@ func (b bootstrapProcess) Run( | |
} | ||
|
||
bootstrapResult := NewNamespaceResults(namespacesRunFirst) | ||
for _, namespaces := range []Namespaces{ | ||
for runIndex, namespaces := range []Namespaces{ | ||
namespacesRunFirst, | ||
namespacesRunSecond, | ||
} { | ||
|
@@ -266,24 +271,23 @@ func (b bootstrapProcess) Run( | |
continue | ||
} | ||
|
||
// Check if snapshot-type ranges have advanced while bootstrapping previous ranges. | ||
// If second run, check if snapshot-type ranges have advanced while bootstrapping previous ranges. | ||
// If yes, return an error to force a retry | ||
if persistConf := ns.DataRunOptions.RunOptions.PersistConfig(); persistConf.Enabled && | ||
persistConf.FileSetType == persist.FileSetSnapshotType { | ||
if runIndex == 1 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think checking for the second run should be enough here to replace previous condition. This is needed because now second run blocks won't always have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do I understand correctly that this is not really required to avoid loading blocks in memory for read only? Can we split this into separate PR? Mainly because with my limited knowledge this seem to be a dangerious change that might also affect non read only namespaces and we might need to revert it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is needed because if this condition is left unchanged, we won't be able to check if target ranges have advanced for read-only namespaces. Don't think that this change is dangerous, because it will behave in the same way as before (just the condition is different) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, i agree the logic is still similar but i agree - i’d rather not change setting file snapshot type to something other than Snapshot. I’ll keep reviewing and give recommendation once understanding the larger change, but seems we are going from type safe to type unsafe potentially. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this make more sense if we based the decision on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree that decision based on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated PR to use |
||
var ( | ||
now = xtime.ToUnixNano(b.nowFn()) | ||
nsOptions = ns.Metadata.Options() | ||
upToDateDataRanges = b.targetRangesForData(now, nsOptions.RetentionOptions()) | ||
upToDateDataRanges = b.targetRangesForData(now, nsOptions.RetentionOptions(), ns.ReadOnly) | ||
) | ||
// Only checking data ranges. Since index blocks can only be a multiple of | ||
// data block size, the ranges for index could advance only if data ranges | ||
// have advanced, too (while opposite is not necessarily true) | ||
if !upToDateDataRanges.secondRangeWithPersistFalse.Range.Equal(ns.DataTargetRange.Range) { | ||
if !upToDateDataRanges.secondRange.Range.Equal(ns.DataTargetRange.Range) { | ||
upToDateIndexRanges := b.targetRangesForIndex(now, nsOptions.RetentionOptions(), | ||
nsOptions.IndexOptions()) | ||
nsOptions.IndexOptions(), ns.ReadOnly) | ||
fields := b.logFields(ns.Metadata, ns.Shards, | ||
upToDateDataRanges.secondRangeWithPersistFalse.Range, | ||
upToDateIndexRanges.secondRangeWithPersistFalse.Range) | ||
upToDateDataRanges.secondRange.Range, | ||
upToDateIndexRanges.secondRange.Range) | ||
b.log.Error("time ranges of snapshot-type blocks advanced", fields...) | ||
return NamespaceResults{}, ErrFileSetSnapshotTypeRangeAdvanced | ||
} | ||
|
@@ -445,27 +449,31 @@ func (b bootstrapProcess) logBootstrapResult( | |
func (b bootstrapProcess) targetRangesForData( | ||
at xtime.UnixNano, | ||
ropts retention.Options, | ||
readOnly bool, | ||
) targetRangesResult { | ||
return b.targetRanges(at, targetRangesOptions{ | ||
retentionPeriod: ropts.RetentionPeriod(), | ||
futureRetentionPeriod: ropts.FutureRetentionPeriod(), | ||
blockSize: ropts.BlockSize(), | ||
bufferPast: ropts.BufferPast(), | ||
bufferFuture: ropts.BufferFuture(), | ||
readOnly: readOnly, | ||
}) | ||
} | ||
|
||
func (b bootstrapProcess) targetRangesForIndex( | ||
at xtime.UnixNano, | ||
ropts retention.Options, | ||
idxopts namespace.IndexOptions, | ||
readOnly bool, | ||
) targetRangesResult { | ||
return b.targetRanges(at, targetRangesOptions{ | ||
retentionPeriod: ropts.RetentionPeriod(), | ||
futureRetentionPeriod: ropts.FutureRetentionPeriod(), | ||
blockSize: idxopts.BlockSize(), | ||
bufferPast: ropts.BufferPast(), | ||
bufferFuture: ropts.BufferFuture(), | ||
readOnly: readOnly, | ||
}) | ||
} | ||
|
||
|
@@ -475,11 +483,12 @@ type targetRangesOptions struct { | |
blockSize time.Duration | ||
bufferPast time.Duration | ||
bufferFuture time.Duration | ||
readOnly bool | ||
} | ||
|
||
type targetRangesResult struct { | ||
firstRangeWithPersistTrue TargetRange | ||
secondRangeWithPersistFalse TargetRange | ||
firstRangeWithPersistTrue TargetRange | ||
secondRange TargetRange | ||
} | ||
|
||
func (b bootstrapProcess) targetRanges( | ||
|
@@ -499,6 +508,12 @@ func (b bootstrapProcess) targetRanges( | |
Truncate(opts.blockSize). | ||
Add(opts.blockSize) | ||
|
||
secondRangeFilesetType := persist.FileSetSnapshotType | ||
if opts.readOnly { | ||
// NB: If namespace is read-only, we don't want to keep blocks in memory. | ||
secondRangeFilesetType = persist.FileSetFlushType | ||
} | ||
|
||
// NB(r): We want the large initial time range bootstrapped to | ||
// bootstrap with persistence so we don't keep the full raw | ||
// data in process until we finish bootstrapping which could | ||
|
@@ -514,15 +529,15 @@ func (b bootstrapProcess) targetRanges( | |
FileSetType: persist.FileSetFlushType, | ||
}), | ||
}, | ||
secondRangeWithPersistFalse: TargetRange{ | ||
secondRange: TargetRange{ | ||
Range: xtime.Range{Start: midPoint, End: cutover}, | ||
RunOptions: b.newRunOptions().SetPersistConfig(PersistConfig{ | ||
Enabled: true, | ||
// These blocks are still active so we'll have to keep them | ||
// in memory, but we want to snapshot them as we receive them | ||
// so that once bootstrapping completes we can still recover | ||
// from just the commit log bootstrapper. | ||
FileSetType: persist.FileSetSnapshotType, | ||
FileSetType: secondRangeFilesetType, | ||
}), | ||
}, | ||
} | ||
|
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.
Hm why are we using “secondRange” instead of “secondRangeWithPersistFalse” 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.
Because if namespace is read-only, it will resolve to
shouldPersist=true
for the second range. Other namespaces will still resolve toshouldPersist=false
as it was before these changes.