Skip to content

Commit 41cf614

Browse files
committed
Improve Tail Latency
- TransactionStatement token aware routing - Mitigate convoy effect: - ExecuteTxnBacklog v1 can execute single key transaction backlogs and disseminate the result - Direct local execution possible for single key transactions - Use shardAppliedBefore instead of gcBefore to cleanup CFK faster Also Improve: - Introduce distributed tracing - Combine RejectBefore and MaxConflicts - Self-addressed messages are delivered directly - Disable AccordSyncPropagator by default, as incompatible with large clusters - FastPathStrategy.SIMPLE should not modify fast path contents; FastPathStrategy.UP introduced to adopt this behaviour - Configurable queue prioritisation - ProtocolModifiers mostly final - Remove unnecessary condition check when serializing TxnUpdate Also Fix: - SequentialExecutor ownership bug - BTree.XUpdater.reset() patch by Benedict; reviewed by Alex Petrov and Ariel Weisberg for CASSANDRA-21361
1 parent 8ad8e56 commit 41cf614

150 files changed

Lines changed: 3250 additions & 1124 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
6.0-alpha2
2+
* Accord: Tail Latency Improvements (CASSANDRA-21361)
3+
* Artificial Latency Injection (CASSANDRA-17024)
4+
* Accord: Clean Shutdown/Restart, Rebootstrap, et al (CASSANDRA-21355)
25
* Reduce memory allocations in SelectStatement.getQuery (CASSANDRA-21351)
36
* Avoid allocation by getFunctions in SelectStatement.authorize (CASSANDRA-21347)
47
* Avoid unit conversion in DatabaseDescriptor.getMaxValueSize() for every deserializing Cell (CASSANDRA-21295)

modules/accord

Submodule accord updated 151 files

src/java/org/apache/cassandra/config/AccordSpec.java renamed to src/java/org/apache/cassandra/config/AccordConfig.java

Lines changed: 97 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,28 @@
2222

2323
import com.fasterxml.jackson.annotation.JsonIgnore;
2424

25+
import accord.api.ProtocolModifiers.CleanCfkBefore;
26+
import accord.api.ProtocolModifiers.CoordinatorBacklogExecution;
27+
import accord.api.ProtocolModifiers.FastExecution;
28+
import accord.api.ProtocolModifiers.ReplicaExecution;
29+
import accord.api.ProtocolModifiers.SendStableMessages;
30+
import accord.primitives.TxnId;
2531
import accord.utils.Invariants;
2632

2733
import org.apache.cassandra.journal.Params;
2834
import org.apache.cassandra.service.accord.serializers.Version;
2935
import org.apache.cassandra.service.consensus.TransactionalMode;
3036

31-
import static org.apache.cassandra.config.AccordSpec.CatchupMode.NORMAL;
32-
import static org.apache.cassandra.config.AccordSpec.QueueShardModel.THREAD_POOL_PER_SHARD;
33-
import static org.apache.cassandra.config.AccordSpec.QueueSubmissionModel.SYNC;
34-
import static org.apache.cassandra.config.AccordSpec.RangeIndexMode.in_memory;
37+
import static org.apache.cassandra.config.AccordConfig.CatchupMode.NORMAL;
38+
import static org.apache.cassandra.config.AccordConfig.QueuePriorityModel.HLC_FIFO;
39+
import static org.apache.cassandra.config.AccordConfig.QueueShardModel.THREAD_POOL_PER_SHARD;
40+
import static org.apache.cassandra.config.AccordConfig.QueueSubmissionModel.SYNC;
41+
import static org.apache.cassandra.config.AccordConfig.RangeIndexMode.in_memory;
3542

36-
// TODO (expected): rename to AccordConf?
37-
public class AccordSpec
43+
public class AccordConfig
3844
{
3945
public volatile boolean enabled = false;
4046

41-
// TODO (expected): move to JournalSpec
4247
public volatile String journal_directory;
4348

4449
/**
@@ -107,6 +112,37 @@ public enum QueueSubmissionModel
107112
EXEC_ST
108113
}
109114

115+
public enum QueuePriorityModel
116+
{
117+
/**
118+
* All work is queued on a first-come first-serve basis.
119+
* Overload can lead to more rapid degradation, as later phases of the state machine are delayed
120+
* by the arrival of new work.
121+
*/
122+
FIFO,
123+
124+
/**
125+
* If the work has an associated TxnId, prioritise by its HLC (and FIFO otherwise)
126+
*/
127+
HLC_FIFO,
128+
129+
/**
130+
* Prioritise Apply, Stable, Commit, Accept, and PreAccept messages in that order.
131+
* Within a given message type, prioritise by HLC.
132+
* Other messages will be mixed with PreAccept messages, but using the next counter rather than the HLC of the TxnId.
133+
* Note: this can have some performance edge cases for contended keys, as we may process Stable messages for later commands before
134+
* we process earlier Accept/Commit, which may delay execution
135+
*/
136+
PHASE_HLC_FIFO,
137+
138+
/**
139+
* Prioritise Apply, Stable, Commit, Accept, and PreAccept messages from the original coordinator only, in that order.
140+
* Within a given message type, prioritise by HLC.
141+
* Other messages will be mixed with PreAccept messages, but using the next counter rather than the HLC of the TxnId.
142+
*/
143+
ORIG_PHASE_HLC_FIFO
144+
}
145+
110146
public QueueShardModel queue_shard_model = THREAD_POOL_PER_SHARD;
111147
public QueueSubmissionModel queue_submission_model = SYNC;
112148

@@ -115,6 +151,15 @@ public enum QueueSubmissionModel
115151
*/
116152
public volatile OptionaldPositiveInt queue_shard_count = OptionaldPositiveInt.UNDEFINED;
117153

154+
public QueuePriorityModel queue_priority_model = HLC_FIFO;
155+
156+
// yield to other executor threads after executing this many tasks in a row, if there are waiting threads and tasks
157+
public int queue_yield_interval = 100;
158+
159+
/**
160+
* If the HLC is older than this, queue by FIFO instead
161+
*/
162+
public DurationSpec.IntMillisecondsBound queue_priority_age_to_fifo = new DurationSpec.IntMillisecondsBound(500);
118163
/**
119164
* The target number of command stores to create per topology shard.
120165
* This determines the amount of execution parallelism possible for a given table/shard on the host.
@@ -165,6 +210,10 @@ public enum QueueSubmissionModel
165210
public volatile DurationSpec.IntSecondsBound shard_durability_cycle = new DurationSpec.IntSecondsBound(5, TimeUnit.MINUTES);
166211
public volatile DurationSpec.IntSecondsBound global_durability_cycle = new DurationSpec.IntSecondsBound(5, TimeUnit.MINUTES);
167212

213+
public volatile DurationSpec.IntSecondsBound topology_watermark_interval = new DurationSpec.IntSecondsBound(60);
214+
public volatile boolean topology_sync_propagator_enabled_pre_start = false;
215+
public volatile boolean topology_sync_propagator_enabled_post_startup = false;
216+
168217
public enum TransactionalRangeMigration
169218
{
170219
auto, explicit
@@ -178,11 +227,6 @@ public enum TransactionalRangeMigration
178227
*/
179228
public volatile TransactionalRangeMigration range_migration = TransactionalRangeMigration.auto;
180229

181-
public enum RebootstrapMode
182-
{
183-
full_repair, truncate_and_stream
184-
}
185-
186230
public enum CatchupMode
187231
{
188232
DISABLED,
@@ -196,15 +240,43 @@ public enum CatchupMode
196240
*/
197241
public TransactionalMode default_transactional_mode = TransactionalMode.off;
198242

199-
public boolean ephemeralReadEnabled = true;
243+
// ******** PROTOCOL MODIFIERS ***********
244+
245+
public CoordinatorBacklogExecution coordinator_backlog_execution;
246+
public Boolean permit_local_delivery;
247+
public Boolean permit_coordinator_local_execution; // if disabled, the privileged coordinator optimisation will be counter-productive and should also be disabled
248+
public TxnId.FastPath permit_fast_path;
249+
public Boolean permit_track_stable_medium_path;
250+
public Boolean permit_fast_quorum_medium_path;
251+
public Boolean always_inform_durable_single_key;
252+
public ReplicaExecution replica_execution;
253+
public Float replica_execution_distributed_persist_chance;
254+
public FastExecution fast_write_execution;
255+
public FastExecution fast_read_execution;
256+
public CleanCfkBefore clean_cfk_before;
257+
public SendStableMessages send_stable;
258+
/**
259+
* include the least information expected to be necessary in messages -
260+
* this is more efficient but may lead to some additional traffic and latency when earlier messages had not arrived
261+
*/
262+
public Boolean send_minimal;
263+
// note: simulator incompatible (for now)
264+
public Boolean precise_micros;
265+
266+
public boolean ephemeral_reads = true;
200267
public boolean state_cache_listener_jfr_enabled = false;
201268

202269
public float hard_reject_ratio = 0.5f;
203-
public int min_soft_reject_count = 10;
204-
public int max_soft_reject_count = 100;
270+
public int min_soft_reject_count = 100;
271+
public int max_soft_reject_count = 1000;
205272
public DurationSpec.LongMicrosecondsBound soft_reject_age = new DurationSpec.LongMicrosecondsBound("10s");
206273
public DurationSpec.LongMicrosecondsBound soft_reject_cumulative_age = new DurationSpec.LongMicrosecondsBound("60s");
207274

275+
276+
public DurationSpec.IntSecondsBound commands_for_key_prune_delta = new DurationSpec.IntSecondsBound(1);
277+
public int commands_for_key_prune_interval = 64;
278+
public DurationSpec.IntSecondsBound max_conflicts_prune_delta = new DurationSpec.IntSecondsBound(1);
279+
208280
public DurationSpec.IntSecondsBound catchup_on_start_success_latency = new DurationSpec.IntSecondsBound(60);
209281
public DurationSpec.IntSecondsBound catchup_on_start_fail_latency = new DurationSpec.IntSecondsBound(900);
210282
public int catchup_on_start_max_attempts = 5;
@@ -216,7 +288,7 @@ public enum CatchupMode
216288
public enum RangeIndexMode { in_memory, journal_sai }
217289
public RangeIndexMode range_index_mode = in_memory;
218290

219-
public final JournalSpec journal = new JournalSpec();
291+
public final JournalConfig journal = new JournalConfig();
220292

221293
public enum MixedTimeSourceHandling
222294
{
@@ -225,7 +297,7 @@ public enum MixedTimeSourceHandling
225297

226298
public volatile MixedTimeSourceHandling mixedTimeSourceHandling = MixedTimeSourceHandling.reject;
227299

228-
public static class JournalSpec implements Params
300+
public static class JournalConfig implements Params
229301
{
230302
public enum ReplayMode
231303
{
@@ -265,11 +337,17 @@ public enum StopMarkerFailurePolicy
265337
*/
266338
EXIT,
267339

340+
/**
341+
* @deprecated since alpha release, replaced by ALLOW_UNSAFE_STARTUP for consistency with FailurePolicy.ALLOW_UNSAFE_STARTUP
342+
*/
343+
@Deprecated(since="6.0")
344+
UNSAFE_STARTUP,
345+
268346
/**
269347
* If the start marker exceeds the stop marker startup, assuming the consensus log has been determined complete externally.
270348
* Note this is VERY UNSAFE if you care about isolation guarantees.
271349
*/
272-
UNSAFE_STARTUP,
350+
ALLOW_UNSAFE_STARTUP,
273351

274352
REBOOTSTRAP
275353
}
@@ -290,7 +368,7 @@ public enum StopMarkerFailurePolicy
290368
public Version version = Version.DOWNGRADE_SAFE_VERSION;
291369
public boolean enable_compaction = true;
292370

293-
public JournalSpec setFlushPeriod(DurationSpec newFlushPeriod)
371+
public JournalConfig setFlushPeriod(DurationSpec newFlushPeriod)
294372
{
295373
flushPeriod = newFlushPeriod;
296374
flushCombinedBlockPeriod = Long.MIN_VALUE;

src/java/org/apache/cassandra/config/CassandraRelevantProperties.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public enum CassandraRelevantProperties
4444
{
4545
ACCORD_AGENT_CLASS("cassandra.test.accord.agent"),
4646
ACCORD_ALLOW_TEST_MODES("cassandra.test.accord.allow_test_modes", "false"),
47+
ACCORD_DEBUG_EXECUTION("accord.debug_execution"),
4748
ACCORD_KEY_PARANOIA_COSTFACTOR(Invariants.KEY_PARANOIA_COSTFACTOR),
4849
ACCORD_KEY_PARANOIA_CPU(Invariants.KEY_PARANOIA_CPU),
4950
ACCORD_KEY_PARANOIA_MEMORY(Invariants.KEY_PARANOIA_MEMORY),

src/java/org/apache/cassandra/config/Config.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,6 @@ public static Set<String> splitCommaDelimited(String src)
165165
@Replaces(oldName = "cas_contention_timeout_in_ms", converter = Converters.MILLIS_DURATION_LONG, deprecated = true)
166166
public volatile DurationSpec.LongMillisecondsBound cas_contention_timeout = new DurationSpec.LongMillisecondsBound("1800ms");
167167

168-
public volatile DurationSpec.LongMillisecondsBound accord_preaccept_timeout = new DurationSpec.LongMillisecondsBound("1s");
169-
170168
@Replaces(oldName = "truncate_request_timeout_in_ms", converter = Converters.MILLIS_DURATION_LONG, deprecated = true)
171169
public volatile DurationSpec.LongMillisecondsBound truncate_request_timeout = new DurationSpec.LongMillisecondsBound("60000ms");
172170

@@ -1238,7 +1236,7 @@ public enum PaxosOnLinearizabilityViolation
12381236
*/
12391237
public ParameterizedClass default_compaction = null;
12401238

1241-
public final AccordSpec accord = new AccordSpec();
1239+
public final AccordConfig accord = new AccordConfig();
12421240

12431241
public static Supplier<Config> getOverrideLoadConfig()
12441242
{

src/java/org/apache/cassandra/config/DatabaseDescriptor.java

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
import org.apache.cassandra.service.FileSystemOwnershipCheck;
127127
import org.apache.cassandra.service.StartupChecks;
128128
import org.apache.cassandra.service.StorageService;
129+
import org.apache.cassandra.service.accord.AccordService;
129130
import org.apache.cassandra.service.accord.api.AccordWaitStrategies;
130131
import org.apache.cassandra.service.consensus.TransactionalMode;
131132
import org.apache.cassandra.service.paxos.Paxos;
@@ -574,7 +575,7 @@ private static void applyAll() throws ConfigurationException
574575

575576
applyGuardrails();
576577

577-
applyAccordProgressLog();
578+
applyAccord();
578579

579580
applyStartupChecks();
580581
}
@@ -1370,7 +1371,7 @@ private static void applyGuardrails()
13701371
}
13711372
}
13721373

1373-
private static void applyAccordProgressLog()
1374+
private static void applyAccord()
13741375
{
13751376
try
13761377
{
@@ -1382,6 +1383,7 @@ private static void applyAccordProgressLog()
13821383
{
13831384
throw new ConfigurationException("Invalid accord progress log configuration: " + e.getMessage(), e);
13841385
}
1386+
AccordService.applyProtocolModifiers(getAccord());
13851387
}
13861388

13871389
public static StartupChecksConfiguration getStartupChecksConfiguration()
@@ -1663,12 +1665,6 @@ static void checkForLowestAcceptedTimeouts(Config conf)
16631665
logInfo("truncate_request_timeout", conf.truncate_request_timeout, LOWEST_ACCEPTED_TIMEOUT);
16641666
conf.truncate_request_timeout = LOWEST_ACCEPTED_TIMEOUT;
16651667
}
1666-
1667-
if (conf.accord_preaccept_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
1668-
{
1669-
logInfo("accord_preaccept_timeout", conf.accord_preaccept_timeout, LOWEST_ACCEPTED_TIMEOUT);
1670-
conf.accord_preaccept_timeout = LOWEST_ACCEPTED_TIMEOUT;
1671-
}
16721668
}
16731669

16741670
private static void logInfo(String property, DurationSpec.LongMillisecondsBound actualValue, DurationSpec.LongMillisecondsBound lowestAcceptedValue)
@@ -5634,18 +5630,17 @@ public static void setUseStatementsEnabled(boolean enabled)
56345630
}
56355631
}
56365632

5637-
5638-
public static AccordSpec getAccord()
5633+
public static AccordConfig getAccord()
56395634
{
56405635
return conf.accord;
56415636
}
56425637

5643-
public static AccordSpec.TransactionalRangeMigration getTransactionalRangeMigration()
5638+
public static AccordConfig.TransactionalRangeMigration getTransactionalRangeMigration()
56445639
{
56455640
return conf.accord.range_migration;
56465641
}
56475642

5648-
public static void setTransactionalRangeMigration(AccordSpec.TransactionalRangeMigration val)
5643+
public static void setTransactionalRangeMigration(AccordConfig.TransactionalRangeMigration val)
56495644
{
56505645
conf.accord.range_migration = Preconditions.checkNotNull(val);
56515646
}
@@ -5670,12 +5665,12 @@ public static void setAccordTransactionsEnabled(boolean b)
56705665
conf.accord.enabled = b;
56715666
}
56725667

5673-
public static AccordSpec.QueueShardModel getAccordQueueShardModel()
5668+
public static AccordConfig.QueueShardModel getAccordQueueShardModel()
56745669
{
56755670
return conf.accord.queue_shard_model;
56765671
}
56775672

5678-
public static AccordSpec.QueueSubmissionModel getAccordQueueSubmissionModel()
5673+
public static AccordConfig.QueueSubmissionModel getAccordQueueSubmissionModel()
56795674
{
56805675
return conf.accord.queue_submission_model;
56815676
}
@@ -6278,7 +6273,7 @@ public static void setPaxosRepairRaceWait(boolean paxosRepairRaceWait)
62786273

62796274
public static boolean getAccordEphemeralReadEnabledEnabled()
62806275
{
6281-
return conf.accord.ephemeralReadEnabled;
6276+
return conf.accord.ephemeral_reads;
62826277
}
62836278

62846279
public static AutoRepairConfig getAutoRepairConfig()

src/java/org/apache/cassandra/cql3/Attributes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,9 @@ public int getTimeToLive(QueryOptions options, TableMetadata metadata) throws In
153153
public void collectMarkerSpecification(VariableSpecifications boundNames)
154154
{
155155
if (timestamp != null)
156-
timestamp.collectMarkerSpecification(boundNames);
156+
timestamp.collectMarkerSpecification(boundNames, this);
157157
if (timeToLive != null)
158-
timeToLive.collectMarkerSpecification(boundNames);
158+
timeToLive.collectMarkerSpecification(boundNames, this);
159159
}
160160

161161
public static class Raw

src/java/org/apache/cassandra/cql3/ColumnsExpression.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,10 +386,10 @@ public boolean isMapElementExpression()
386386
* @param boundNames the variables specification where to collect the
387387
* bind variables of the map key/collection element in.
388388
*/
389-
public void collectMarkerSpecification(VariableSpecifications boundNames)
389+
public void collectMarkerSpecification(VariableSpecifications boundNames, Object owner)
390390
{
391391
if (element != null)
392-
element.collectMarkerSpecification(boundNames);
392+
element.collectMarkerSpecification(boundNames, owner);
393393
}
394394

395395
/**

src/java/org/apache/cassandra/cql3/ElementExpression.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,9 @@ public AbstractType<?> type()
140140
* @param boundNames the variables specification where to collect the
141141
* bind variables of the map key/collection element in.
142142
*/
143-
public void collectMarkerSpecification(VariableSpecifications boundNames)
143+
public void collectMarkerSpecification(VariableSpecifications boundNames, Object owner)
144144
{
145-
keyOrIndex.collectMarkerSpecification(boundNames);
145+
keyOrIndex.collectMarkerSpecification(boundNames, owner);
146146
}
147147

148148
/**

src/java/org/apache/cassandra/cql3/Json.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public Marker(int bindIndex)
8686

8787
public Prepared prepareAndCollectMarkers(TableMetadata metadata, Collection<ColumnMetadata> receivers, VariableSpecifications boundNames)
8888
{
89-
boundNames.add(bindIndex, makeReceiver(metadata));
89+
boundNames.add(bindIndex, makeReceiver(metadata), null);
9090
return new PreparedMarker(bindIndex, receivers);
9191
}
9292

@@ -239,7 +239,7 @@ public DelayedColumnValue(PreparedMarker prepared, ColumnMetadata column, boolea
239239
}
240240

241241
@Override
242-
public void collectMarkerSpecification(VariableSpecifications boundNames)
242+
public void collectMarkerSpecification(VariableSpecifications boundNames, Object owner)
243243
{
244244
// We've already collected what we should (and in practice this method is never called).
245245
}

0 commit comments

Comments
 (0)