From c7f3b4e62c34138c1d61355b8c7f1f247d8c79ab Mon Sep 17 00:00:00 2001 From: anastasia Date: Wed, 10 Nov 2021 00:12:08 +0300 Subject: [PATCH] Clarify the meaning of StandbyReply LSNs: write_lsn - The last LSN received and processed by pageserver's walreceiver. flush_lsn - same as write_lsn. At pageserver it doesn't guarantees data persistence, but it's fine. We rely on safekeepers. apply_lsn - The LSN at which pageserver guaranteed persistence of all received data (disk_consistent_lsn). --- pageserver/src/walreceiver.rs | 24 +++++++++++++++++------- vendor/postgres | 2 +- walkeeper/src/replication.rs | 8 ++++---- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/pageserver/src/walreceiver.rs b/pageserver/src/walreceiver.rs index 1f84ed8507..ba4f1aa1e5 100644 --- a/pageserver/src/walreceiver.rs +++ b/pageserver/src/walreceiver.rs @@ -321,14 +321,24 @@ fn walreceiver_main( }; if let Some(last_lsn) = status_update { - // TODO: More thought should go into what values are sent here. let last_lsn = PgLsn::from(u64::from(last_lsn)); - // We are using disk consistent LSN as `write_lsn`, i.e. LSN at which page server - // may guarantee persistence of all received data. Safekeeper is not free to remove - // WAL preceding `write_lsn`: it should not be requested by this page server. - let write_lsn = PgLsn::from(u64::from(timeline.get_disk_consistent_lsn())); - let flush_lsn = last_lsn; - let apply_lsn = PgLsn::from(0); + + // The last LSN we processed. It is not guaranteed to survive pageserver crash. + let write_lsn = last_lsn; + // This value doesn't guarantee data durability, but it's ok. + // In setup with WAL service, pageserver durability is guaranteed by safekeepers. + // In setup without WAL service, we just don't care. + let flush_lsn = write_lsn; + // `disk_consistent_lsn` is the LSN at which page server guarantees persistence of all received data + // Depending on the setup we recieve WAL directly from Compute Node or + // from a WAL service. + // + // Senders use the feedback to determine if we are caught up: + // - Safekeepers are free to remove WAL preceding `apply_lsn`, + // as it will never be requested by this page server. + // - Compute Node uses 'apply_lsn' to calculate a lag for back pressure mechanism + // (delay WAL inserts to avoid lagging pageserver responses and WAL overflow). + let apply_lsn = PgLsn::from(u64::from(timeline.get_disk_consistent_lsn())); let ts = SystemTime::now(); const NO_REPLY: u8 = 0; physical_stream.standby_status_update(write_lsn, flush_lsn, apply_lsn, ts, NO_REPLY)?; diff --git a/vendor/postgres b/vendor/postgres index a70d892bb9..da7459982c 160000 --- a/vendor/postgres +++ b/vendor/postgres @@ -1 +1 @@ -Subproject commit a70d892bb93e0a8a6cda8a8fccd4e4fbf408ea79 +Subproject commit da7459982caf933db266109c363b655b5c1be56d diff --git a/walkeeper/src/replication.rs b/walkeeper/src/replication.rs index 9f9e974336..f3486e2885 100644 --- a/walkeeper/src/replication.rs +++ b/walkeeper/src/replication.rs @@ -55,9 +55,9 @@ impl HotStandbyFeedback { /// Standby status update #[derive(Debug, Clone, Serialize, Deserialize)] pub struct StandbyReply { - pub write_lsn: Lsn, // disk consistent lSN - pub flush_lsn: Lsn, // LSN committedby quorum - pub apply_lsn: Lsn, // not used + pub write_lsn: Lsn, // not used + pub flush_lsn: Lsn, // not used + pub apply_lsn: Lsn, // pageserver's disk consistent lSN pub reply_ts: TimestampTz, pub reply_requested: bool, } @@ -115,7 +115,7 @@ impl ReplicationConn { Some(STANDBY_STATUS_UPDATE_TAG_BYTE) => { let reply = StandbyReply::des(&m[1..]) .context("failed to deserialize StandbyReply")?; - state.disk_consistent_lsn = reply.write_lsn; + state.disk_consistent_lsn = reply.apply_lsn; timeline.update_replica_state(replica, Some(state)); } _ => warn!("unexpected message {:?}", msg),