mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-25 14:53:37 +00:00
Quorum based failover (#2668)
To enable quorum commit: ```diff $ patronictl.py edit-config --- +++ @@ -5,3 +5,4 @@ use_pg_rewind: true retry_timeout: 10 ttl: 30 +synchronous_mode: quorum Apply these changes? [y/N]: y Configuration changed ``` By default Patroni will use `ANY 1(list,of,stanbys)` in `synchronous_standby_names`. That is, only one node out of listed replicas will be used for quorum. If you want to increase the number of quorum nodes it is possible to do it with: ```diff $ patronictl edit-config --- +++ @@ -6,3 +6,4 @@ retry_timeout: 10 synchronous_mode: quorum ttl: 30 +synchronous_node_count: 2 Apply these changes? [y/N]: y Configuration changed ``` Good old `synchronous_mode: on` is still supported. Close https://github.com/patroni/patroni/issues/664 Close https://github.com/zalando/patroni/pull/672
This commit is contained in:
+54
-52
@@ -34,6 +34,8 @@ There are only a few simple rules you need to follow:
|
||||
|
||||
After that you just need to start Patroni and it will handle the rest:
|
||||
|
||||
0. Patroni will set ``bootstrap.dcs.synchronous_mode`` to :ref:`quorum <quorum_mode>`
|
||||
if it is not explicitly set to any other value.
|
||||
1. ``citus`` extension will be automatically added to ``shared_preload_libraries``.
|
||||
2. If ``max_prepared_transactions`` isn't explicitly set in the global
|
||||
:ref:`dynamic configuration <dynamic_configuration>` Patroni will
|
||||
@@ -77,36 +79,36 @@ It results in two major differences in :ref:`patronictl` behaviour when
|
||||
An example of :ref:`patronictl_list` output for the Citus cluster::
|
||||
|
||||
postgres@coord1:~$ patronictl list demo
|
||||
+ Citus cluster: demo ----------+--------------+---------+----+-----------+
|
||||
| Group | Member | Host | Role | State | TL | Lag in MB |
|
||||
+-------+---------+-------------+--------------+---------+----+-----------+
|
||||
| 0 | coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
|
||||
| 0 | coord2 | 172.27.0.6 | Sync Standby | running | 1 | 0 |
|
||||
| 0 | coord3 | 172.27.0.4 | Leader | running | 1 | |
|
||||
| 1 | work1-1 | 172.27.0.8 | Sync Standby | running | 1 | 0 |
|
||||
| 1 | work1-2 | 172.27.0.2 | Leader | running | 1 | |
|
||||
| 2 | work2-1 | 172.27.0.5 | Sync Standby | running | 1 | 0 |
|
||||
| 2 | work2-2 | 172.27.0.7 | Leader | running | 1 | |
|
||||
+-------+---------+-------------+--------------+---------+----+-----------+
|
||||
+ Citus cluster: demo ----------+----------------+---------+----+-----------+
|
||||
| Group | Member | Host | Role | State | TL | Lag in MB |
|
||||
+-------+---------+-------------+----------------+---------+----+-----------+
|
||||
| 0 | coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
|
||||
| 0 | coord2 | 172.27.0.6 | Quorum Standby | running | 1 | 0 |
|
||||
| 0 | coord3 | 172.27.0.4 | Leader | running | 1 | |
|
||||
| 1 | work1-1 | 172.27.0.8 | Quorum Standby | running | 1 | 0 |
|
||||
| 1 | work1-2 | 172.27.0.2 | Leader | running | 1 | |
|
||||
| 2 | work2-1 | 172.27.0.5 | Quorum Standby | running | 1 | 0 |
|
||||
| 2 | work2-2 | 172.27.0.7 | Leader | running | 1 | |
|
||||
+-------+---------+-------------+----------------+---------+----+-----------+
|
||||
|
||||
If we add the ``--group`` option, the output will change to::
|
||||
|
||||
postgres@coord1:~$ patronictl list demo --group 0
|
||||
+ Citus cluster: demo (group: 0, 7179854923829112860) -----------+
|
||||
| Member | Host | Role | State | TL | Lag in MB |
|
||||
+--------+-------------+--------------+---------+----+-----------+
|
||||
| coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
|
||||
| coord2 | 172.27.0.6 | Sync Standby | running | 1 | 0 |
|
||||
| coord3 | 172.27.0.4 | Leader | running | 1 | |
|
||||
+--------+-------------+--------------+---------+----+-----------+
|
||||
+ Citus cluster: demo (group: 0, 7179854923829112860) -+-----------+
|
||||
| Member | Host | Role | State | TL | Lag in MB |
|
||||
+--------+-------------+----------------+---------+----+-----------+
|
||||
| coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
|
||||
| coord2 | 172.27.0.6 | Quorum Standby | running | 1 | 0 |
|
||||
| coord3 | 172.27.0.4 | Leader | running | 1 | |
|
||||
+--------+-------------+----------------+---------+----+-----------+
|
||||
|
||||
postgres@coord1:~$ patronictl list demo --group 1
|
||||
+ Citus cluster: demo (group: 1, 7179854923881963547) -----------+
|
||||
| Member | Host | Role | State | TL | Lag in MB |
|
||||
+---------+------------+--------------+---------+----+-----------+
|
||||
| work1-1 | 172.27.0.8 | Sync Standby | running | 1 | 0 |
|
||||
| work1-2 | 172.27.0.2 | Leader | running | 1 | |
|
||||
+---------+------------+--------------+---------+----+-----------+
|
||||
+ Citus cluster: demo (group: 1, 7179854923881963547) -+-----------+
|
||||
| Member | Host | Role | State | TL | Lag in MB |
|
||||
+---------+------------+----------------+---------+----+-----------+
|
||||
| work1-1 | 172.27.0.8 | Quorum Standby | running | 1 | 0 |
|
||||
| work1-2 | 172.27.0.2 | Leader | running | 1 | |
|
||||
+---------+------------+----------------+---------+----+-----------+
|
||||
|
||||
Citus worker switchover
|
||||
-----------------------
|
||||
@@ -122,28 +124,28 @@ new primary worker node is ready to accept read-write queries.
|
||||
An example of :ref:`patronictl_switchover` on the worker cluster::
|
||||
|
||||
postgres@coord1:~$ patronictl switchover demo
|
||||
+ Citus cluster: demo ----------+--------------+---------+----+-----------+
|
||||
| Group | Member | Host | Role | State | TL | Lag in MB |
|
||||
+-------+---------+-------------+--------------+---------+----+-----------+
|
||||
| 0 | coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
|
||||
| 0 | coord2 | 172.27.0.6 | Sync Standby | running | 1 | 0 |
|
||||
| 0 | coord3 | 172.27.0.4 | Leader | running | 1 | |
|
||||
| 1 | work1-1 | 172.27.0.8 | Leader | running | 1 | |
|
||||
| 1 | work1-2 | 172.27.0.2 | Sync Standby | running | 1 | 0 |
|
||||
| 2 | work2-1 | 172.27.0.5 | Sync Standby | running | 1 | 0 |
|
||||
| 2 | work2-2 | 172.27.0.7 | Leader | running | 1 | |
|
||||
+-------+---------+-------------+--------------+---------+----+-----------+
|
||||
+ Citus cluster: demo ----------+----------------+---------+----+-----------+
|
||||
| Group | Member | Host | Role | State | TL | Lag in MB |
|
||||
+-------+---------+-------------+----------------+---------+----+-----------+
|
||||
| 0 | coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
|
||||
| 0 | coord2 | 172.27.0.6 | Quorum Standby | running | 1 | 0 |
|
||||
| 0 | coord3 | 172.27.0.4 | Leader | running | 1 | |
|
||||
| 1 | work1-1 | 172.27.0.8 | Leader | running | 1 | |
|
||||
| 1 | work1-2 | 172.27.0.2 | Quorum Standby | running | 1 | 0 |
|
||||
| 2 | work2-1 | 172.27.0.5 | Quorum Standby | running | 1 | 0 |
|
||||
| 2 | work2-2 | 172.27.0.7 | Leader | running | 1 | |
|
||||
+-------+---------+-------------+----------------+---------+----+-----------+
|
||||
Citus group: 2
|
||||
Primary [work2-2]:
|
||||
Candidate ['work2-1'] []:
|
||||
When should the switchover take place (e.g. 2022-12-22T08:02 ) [now]:
|
||||
Current cluster topology
|
||||
+ Citus cluster: demo (group: 2, 7179854924063375386) -----------+
|
||||
| Member | Host | Role | State | TL | Lag in MB |
|
||||
+---------+------------+--------------+---------+----+-----------+
|
||||
| work2-1 | 172.27.0.5 | Sync Standby | running | 1 | 0 |
|
||||
| work2-2 | 172.27.0.7 | Leader | running | 1 | |
|
||||
+---------+------------+--------------+---------+----+-----------+
|
||||
+ Citus cluster: demo (group: 2, 7179854924063375386) -+-----------+
|
||||
| Member | Host | Role | State | TL | Lag in MB |
|
||||
+---------+------------+----------------+---------+----+-----------+
|
||||
| work2-1 | 172.27.0.5 | Quorum Standby | running | 1 | 0 |
|
||||
| work2-2 | 172.27.0.7 | Leader | running | 1 | |
|
||||
+---------+------------+----------------+---------+----+-----------+
|
||||
Are you sure you want to switchover cluster demo, demoting current primary work2-2? [y/N]: y
|
||||
2022-12-22 07:02:40.33003 Successfully switched over to "work2-1"
|
||||
+ Citus cluster: demo (group: 2, 7179854924063375386) ------+
|
||||
@@ -154,17 +156,17 @@ An example of :ref:`patronictl_switchover` on the worker cluster::
|
||||
+---------+------------+---------+---------+----+-----------+
|
||||
|
||||
postgres@coord1:~$ patronictl list demo
|
||||
+ Citus cluster: demo ----------+--------------+---------+----+-----------+
|
||||
| Group | Member | Host | Role | State | TL | Lag in MB |
|
||||
+-------+---------+-------------+--------------+---------+----+-----------+
|
||||
| 0 | coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
|
||||
| 0 | coord2 | 172.27.0.6 | Sync Standby | running | 1 | 0 |
|
||||
| 0 | coord3 | 172.27.0.4 | Leader | running | 1 | |
|
||||
| 1 | work1-1 | 172.27.0.8 | Leader | running | 1 | |
|
||||
| 1 | work1-2 | 172.27.0.2 | Sync Standby | running | 1 | 0 |
|
||||
| 2 | work2-1 | 172.27.0.5 | Leader | running | 2 | |
|
||||
| 2 | work2-2 | 172.27.0.7 | Sync Standby | running | 2 | 0 |
|
||||
+-------+---------+-------------+--------------+---------+----+-----------+
|
||||
+ Citus cluster: demo ----------+----------------+---------+----+-----------+
|
||||
| Group | Member | Host | Role | State | TL | Lag in MB |
|
||||
+-------+---------+-------------+----------------+---------+----+-----------+
|
||||
| 0 | coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
|
||||
| 0 | coord2 | 172.27.0.6 | Quorum Standby | running | 1 | 0 |
|
||||
| 0 | coord3 | 172.27.0.4 | Leader | running | 1 | |
|
||||
| 1 | work1-1 | 172.27.0.8 | Leader | running | 1 | |
|
||||
| 1 | work1-2 | 172.27.0.2 | Quorum Standby | running | 1 | 0 |
|
||||
| 2 | work2-1 | 172.27.0.5 | Leader | running | 2 | |
|
||||
| 2 | work2-2 | 172.27.0.7 | Quorum Standby | running | 2 | 0 |
|
||||
+-------+---------+-------------+----------------+---------+----+-----------+
|
||||
|
||||
And this is how it looks on the coordinator side::
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ In order to change the dynamic configuration you can use either :ref:`patronictl
|
||||
- **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. In this mode a replica will be chosen as synchronous and only the latest leader and synchronous replica are able to participate in leader election. 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**:
|
||||
|
||||
+109
-12
@@ -6,8 +6,9 @@ Replication modes
|
||||
|
||||
Patroni uses PostgreSQL streaming replication. For more information about streaming replication, see the `Postgres documentation <http://www.postgresql.org/docs/current/static/warm-standby.html#STREAMING-REPLICATION>`__. By default Patroni configures PostgreSQL for asynchronous replication. Choosing your replication schema is dependent on your business considerations. Investigate both async and sync replication, as well as other HA solutions, to determine which solution is best for you.
|
||||
|
||||
|
||||
Asynchronous mode durability
|
||||
----------------------------
|
||||
============================
|
||||
|
||||
In asynchronous mode the cluster is allowed to lose some committed transactions to ensure availability. When the primary server fails or becomes unavailable for any other reason Patroni will automatically promote a sufficiently healthy standby to primary. Any transactions that have not been replicated to that standby remain in a "forked timeline" on the primary, and are effectively unrecoverable [1]_.
|
||||
|
||||
@@ -15,10 +16,11 @@ The amount of transactions that can be lost is controlled via ``maximum_lag_on_f
|
||||
|
||||
By default, when running leader elections, Patroni does not take into account the current timeline of replicas, what in some cases could be undesirable behavior. You can prevent the node not having the same timeline as a former primary become the new leader by changing the value of ``check_timeline`` parameter to ``true``.
|
||||
|
||||
PostgreSQL synchronous replication
|
||||
----------------------------------
|
||||
|
||||
You can use Postgres's `synchronous replication <http://www.postgresql.org/docs/current/static/warm-standby.html#SYNCHRONOUS-REPLICATION>`__ with Patroni. Synchronous replication ensures consistency across a cluster by confirming that writes are written to a secondary before returning to the connecting client with a success. The cost of synchronous replication: reduced throughput on writes. This throughput will be entirely based on network performance.
|
||||
PostgreSQL synchronous replication
|
||||
==================================
|
||||
|
||||
You can use Postgres's `synchronous replication <http://www.postgresql.org/docs/current/static/warm-standby.html#SYNCHRONOUS-REPLICATION>`__ with Patroni. Synchronous replication ensures consistency across a cluster by confirming that writes are written to a secondary before returning to the connecting client with a success. The cost of synchronous replication: increased latency and reduced throughput on writes. This throughput will be entirely based on network performance.
|
||||
|
||||
In hosted datacenter environments (like AWS, Rackspace, or any network you do not control), synchronous replication significantly increases the variability of write performance. If followers become inaccessible from the leader, the leader effectively becomes read-only.
|
||||
|
||||
@@ -33,10 +35,11 @@ When using PostgreSQL synchronous replication, use at least three Postgres data
|
||||
|
||||
Using PostgreSQL synchronous replication does not guarantee zero lost transactions under all circumstances. When the primary and the secondary that is currently acting as a synchronous replica fail simultaneously a third node that might not contain all transactions will be promoted.
|
||||
|
||||
|
||||
.. _synchronous_mode:
|
||||
|
||||
Synchronous mode
|
||||
----------------
|
||||
================
|
||||
|
||||
For use cases where losing committed transactions is not permissible you can turn on Patroni's ``synchronous_mode``. When ``synchronous_mode`` is turned on Patroni will not promote a standby unless it is certain that the standby contains all transactions that may have returned a successful commit status to client [2]_. This means that the system may be unavailable for writes even though some servers are available. System administrators can still use manual failover commands to promote a standby even if it results in transaction loss.
|
||||
|
||||
@@ -55,28 +58,122 @@ up.
|
||||
|
||||
You can ensure that a standby never becomes the synchronous standby by setting ``nosync`` tag to true. This is recommended to set for standbys that are behind slow network connections and would cause performance degradation when becoming a synchronous standby. Setting tag ``nostream`` to true will also have the same effect.
|
||||
|
||||
Synchronous mode can be switched on and off via Patroni REST interface. See :ref:`dynamic configuration <dynamic_configuration>` for instructions.
|
||||
Synchronous mode can be switched on and off using ``patronictl edit-config`` command or via Patroni REST interface. See :ref:`dynamic configuration <dynamic_configuration>` for instructions.
|
||||
|
||||
Note: Because of the way synchronous replication is implemented in PostgreSQL it is still possible to lose transactions even when using ``synchronous_mode_strict``. If the PostgreSQL backend is cancelled while waiting to acknowledge replication (as a result of packet cancellation due to client timeout or backend failure) transaction changes become visible for other backends. Such changes are not yet replicated and may be lost in case of standby promotion.
|
||||
|
||||
|
||||
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.
|
||||
==============================
|
||||
|
||||
The parameter ``synchronous_node_count`` is used by Patroni to manage the 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 the 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.
|
||||
|
||||
|
||||
Maximum lag on synchronous node
|
||||
===============================
|
||||
|
||||
By default Patroni sticks to nodes that are declared as ``synchronous``, according to the ``pg_stat_replication`` view, 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. The default is ``-1``, and Patroni will not take action to swap a synchronous unhealthy standby when the value is set to ``0`` or less. Please set the value high enough so that Patroni won't swap synchronous standbys frequently during high transaction volume.
|
||||
|
||||
|
||||
Synchronous mode implementation
|
||||
-------------------------------
|
||||
===============================
|
||||
|
||||
When in synchronous mode Patroni maintains synchronization state in the DCS, containing the latest primary and current synchronous standby databases. This state is updated with strict ordering constraints to ensure the following invariants:
|
||||
When in synchronous mode Patroni maintains synchronization state in the DCS (``/sync`` key), containing the latest primary and current synchronous standby databases. This state is updated with strict ordering constraints to ensure the following invariants:
|
||||
|
||||
- A node must be marked as the latest leader whenever it can accept write transactions. Patroni crashing or PostgreSQL not shutting down can cause violations of this invariant.
|
||||
|
||||
- A node must be set as the synchronous standby in PostgreSQL as long as it is published as the synchronous standby.
|
||||
- A node must be set as the synchronous standby in PostgreSQL as long as it is published as the synchronous standby in the ``/sync`` key in DCS..
|
||||
|
||||
- A node that is not the leader or current synchronous standby is not allowed to promote itself automatically.
|
||||
|
||||
Patroni will only assign one or more synchronous standby nodes based on ``synchronous_node_count`` parameter to ``synchronous_standby_names``.
|
||||
|
||||
On each HA loop iteration Patroni re-evaluates synchronous standby nodes choice. If the current list of synchronous standby nodes are connected and has not requested its synchronous status to be removed it remains picked. Otherwise the cluster member available for sync that is furthest ahead in replication is picked.
|
||||
On each HA loop iteration Patroni re-evaluates synchronous standby nodes choice. If the current list of synchronous standby nodes are connected and has not requested its synchronous status to be removed it remains picked. Otherwise the cluster members available for sync that are furthest ahead in replication are picked.
|
||||
|
||||
Example:
|
||||
---------
|
||||
|
||||
``/config`` key in DCS
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: YAML
|
||||
|
||||
synchronous_mode: on
|
||||
synchronous_node_count: 2
|
||||
...
|
||||
|
||||
``/sync`` key in DCS
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: JSON
|
||||
|
||||
{
|
||||
"leader": "node0",
|
||||
"sync_standby": "node1,node2"
|
||||
}
|
||||
|
||||
postgresql.conf
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: INI
|
||||
|
||||
synchronous_standby_names = 'FIRST 2 (node1,node2)'
|
||||
|
||||
|
||||
In the above examples only nodes ``node1`` and ``node2`` are known to be synchronous and allowed to be automatically promoted if the primary (``node0``) fails.
|
||||
|
||||
|
||||
.. _quorum_mode:
|
||||
|
||||
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, 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.
|
||||
|
||||
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.
|
||||
|
||||
Other parameters, like ``synchronous_node_count``, ``maximum_lag_on_syncnode``, and ``synchronous_mode_strict`` continue to work the same way as with ``synchronous_mode=on``.
|
||||
|
||||
Example:
|
||||
---------
|
||||
|
||||
``/config`` key in DCS
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: YAML
|
||||
|
||||
synchronous_mode: quorum
|
||||
synchronous_node_count: 2
|
||||
...
|
||||
|
||||
``/sync`` key in DCS
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: JSON
|
||||
|
||||
{
|
||||
"leader": "node0",
|
||||
"sync_standby": "node1,node2,node3",
|
||||
"quorum": 1
|
||||
}
|
||||
|
||||
postgresql.conf
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: INI
|
||||
|
||||
synchronous_standby_names = 'ANY 2 (node1,node2,node3)'
|
||||
|
||||
|
||||
If the primary (``node0``) failed, in the above example two of the ``node1``, ``node2``, ``node3`` will have the latest transaction received, but we don't know which ones. To figure out whether the node ``node1`` has received the latest transaction, we need to compare its LSN with the LSN on **at least** one node (``quorum=1`` in the ``/sync`` key) among ``node2`` and ``node3``. If ``node1`` isn't behind of at least one of them, we can guarantee that there will be no user visible data loss if ``node1`` is promoted.
|
||||
|
||||
|
||||
.. [1] The data is still there, but recovering it requires a manual recovery effort by data recovery specialists. When Patroni is allowed to rewind with ``use_pg_rewind`` the forked timeline will be automatically erased to rejoin the failed primary with the cluster. However, for ``use_pg_rewind`` to function properly, either the cluster must be initialized with ``data page checksums`` (``--data-checksums`` option for ``initdb``) and/or ``wal_log_hints`` must be set to ``on``.
|
||||
|
||||
@@ -45,6 +45,10 @@ For all health check ``GET`` requests Patroni returns a JSON document with the s
|
||||
|
||||
- ``GET /read-only-sync``: like the above endpoint, but also includes the primary.
|
||||
|
||||
- ``GET /quorum``: returns HTTP status code **200** only when this Patroni node is listed as a quorum node in ``synchronous_standby_names`` on the primary.
|
||||
|
||||
- ``GET /read-only-quorum``: like the above endpoint, but also includes the primary.
|
||||
|
||||
- ``GET /asynchronous`` or ``GET /async``: returns HTTP status code **200** only when the Patroni node is running as an asynchronous standby.
|
||||
|
||||
|
||||
@@ -308,6 +312,9 @@ Retrieve the Patroni metrics in Prometheus format through the ``GET /metrics`` e
|
||||
# HELP patroni_sync_standby Value is 1 if this node is a sync standby replica, 0 otherwise.
|
||||
# TYPE patroni_sync_standby gauge
|
||||
patroni_sync_standby{scope="batman",name="patroni1"} 0
|
||||
# HELP patroni_quorum_standby Value is 1 if this node is a quorum standby replica, 0 otherwise.
|
||||
# TYPE patroni_quorum_standby gauge
|
||||
patroni_quorum_standby{scope="batman",name="patroni1"} 0
|
||||
# HELP patroni_xlog_received_location Current location of the received Postgres transaction log, 0 if this node is not a replica.
|
||||
# TYPE patroni_xlog_received_location counter
|
||||
patroni_xlog_received_location{scope="batman",name="patroni1"} 0
|
||||
|
||||
Reference in New Issue
Block a user