-
Notifications
You must be signed in to change notification settings - Fork 531
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AOF Replay using a Background Task at the Replica (#783)
* remove unused code * nit * cleanup replication tests * expose replica max lag parameter * add guarded initialization API for TsavoriteLog to avoid disrupting iterator consumer operations when skipping addresses at replica * background replay consume implementation * rename replay max lag parameter and added stats info * update aof stream checks * fix LRANGE bug * ensure replicaof resets replay iterator * add async replay tests * remap ReplicationOffsetMaxLag parameter to make infinite lag default * streamline spinwait for initialization using ProtectAndDrain * add check to detect AOF divergence at the replica * update unit tests for ClusterReplayAsync * delete stale comment * pageSizeBits instance variable for use with process AOF stream * update sanity check * add comment for sanity check * release new version
- Loading branch information
Showing
21 changed files
with
352 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
113 changes: 113 additions & 0 deletions
113
libs/cluster/Server/Replication/ReplicaOps/ReplicaReplayTask.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
|
||
using System; | ||
using System.Threading; | ||
using Garnet.common; | ||
using Microsoft.Extensions.Logging; | ||
using Tsavorite.core; | ||
|
||
namespace Garnet.cluster | ||
{ | ||
internal sealed partial class ReplicationManager : IBulkLogEntryConsumer, IDisposable | ||
{ | ||
TsavoriteLogScanSingleIterator replayIterator = null; | ||
CancellationTokenSource replicaReplayTaskCts; | ||
SingleWriterMultiReaderLock activeReplay; | ||
|
||
/// <summary> | ||
/// Reset background replay iterator | ||
/// </summary> | ||
public void ResetReplayIterator() | ||
{ | ||
ResetReplayCts(); | ||
replayIterator?.Dispose(); | ||
replayIterator = null; | ||
|
||
void ResetReplayCts() | ||
{ | ||
if (replicaReplayTaskCts == null) | ||
{ | ||
replicaReplayTaskCts = CancellationTokenSource.CreateLinkedTokenSource(ctsRepManager.Token); | ||
} | ||
else | ||
{ | ||
replicaReplayTaskCts.Cancel(); | ||
try | ||
{ | ||
activeReplay.WriteLock(); | ||
replicaReplayTaskCts.Dispose(); | ||
replicaReplayTaskCts = CancellationTokenSource.CreateLinkedTokenSource(ctsRepManager.Token); | ||
} | ||
finally | ||
{ | ||
activeReplay.WriteUnlock(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
public void Throttle() { } | ||
|
||
public unsafe void Consume(byte* record, int recordLength, long currentAddress, long nextAddress, bool isProtected) | ||
{ | ||
ReplicationOffset = currentAddress; | ||
var ptr = record; | ||
while (ptr < record + recordLength) | ||
{ | ||
replicaReplayTaskCts.Token.ThrowIfCancellationRequested(); | ||
var entryLength = storeWrapper.appendOnlyFile.HeaderSize; | ||
var payloadLength = storeWrapper.appendOnlyFile.UnsafeGetLength(ptr); | ||
if (payloadLength > 0) | ||
{ | ||
aofProcessor.ProcessAofRecordInternal(ptr + entryLength, payloadLength, true); | ||
entryLength += TsavoriteLog.UnsafeAlign(payloadLength); | ||
} | ||
else if (payloadLength < 0) | ||
{ | ||
if (!clusterProvider.serverOptions.EnableFastCommit) | ||
{ | ||
throw new GarnetException("Received FastCommit request at replica AOF processor, but FastCommit is not enabled", clientResponse: false); | ||
} | ||
TsavoriteLogRecoveryInfo info = new(); | ||
info.Initialize(new ReadOnlySpan<byte>(ptr + entryLength, -payloadLength)); | ||
storeWrapper.appendOnlyFile?.UnsafeCommitMetadataOnly(info, isProtected); | ||
entryLength += TsavoriteLog.UnsafeAlign(-payloadLength); | ||
} | ||
ptr += entryLength; | ||
ReplicationOffset += entryLength; | ||
} | ||
|
||
if (ReplicationOffset != nextAddress) | ||
{ | ||
logger?.LogError("ReplicaReplayTask.Consume NextAddress Mismatch recordLength:{recordLength}; currentAddress:{currentAddress}; nextAddress:{nextAddress}; replicationOffset:{ReplicationOffset}", recordLength, currentAddress, nextAddress, ReplicationOffset); | ||
throw new GarnetException($"ReplicaReplayTask.Consume NextAddress Mismatch recordeLength:{recordLength}; currentAddress:{currentAddress}; nextAddress:{nextAddress}; replicationOffset:{ReplicationOffset}", LogLevel.Warning, clientResponse: false); | ||
} | ||
} | ||
|
||
public async void ReplicaReplayTask() | ||
{ | ||
try | ||
{ | ||
activeReplay.ReadLock(); | ||
while (true) | ||
{ | ||
replicaReplayTaskCts.Token.ThrowIfCancellationRequested(); | ||
await replayIterator.BulkConsumeAllAsync( | ||
this, | ||
clusterProvider.serverOptions.ReplicaSyncDelayMs, | ||
maxChunkSize: 1 << 20, | ||
replicaReplayTaskCts.Token); | ||
} | ||
} | ||
catch (Exception ex) | ||
{ | ||
logger?.LogWarning(ex, "An exception occurred at ReplicationManager.ReplicaReplayTask - terminating"); | ||
} | ||
finally | ||
{ | ||
activeReplay.ReadUnlock(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.