Apply suggestions from code review

Co-authored-by: Matt Baker <[email protected]>
Co-authored-by: Israel <[email protected]>
This commit is contained in:
Alexander Kukushkin
2023-07-20 07:03:22 +02:00
committed by GitHub
co-authored by Matt Baker Israel
parent 300740c919
commit ad4bea7e56
4 changed files with 19 additions and 17 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ In order to change the dynamic configuration you can use either ``patronictl edi
- **max\_timelines\_history**: maximum number of timeline history items kept in DCS. Default value: 0. When set to 0, it keeps the full history in DCS.
- **primary\_start\_timeout**: the amount of time a primary is allowed to recover from failures before failover is triggered (in seconds). Default is 300 seconds. When set to 0 failover is done immediately after a crash is detected if possible. When using asynchronous replication a failover can cause lost transactions. Worst case failover time for primary failure is: loop\_wait + primary\_start\_timeout + loop\_wait, unless primary\_start\_timeout is zero, in which case it's just loop\_wait. Set the value according to your durability/availability tradeoff.
- **primary\_stop\_timeout**: The number of seconds Patroni is allowed to wait when stopping Postgres and effective only when synchronous_mode is enabled. When set to > 0 and the synchronous_mode is enabled, Patroni sends SIGKILL to the postmaster if the stop operation is running for more than the value set by primary\_stop\_timeout. Set the value according to your durability/availability tradeoff. If the parameter is not set or set <= 0, primary\_stop\_timeout does not apply.
- **synchronous\_mode**: turns on synchronous replication mode. Possible values: ``off``, ``on``, ``quorum``. In this mode the leader takes care about management of ``synchronous_standby_names`` and and only the last known leader or one of synchronous replicas are allowed to participate in leader race. Synchronous mode makes sure that successfully committed transactions will not be lost at failover, at the cost of losing availability for writes when Patroni cannot ensure transaction durability. See :ref:`replication modes documentation <replication_modes>` for details.
- **synchronous\_mode**: turns on synchronous replication mode. Possible values: ``off``, ``on``, ``quorum``. In this mode the leader takes care of management of ``synchronous_standby_names``, and only the last known leader, or one of synchronous replicas, are allowed to participate in leader race. Synchronous mode makes sure that successfully committed transactions will not be lost at failover, at the cost of losing availability for writes when Patroni cannot ensure transaction durability. See :ref:`replication modes documentation <replication_modes>` for details.
- **synchronous\_mode\_strict**: prevents disabling synchronous replication if no synchronous replicas are available, blocking all client writes to the primary. See :ref:`replication modes documentation <replication_modes>` for details.
- **failsafe\_mode**: Enables :ref:`DCS Failsafe Mode <dcs_failsafe_mode>`. Defaults to `false`.
- **postgresql**:
+6 -6
View File
@@ -66,15 +66,15 @@ Note: Because of the way synchronous replication is implemented in PostgreSQL it
Synchronous Replication Factor
==============================
The parameter ``synchronous_node_count`` is used by Patroni to manage number of synchronous standby databases. It is set to 1 by default. It has no effect when ``synchronous_mode`` is set to off. When enabled, Patroni manages precise number of synchronous standby databases based on parameter ``synchronous_node_count`` and adjusts the state in DCS & synchronous_standby_names as members join and leave. If the parameter is set to the value higher than the number of eligible nodes it will be automatically reduced by Patroni down to 1.
The parameter ``synchronous_node_count`` is used by Patroni to manage number of synchronous standby databases. It is set to 1 by default. It has no effect when ``synchronous_mode`` is set to off. When enabled, Patroni manages precise number of synchronous standby databases based on parameter ``synchronous_node_count`` and adjusts the state in DCS & ``synchronous_standby_names`` in PostgreSQL as members join and leave. If the parameter is set to a value higher than the number of eligible nodes it will be automatically reduced by Patroni down to 1.
Maximum lag on synchronous node
===============================
By default Patroni sticks to a node that is declared as ``synchronous`` according to the ``pg_stat_replication`` even when there are other nodes ahead of it. It is done to minimize the number of changes of ``synchronous_standby_names``. To change this behavior one may use ``maximum_lag_on_syncnode`` parameter. It controls how much the replica can lag in to be allowed chosen as synchronous.
By default Patroni sticks to a node that is declared as ``synchronous``, according to the setting ``pg_stat_replication``, even when there are other nodes ahead of it. This is done to minimize the number of changes of ``synchronous_standby_names``. To change this behavior one may use ``maximum_lag_on_syncnode`` parameter. It controls how much lag the replica can have to still be considered as "synchronous".
Patroni utilizes the max replica LSN if there is more than one standby, otherwise it will use leader's current wal LSN. Default is ``-1``, and Patroni will not take action to swap synchronous unhealthy standby when the value is set to 0 or below. Please set the value high enough so Patroni won't swap synchrounous standbys fequently during high transaction volume.
Patroni utilizes the max replica LSN if there is more than one standby, otherwise it will use leader's current wal LSN. The default is ``-1``, and Patroni will not take action to swap a synchronous unhealthy standby when the value is set to 0 or below. Please set the value high enough so that Patroni won't swap synchronous standbys frequently during high transaction volume.
Synchronous mode implementation
@@ -100,11 +100,11 @@ Quorum commit mode
Starting from PostgreSQL v10 Patroni supports quorum-based synchronous replication.
In this mode Patroni maintains synchronization state in the DCS, containing the latest known primary, number of nodes required for quorum and nodes currently eligible to vote on quorum. In steady state the nodes voting on quorum are the leader and all synchronous standbys. This state is updated with strict ordering constraints with regards to node promotion and ``synchronous_standby_names`` to ensure that at all times any subset of voters that can achieve quorum is contained to have at least one node having the latest successful commit.
In this mode, Patroni maintains synchronization state in the DCS, containing the latest known primary, the number of nodes required for quorum and the nodes currently eligible to vote on quorum. In steady state, the nodes voting on quorum are the leader and all synchronous standbys. This state is updated with strict ordering constraints, with regards to node promotion and ``synchronous_standby_names``, to ensure that at all times any subset of voters that can achieve quorum includes at least one node with the latest successful commit.
On each iteration of HA loop Patroni re-evaluates synchronous standby choices and quorum based on node availability and requested cluster configuration. In PostgreSQL versions above 9.6 all eligible nodes are added as synchronous standbys as soon as their replication catches up to leader.
On each iteration of HA loop, Patroni re-evaluates synchronous standby choices and quorum, based on node availability and requested cluster configuration. In PostgreSQL versions above 9.6 all eligible nodes are added as synchronous standbys as soon as their replication catches up to leader.
Quorum commit helps to reduce worst case latencies even during normal operation as a higher latency of replicating to one standby can be compensated by other standbys.
Quorum commit helps to reduce worst case latencies, even during normal operation, as a higher latency of replicating to one standby can be compensated by other standbys.
The quorum-based synchronous mode could be enabled by setting ``synchronous_mode`` to ``quorum`` using ``patronictl edit-config`` command or via Patroni REST interface. See :ref:`dynamic configuration <dynamic_configuration>` for instructions.
+11 -10
View File
@@ -745,7 +745,7 @@ class Ha(object):
logger.info("Synchronous replication key updated by someone else")
def process_sync_replication(self) -> None:
"""Process synchronous replication beahvior on the primary."""
"""Process synchronous replication behavior on the primary."""
if self.is_quorum_commit_mode():
# The synchronous_standby_names was adjusted right before promote.
# After that, when postgres has become a primary, we need to reflect this change
@@ -920,11 +920,11 @@ class Ha(object):
return promote_message
def fetch_node_status(self, member: Member) -> _MemberStatus:
"""This function performs http get request on member.api_url and fetches its status.
"""Perform http get request on member.api_url to fetch its status.
Usually it happens during the leader race and we can't afford wating for a response indefinite time,
therefore the request timeout is hardcoded to 2 seconds, which seems to be a good compromise.
The node which is slow to respond most likely will not be healthy.
Usually this happens during the leader race and we can't afford to wait an indefinite time
for a response, therefore the request timeout is hardcoded to 2 seconds, which seems to be a
good compromise. The node which is slow to respond is most likely unhealthy.
:returns: :class:`_MemberStatus` object
"""
@@ -987,7 +987,7 @@ class Ha(object):
return all(results)
def is_lagging(self, wal_position: int) -> bool:
"""Checks if node should consider itself unhealthy to be promoted due to replication lag.
"""Check if node should consider itself unhealthy to be promoted due to replication lag.
:param wal_position: Current wal position.
:returns `True` when node is lagging
@@ -996,14 +996,15 @@ class Ha(object):
return lag > self.global_config.maximum_lag_on_failover
def _is_healthiest_node(self, members: Collection[Member], check_replication_lag: bool = True) -> bool:
"""This method tries to determine whether the current node is healthy enough to became a new leader candidate.
"""Determine whether the current node is healthy enough to become a new leader candidate.
:param members: the list of nodes to check against
:param check_replication_lag: whether to take the replication lag into account.
If the lag exceeds configured threshold the node disqualifies itself.
:returns: `True` in case if the node is eligible to become the new leader. Since this method is executed
on multiple nodes independently it could happen that many nodes will count themselves as
healthiest because they received/replayed up to the same LSN, but it is totally fine.
:returns: `True` if the node is eligible to become the new leader. Since this method is executed
on multiple nodes independently it is possible that multiple nodes could count
themselves as the healthiest because they received/replayed up to the same LSN,
but this is totally fine.
"""
my_wal_position = self.state_handler.last_operation()
if check_replication_lag and self.is_lagging(my_wal_position):
+1
View File
@@ -266,6 +266,7 @@ END;$$""")
- `synchronous_node_count`: controlls how many nodes should be set as synchronous.
:param cluster: current cluster topology from DCS
:returns: current synchronous replication state as a :class:`_SyncState` object
"""
self._handle_synchronous_standby_names_change()