patroni.postgresql.sync module
- class patroni.postgresql.sync.SyncHandler(postgresql: Postgresql)View on GitHub
Bases:
objectClass responsible for working with the synchronous_standby_names.
Sync standbys are chosen based on their state in pg_stat_replication. When synchronous_standby_names is changed we memorize the _primary_flush_lsn and the current_state() method will count newly added names as “sync” only when they reached memorized LSN and also reported as “sync” by pg_stat_replication
- __init__(postgresql: Postgresql) NoneView on GitHub
- _handle_synchronous_standby_names_change() NoneView on GitHub
Handles changes of “synchronous_standby_names” GUC.
If “synchronous_standby_names” was changed, we need to check that newly added replicas have reached self._primary_flush_lsn. Only after that they could be counted as synchronous.
- _process_replica_readiness(cluster: Cluster, replica_list: _ReplicaList) NoneView on GitHub
Flags replicas as truly “synchronous” when they have caught up with
_primary_flush_lsn.- Parameters:
cluster – current cluster topology from DCS
replica_list – collection of replicas that we want to evaluate.
- current_state(cluster: Cluster) Tuple[CaseInsensitiveSet, CaseInsensitiveSet, int, CaseInsensitiveSet]View on GitHub
Find the best candidates to be the synchronous standbys.
Current synchronous standby is always preferred, unless it has disconnected or does not want to be a synchronous standby any longer.
Standbys are selected based on values from the global configuration:
maximum_lag_on_syncnode: would help swapping unhealthy sync replica in case if it stops responding (or hung). Please set the value high enough so it won’t unncessarily swap sync standbys during high loads. Any value less or equal of 0 keeps the behavior backward compatible. Please note that it will not also swap sync standbys in case where all replicas are hung.
synchronous_node_count: controlls how many nodes should be set as synchronous.
- Returns:
tuple of candidates
CaseInsensitiveSetand synchronous standbysCaseInsensitiveSet.
- set_synchronous_standby_names(sync: Collection[str]) NoneView on GitHub
Constructs and sets “synchronous_standby_names” GUC value.
- Parameters:
sync – set of nodes to sync to
- class patroni.postgresql.sync._Replica(pid: int, application_name: str, sync_state: str, lsn: int, nofailover: bool)View on GitHub
Bases:
NamedTupleClass representing a single replica that is eligible to be synchronous.
Attributes are taken from
pg_stat_replicationview and respectiveCluster.members.- Variables:
pid – PID of walsender process.
application_name – matches with the
Member.name.sync_state – possible values are:
async,potential,quorum, andsync.lsn –
write_lsn,flush_lsn, orreplay_lsn, depending on the value ofsynchronous_commitGUC.nofailover – whether the corresponding member has
nofailovertag set toTrue.
- _asdict()
Return a new dict which maps field names to their values.
- _field_defaults = {}
- _fields = ('pid', 'application_name', 'sync_state', 'lsn', 'nofailover')
- classmethod _make(iterable)
Make a new _Replica object from a sequence or iterable
- _replace(**kwds)
Return a new _Replica object replacing specified fields with new values
- class patroni.postgresql.sync._ReplicaList(postgresql: Postgresql, cluster: Cluster)View on GitHub
-
A collection of :class:
_Replicaobjects.Values are reverse ordered by
_Replica.sync_stateand_Replica.lsn. That is, first there will be replicas that havesync_state==sync, even if they are not the most up-to-date in term of write/flush/replay LSN. It helps to keep the result of choosing new synchronous nodes consistent in case if a synchronous standby member is slowed down OR async node is receiving changes faster than the sync member. Such cases would trigger sync standby member swapping, but only if lag on this member is exceeding a threshold (maximum_lag_on_syncnode).- Variables:
max_lsn – maximum value of
_Replica.lsnamong all values. In case if there is just one element in the list we take value ofpg_current_wal_flush_lsn().
- __init__(postgresql: Postgresql, cluster: Cluster) NoneView on GitHub
Create :class:
_ReplicaListobject.- Parameters:
postgresql – reference to :class:
Postgresqlobject.cluster – currently known cluster state from DCS.
- static _should_cascade(members: CaseInsensitiveDict, replication: CaseInsensitiveDict, member: Member) boolView on GitHub
Check whether member is supposed to cascade from another standby node.
- Parameters:
members – members that are eligible to stream (state=running and don’t have nosync tag)
replication – state of
pg_stat_replication, already filtered by member names from membersmember – member that we want to check
- Returns:
Trueif provided member should stream from other standby node in the cluster (according toreplicatefromtag), because some standbys in a chain already streaming from the primary, otherwiseFalse
- class patroni.postgresql.sync._SSN(sync_type: str, has_star: bool, num: int, members: CaseInsensitiveSet)View on GitHub
Bases:
NamedTupleclass representing “synchronous_standby_names” value after parsing.
- Variables:
sync_type – possible values: ‘off’, ‘priority’, ‘quorum’
has_star – is set to True if “synchronous_standby_names” contains ‘*’
num – how many nodes are required to be synchronous
members – collection of standby names listed in “synchronous_standby_names”
- _asdict()
Return a new dict which maps field names to their values.
- _field_defaults = {}
- _fields = ('sync_type', 'has_star', 'num', 'members')
- classmethod _make(iterable)
Make a new _SSN object from a sequence or iterable
- _replace(**kwds)
Return a new _SSN object replacing specified fields with new values
- members: CaseInsensitiveSet
Alias for field number 3
- patroni.postgresql.sync.parse_sync_standby_names(value: str) _SSNView on GitHub
Parse postgresql synchronous_standby_names to constituent parts.
- Parameters:
value – the value of synchronous_standby_names
- Returns:
_SSNobject- Raises:
ValueError – if the configuration value can not be parsed
>>> parse_sync_standby_names('').sync_type 'off'
>>> parse_sync_standby_names('FiRsT').sync_type 'priority'
>>> 'first' in parse_sync_standby_names('FiRsT').members True
>>> set(parse_sync_standby_names('"1"').members) {'1'}
>>> parse_sync_standby_names(' a , b ').members == {'a', 'b'} True
>>> parse_sync_standby_names(' a , b ').num 1
>>> parse_sync_standby_names('ANY 4("a",*,b)').has_star True
>>> parse_sync_standby_names('ANY 4("a",*,b)').num 4
>>> parse_sync_standby_names('1') Traceback (most recent call last): ... ValueError: Unparsable synchronous_standby_names value
>>> parse_sync_standby_names('a,') Traceback (most recent call last): ... ValueError: Unparsable synchronous_standby_names value
>>> parse_sync_standby_names('ANY 4("a" b,"c c")') Traceback (most recent call last): ... ValueError: Unparsable synchronous_standby_names value
>>> parse_sync_standby_names('FIRST 4("a",)') Traceback (most recent call last): ... ValueError: Unparsable synchronous_standby_names value
>>> parse_sync_standby_names('2 (,)') Traceback (most recent call last): ... ValueError: Unparsable synchronous_standby_names value
- patroni.postgresql.sync.quote_standby_name(value: str) strView on GitHub
Quote provided value if it is nenecessary.
- Parameters:
value – name of a synchronous standby.
- Returns:
a quoted value if it is required or the original one.