Repository navigation
0.6.1 fixes a stall in Quorum publishes. A fresh 0.6.0 cluster finalizes
majority_ack, and under load a Quorum stream on three or more brokers could
then stall for up to the replication tick (2 s by default) before its publishes
were acknowledged (#1479). Upgrading is recommended for anyone running Quorum
on three or more brokers. The release also closes a placement race when a
stream's consistency changes (#1253), makes a forward refuse a stream recreated
under the same name (#1324), and brings back the small-batch fire-and-forget
throughput that 0.6.0 listed as a known issue (#1469).
Upgrading.
- Under a Raft control plane, the consistency-change fence (#1253) takes effect
once every member runs 0.6.1 (metadata level 19). Until then a change of
consistency fences nothing, as in 0.6.0. - A Postgres control plane runs migration
0036on start. - The forward incarnation check (#1324) applies between brokers that both run
0.6.1, which offer theFORWARD_INCARNATIONpeer capability. A forward to a
0.6.0 broker is sent as before and checked by generation alone.
Added
- A write can name its shard instead of hashing a key (#1465).
publish,publish_batch,
publish_idempotent,publish_if,commitandstate_gettake an optionalshard,
negotiated asFEATURE_EXPLICIT_SHARD(bit0x8of the extended feature word). A shard the
stream does not have is refused withinvalid_requestand nothing is written. The Rust client
addspublish_on_shardandpublish_batch_on_shard(Publisher,ClusterClient), and
commit_on_shard,commit_if_on_shard,publish_if_on_shardandstate_get_on_shard
(Client,ClusterClient).ClusterClientsends each to the named shard's owner or leader.
They fail without sending against a broker that did not advertise the bit. Caches and counters
take no shard. - Metrics for what a
Quorumacknowledgement waits on (#1479):
felix_broker_publish_quorum_wait_seconds, how long a publish waited for its
majority, andfelix_storage_replica_state_writes_totalwith
felix_storage_replica_state_write_duration_seconds, the replica-state writes
a follower makes for commit offsets.
Fixed
- Changing a stream's consistency or durability now fences placement passes
that read the stream before the change (#1253). A pass that read aQuorum
stream could otherwise replace its leader on its followers' word after the
stream becameLeaderand the leader was serving on its lease, leaving two
brokers serving. Postgres gets migration 0036; under Raft it applies once
every member is at metadata level 19. - A forwarded publish or cache op now names the incarnation of the stream or
cache its route was for, and the owner refuses one for another incarnation
(#1324). Before, a forward routed by a deleted stream's assignment could land
in a stream recreated at the same generation, which a control-plane restore
makes possible. Sent only to brokers that offerFORWARD_INCARNATION. - A leader that crashed under
PeriodicorNoneno longer answers its
successor's fence just because the routes now show a set of two (#1336). The
set can shrink from three to two under the same leader, and a record the
three acknowledged may be on neither copy. It answers only when the
generation it led had those same two copies and its own last record is from
that generation. - A subscribe from
lateston a durable stream whose log ends in generation-start
records now reportsstart_offsetandlive_offsetjust past the last event,
not at the raw tail (#1475). Those records are never delivered, so a client that
read history up tolive_offset - 1after joining atlatestwaited forever,
which on a 0.6.0 cluster is any Quorum shard with no write since its leader
started. A client that negotiatedFLAG_EVENT_BATCH_SKIPPEDcounts no drop at
the join. A client with offsets but without it now reads one false drop per
trailing generation start at alatestjoin, as it already did mid-stream.
Count drops before the first event asoffset - start_offset - skipped_before:
start_offsetcan be 0. - A
Quorumstream on three or more brokers no longer stalls for up to the
replication tick (2 s by default) under load (#1479). A follower's answer that
arrived after the pass that asked for it moved no cursor, so no pass counted
it, and with every publisher waiting on the mark nothing else started one.
Such an answer now starts a pass, and a pass waiting for a majority counts a
busy follower's answer itself instead of only giving up on it. The stall was
most visible oncemajority_ackis finalized: 256 B durable publishes at 64
in flight fell 38% with a p999 of 1.86 s.
Performance
- A replicated durable shard no longer writes its replica state on the
acknowledgement path underfsync_mode = on_commit(#1456). The commit offset
is written behind, and one write in flight carries every advance made while it
runs, so aQuorumack costs one data fsync per replica instead of about
three. After a crash the commit offset can read back one write behind; the
accepted generation is still on disk before a fence is answered. - Fire-and-forget publishes of small batches under
pub_ingress_waitare back to the throughput the
0.6.0 performance runs measured (#1469). A control stream now parks at most 16 unacked publishes while it
waits for queue room; past that it waits inline. With the acked cap of 1024, a busy broker's
streams parked until the process-wide byte budget ran out, and every publish then waited on
that budget: 256 B batch-64 fire-and-forget lost 13%.
The trade-off: a fire-and-forget stream to one full shard stops reading after 16 frames
instead of after the byte budget runs out, and with the default stream window it can then
hold the connection's flow-control credit and stall the connection's other streams.