Skip to content

Commit dfcd20b

Browse files
authored
Write changes using WriteTxId in consistent mode (#11374)
1 parent 79c834b commit dfcd20b

File tree

15 files changed

+387
-25
lines changed

15 files changed

+387
-25
lines changed

ydb/core/base/row_version.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
namespace NKikimr {
88

9+
TRowVersion TRowVersion::Parse(const NKikimrProto::TRowVersion& proto) {
10+
return TRowVersion(proto.GetStep(), proto.GetTxId());
11+
}
12+
913
void TRowVersion::Serialize(NKikimrProto::TRowVersion& proto) const {
1014
proto.SetStep(Step);
1115
proto.SetTxId(TxId);

ydb/core/base/row_version.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ namespace NKikimr {
7575
return ++copy;
7676
}
7777

78+
static TRowVersion Parse(const NKikimrProto::TRowVersion& proto);
7879
void Serialize(NKikimrProto::TRowVersion& proto) const;
7980

8081
friend constexpr bool operator==(const TRowVersion& a, const TRowVersion& b) {

ydb/core/change_exchange/change_record.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class IChangeRecord: public TThrRefBase {
3737

3838
virtual void Accept(IVisitor& visitor) const = 0;
3939

40+
virtual void RewriteTxId(ui64 value) = 0;
41+
4042
virtual TString ToString() const = 0;
4143
virtual void Out(IOutputStream& out) const = 0;
4244

@@ -56,6 +58,8 @@ class TChangeRecordBase: public IChangeRecord {
5658
const TString& GetSourceId() const override { return SourceId; }
5759
bool IsBroadcast() const override { return false; }
5860

61+
void RewriteTxId(ui64) override { Y_ABORT("not implemented"); }
62+
5963
TString ToString() const override;
6064
void Out(IOutputStream& out) const override;
6165

ydb/core/protos/replication.proto

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import "ydb/core/scheme/protos/pathid.proto";
2+
import "ydb/core/protos/base.proto";
23
import "ydb/public/api/protos/annotations/sensitive.proto";
34
import "ydb/public/api/protos/ydb_issue_message.proto";
45

@@ -257,3 +258,22 @@ message TEvWorkerDataEnd {
257258
repeated uint64 AdjacentPartitionsIds = 3;
258259
repeated uint64 ChildPartitionsIds = 4;
259260
}
261+
262+
message TEvGetTxId {
263+
repeated NKikimrProto.TRowVersion Versions = 1;
264+
}
265+
266+
message TEvTxIdResult {
267+
message TVersionTxId {
268+
optional NKikimrProto.TRowVersion Version = 1;
269+
optional uint64 TxId = 2;
270+
}
271+
272+
optional TControllerIdentity Controller = 1;
273+
repeated TVersionTxId VersionTxIds = 2;
274+
}
275+
276+
message TEvHeartbeat {
277+
optional TWorkerIdentity Worker = 1;
278+
optional NKikimrProto.TRowVersion Version = 2;
279+
}

ydb/core/tx/replication/service/base_table_writer.cpp

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "base_table_writer.h"
22
#include "logging.h"
3+
#include "service.h"
34
#include "worker.h"
45

56
#include <ydb/core/base/tablet_pipecache.h>
@@ -16,6 +17,7 @@
1617

1718
#include <util/generic/map.h>
1819
#include <util/generic/maybe.h>
20+
#include <util/generic/set.h>
1921
#include <util/string/builder.h>
2022

2123
namespace NKikimr::NReplication::NService {
@@ -426,16 +428,71 @@ class TLocalTableWriter
426428

427429
Y_ABORT_UNLESS(PendingRecords.empty());
428430
TVector<NChangeExchange::TEvChangeExchange::TEvEnqueueRecords::TRecordInfo> records(::Reserve(ev->Get()->Records.size()));
431+
TSet<TRowVersion> versionsWithoutTxId;
429432

430-
for (auto& record : ev->Get()->Records) {
431-
records.emplace_back(record.Offset, TablePathId, record.Data.size());
432-
auto res = PendingRecords.emplace(
433-
record.Offset, Parser->Parse(ev->Get()->Source, record.Offset, std::move(record.Data))
434-
);
435-
Y_ABORT_UNLESS(res.second);
433+
for (auto& [offset, data, _] : ev->Get()->Records) {
434+
auto record = Parser->Parse(ev->Get()->Source, offset, std::move(data));
435+
436+
if (Mode == EWriteMode::Consistent) {
437+
const auto version = TRowVersion(record->GetStep(), record->GetTxId());
438+
439+
if (record->GetKind() == NChangeExchange::IChangeRecord::EKind::CdcHeartbeat) {
440+
TxIds.erase(TxIds.begin(), TxIds.upper_bound(version));
441+
Send(Worker, new TEvService::TEvHeartbeat(version));
442+
continue;
443+
} else if (record->GetKind() != NChangeExchange::IChangeRecord::EKind::CdcDataChange) {
444+
Y_ABORT("Unexpected record kind");
445+
}
446+
447+
if (auto it = TxIds.upper_bound(version); it != TxIds.end()) {
448+
record->RewriteTxId(it->second);
449+
} else {
450+
versionsWithoutTxId.insert(version);
451+
PendingTxId[version].push_back(std::move(record));
452+
continue;
453+
}
454+
}
455+
456+
records.emplace_back(record->GetOrder(), TablePathId, record->GetBody().size());
457+
Y_ABORT_UNLESS(PendingRecords.emplace(record->GetOrder(), std::move(record)).second);
458+
}
459+
460+
if (versionsWithoutTxId) {
461+
Send(Worker, new TEvService::TEvGetTxId(versionsWithoutTxId));
462+
}
463+
464+
if (records) {
465+
EnqueueRecords(std::move(records));
466+
}
467+
}
468+
469+
void Handle(TEvService::TEvTxIdResult::TPtr& ev) {
470+
LOG_D("Handle " << ev->Get()->ToString());
471+
472+
TVector<NChangeExchange::TEvChangeExchange::TEvEnqueueRecords::TRecordInfo> records;
473+
474+
for (const auto& kv : ev->Get()->Record.GetVersionTxIds()) {
475+
const auto version = TRowVersion::Parse(kv.GetVersion());
476+
TxIds.emplace(version, kv.GetTxId());
477+
478+
for (auto it = PendingTxId.begin(); it != PendingTxId.end();) {
479+
if (it->first >= version) {
480+
break;
481+
}
482+
483+
for (auto& record : it->second) {
484+
record->RewriteTxId(kv.GetTxId());
485+
records.emplace_back(record->GetOrder(), TablePathId, record->GetBody().size());
486+
Y_ABORT_UNLESS(PendingRecords.emplace(record->GetOrder(), std::move(record)).second);
487+
}
488+
489+
PendingTxId.erase(it++);
490+
}
436491
}
437492

438-
EnqueueRecords(std::move(records));
493+
if (records) {
494+
EnqueueRecords(std::move(records));
495+
}
439496
}
440497

441498
void Handle(NChangeExchange::TEvChangeExchange::TEvRequestRecords::TPtr& ev) {
@@ -502,12 +559,14 @@ class TLocalTableWriter
502559
}
503560

504561
explicit TLocalTableWriter(
562+
EWriteMode mode,
505563
const TPathId& tablePathId,
506564
THolder<IChangeRecordParser>&& parser,
507565
THolder<IChangeRecordSerializer>&& serializer,
508566
std::function<NChangeExchange::IPartitionResolverVisitor*(const NKikimr::TKeyDesc&)>&& createResolverFn)
509567
: TActor(&TThis::StateWork)
510568
, TChangeSender(this, this, this, this, TActorId())
569+
, Mode(mode)
511570
, TablePathId(tablePathId)
512571
, Parser(std::move(parser))
513572
, Serializer(std::move(serializer))
@@ -523,6 +582,7 @@ class TLocalTableWriter
523582
switch (ev->GetTypeRewrite()) {
524583
hFunc(TEvWorker::TEvHandshake, Handle);
525584
hFunc(TEvWorker::TEvData, Handle);
585+
hFunc(TEvService::TEvTxIdResult, Handle);
526586
hFunc(NChangeExchange::TEvChangeExchange::TEvRequestRecords, Handle);
527587
hFunc(NChangeExchange::TEvChangeExchange::TEvRemoveRecords, Handle);
528588
hFunc(NChangeExchange::TEvChangeExchangePrivate::TEvReady, Handle);
@@ -536,6 +596,7 @@ class TLocalTableWriter
536596

537597
private:
538598
mutable TMaybe<TString> LogPrefix;
599+
const EWriteMode Mode;
539600
const TPathId TablePathId;
540601
THolder<IChangeRecordParser> Parser;
541602
THolder<IChangeRecordSerializer> Serializer;
@@ -549,16 +610,19 @@ class TLocalTableWriter
549610
bool Initialized = false;
550611

551612
TMap<ui64, NChangeExchange::IChangeRecord::TPtr> PendingRecords;
613+
TMap<TRowVersion, ui64> TxIds; // key is non-inclusive right hand edge
614+
TMap<TRowVersion, TVector<NChangeExchange::IChangeRecord::TPtr>> PendingTxId;
552615

553616
}; // TLocalTableWriter
554617

555618
IActor* CreateLocalTableWriter(
556619
const TPathId& tablePathId,
557620
THolder<IChangeRecordParser>&& parser,
558621
THolder<IChangeRecordSerializer>&& serializer,
559-
std::function<NChangeExchange::IPartitionResolverVisitor*(const NKikimr::TKeyDesc&)>&& createResolverFn)
622+
std::function<NChangeExchange::IPartitionResolverVisitor*(const NKikimr::TKeyDesc&)>&& createResolverFn,
623+
EWriteMode mode)
560624
{
561-
return new TLocalTableWriter(tablePathId, std::move(parser), std::move(serializer), std::move(createResolverFn));
625+
return new TLocalTableWriter(mode, tablePathId, std::move(parser), std::move(serializer), std::move(createResolverFn));
562626
}
563627

564628
} // namespace NKikimr::NReplication::NService

ydb/core/tx/replication/service/base_table_writer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "lightweight_schema.h"
4+
#include "table_writer.h"
45

56
#include <ydb/core/base/defs.h>
67
#include <ydb/core/change_exchange/change_record.h>
@@ -31,6 +32,7 @@ IActor* CreateLocalTableWriter(
3132
const TPathId& tablePathId,
3233
THolder<IChangeRecordParser>&& parser,
3334
THolder<IChangeRecordSerializer>&& serializer,
34-
std::function<NChangeExchange::IPartitionResolverVisitor*(const NKikimr::TKeyDesc&)>&& createResolverFn);
35+
std::function<NChangeExchange::IPartitionResolverVisitor*(const NKikimr::TKeyDesc&)>&& createResolverFn,
36+
EWriteMode mode = EWriteMode::Simple);
3537

3638
}

ydb/core/tx/replication/service/json_change_record.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ static bool ParseValue(TVector<NTable::TTag>& tags, TVector<TCell>& cells,
9191
void TChangeRecord::Serialize(NKikimrTxDataShard::TEvApplyReplicationChanges_TChange& record, TMemoryPool& pool) const {
9292
pool.Clear();
9393
record.SetSourceOffset(GetOrder());
94-
// TODO: fill WriteTxId
94+
if (WriteTxId) {
95+
record.SetWriteTxId(WriteTxId);
96+
}
9597

9698
TString error;
9799

@@ -155,4 +157,8 @@ void TChangeRecord::Accept(NChangeExchange::IVisitor& visitor) const {
155157
return visitor.Visit(*this);
156158
}
157159

160+
void TChangeRecord::RewriteTxId(ui64 value) {
161+
WriteTxId = value;
162+
}
163+
158164
}

ydb/core/tx/replication/service/json_change_record.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ class TChangeRecord: public NChangeExchange::TChangeRecordBase {
3333
TConstArrayRef<TCell> GetKey() const;
3434

3535
void Accept(NChangeExchange::IVisitor& visitor) const override;
36+
void RewriteTxId(ui64 value) override;
3637

3738
private:
3839
NJson::TJsonValue JsonBody;
3940
TLightweightSchema::TCPtr Schema;
41+
ui64 WriteTxId = 0;
4042

4143
mutable TMaybe<TOwnedCellVec> Key;
4244

0 commit comments

Comments
 (0)