DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.
DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.
ConsistentCut is a distributed algorithm that splits WAL on 2 global areas - Before and After. It guarantees that every transaction committed Before also will be committed Before on every other node participated in the transaction. It means that an Ignite nodes can safely recover themself to the consistent Before state without any coordination with each other.
The border between Before and After areas consists of two WAL records - ConsistentCutStartRecord and ConsistentCutFinishRecord. It guarantees that the Before consists of:
ConsistentCutStartRecord AND weren't included into ConsistentCutFinishRecord#after().ConsistentCutStartRecord and ConsistentCutFinishRecord AND were included into ConsistentCutFinishRecord#before().On the picture below the Before area consist of transactions colored to yellow, while After is green.
/** */
public class ConsistentCutStartRecord extends WALRecord {
/** Consistent Cut ID. */
private final UUID cutId;
}
/** */
public class ConsistentCutFinishRecord extends WALRecord {
/** Consistent Cut ID. */
private final UUID cutId;
/**
* Collections of transactions committed BEFORE.
*/
private final Set<GridCacheVersion> before;
/**
* Collections of transactions committed AFTER.
*/
private final Set<GridCacheVersion> after;
}
Picture bellow illustrates steps of the algorithm on single node:
lastFinishedCutId holds previous ConsistentCutId, or null.SnapshotOperationRequest that holds new ConsistentCutId (goal is to notify every node in a cluster about running incremental snapshot). SnapshotOperationRequest#ConsistentCutId by DiscoverySPI (by the DistributedProcess).ConsistentCutAwareMessage#ConsistentCutId by CommunicationSPI (by transaction messages - Prepare, Finish).ConsistentCutId it starts local ConsistentCut: ConsistentCut != null) or finished (lastFinishedCutId == id) for this id, skip if it has.ConsistentCutAwareMessage#topVer with local node order:ConsistentCut future. ConsistentCut != null wraps outgoing messages to ConsistentCutAwareMessage. It contains info:ConsistentCutId (to start ConsistentCut on remote node, if not yet).txCutId equals to null then transaction starts committing Before Consistent Cut started, otherwise After.ConsistentCutAwareMessage that makes transaction committed (FinishRequest for 2PC, PrepareResponse for 1PC) sets tx#txCutId = message#txCutId.ConsistentCut future.removedActiveTxs (This collection doesn't remove transactions unlike IgniteTxManager#activeTx does).ConsistentCutStartRecord to WAL with the received ConsistentCutId.IgniteTxManager#activeTx. Set listeners on those tx#finishFuture.tx#status == ACTIVE. It's guaranteed that such transactions belongs After side.removedActiveTxs (contains transactions that are might be cleaned from IgniteTxManager#activeTx). Set listeners on those tx#finishFuture.removedActiveTxs to null. We don't care of txs concurrently added to removedActiveTxs, they just don't land into "before" or "after" set and will be excluded from recovery.removedActiveTxs if ConsistentCut != null and removedActiveTxs != null:removedActiveTxs right before it is removed from IgniteTxManager#activeTx.tx#txCutId equals to local, then put transaction into after, otherwise put into before.ConsistentCutFinishRecord into WAL with the collections ( before, after ). ConsistentCut future.ConsistentCut future becomes null.Consistent Cut is such cut that correctly finished on all baseline nodes - ConsistentCutStartRecord and ConsistentCutFinishRecord are written.
"Inconsistent" Cut is such a cut when one or more baseline nodes hasn't wrote ConsistentCutFinishRecord . It's possible in cases:
tx.finalizationStatus == RECOVERY_FINISH).Ignite transaction protocol includes multiple messages. But only some of them affects meaningful (relating to the algorithm) that change state of transactions (PREPARED, COMMITTED):
GridNearTxPrepareRequest / GridDhtTxPrepareRequestGridNearTxPrepareResponse / GridDhtTxPrepareResponseGridNearTxFinishRequest / GridDhtTxFinishRequest
Those messages are wrapped in ConsistentCutAwareMessage that is prepared right before sending message on other node. They used the current ConsistentCutId. Also some messages require to be combine with additional ConsistentCutId to check it them on primary/backup node:
GridNearTxFinishRequest / GridDhtTxFinishRequestGridNearTxPrepareResponse / GridDhtTxPrepareResponse (for 1PC algorithm).Those messages are filled with txCutId that is prepared right before transaction starts committing on first committing node. They used the current ConsistentCutId for this setting. If current ConsistentCutId is not null, then transaction starts committing after ConsistentCut started and it means that this transaction belongs the After side.
class ConsistentCutAwareMessage {
/** Original transaction message. */
Message msg;
/** Consistent Cut ID. */
UUID cutId;
/** Consistent Cut ID after which transaction committed. */
@Nullable UUID txCutId;
/** Cluster topology version on which Consistent Cut started. */
long topVer;
}
A new field added to IgniteInternalTx
class IgniteInternalTx {
/**
* @param ID of {@link ConsistentCut} AFTER which this transaction was committed, {@code null} if transaction
* committed BEFORE.
*/
public void cutId(@Nullable UUID id);
}
// Class is responsible for managing all stuff related to Consistent Cut. It's an entrypoint for transaction threads to check running consistent cut.
class ConsistentCutManager extends GridCacheSharedManagerAdapter {
// Current Consistent Cut. All transactions threads wraps outgoing messages if this field is not null. */
volatile @Nullable ConsistentCut cut;
// Entrypoint for handling received new Consistent Cut ID.
void handleConsistentCutId(UUID id);
}
class ConsistentCut extends GridFutureAdapter<WALPointer> {
Set<GridCacheVersion> beforeCut;
Set<GridCacheVersion> afterCut;
Set<IgniteInternalFuture<IgniteInternalTx>> removedActive;
}