Skip to content

Commit 9b5a2d9

Browse files
committed
architecture doc, part #1
1 parent 05aff3e commit 9b5a2d9

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

Diff for: README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ cd ../../contrib/mmts && make install
6565

6666
### Docker
6767

68-
Directory contrib/mmts also includes docker-compose.yml that is capable of building multi-master and starting 3 node cluster.
68+
Directory contrib/mmts also includes docker-compose.yml that is capable of building multi-master and starting
69+
3 node cluster.
6970

7071
```sh
7172
cd contrib/mmts
@@ -136,7 +137,7 @@ Read description of all management functions at [functions](/contrib/mmts/doc/fu
136137

137138
* Commit latency.
138139
Current implementation of logical replication sends data to subscriber nodes only after local commit, so in case of
139-
heavy-write transaction user will wait for transaction processing two times: on local node and al other nodes
140+
heavy-write transaction user will wait for transaction processing two times: on local node and on all other nodes
140141
(simultaneosly). We have plans to address this issue in future.
141142

142143
* DDL replication.

Diff for: doc/architecture.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# `Multi-master architecture`
2+
3+
## Intro
4+
5+
Multi-master consists of two major subsystems: synchronous logical replication and hearbeat process that
6+
respostible for helth check and cluster recovery.
7+
8+
## Replication
9+
10+
When postgres loads multi-master shared library it sets up logical replication producer an consumer to each node in the cluster and hooks into transaction commit pipeline. Since each server can accept writes it is possible that any server can abort transaction due to concurrent update - in the same way as it happens on a single server between different backends. Usual way of dealing with such situations is to perform transaction in two steps: first try to ensure that commit is possible (PREPARE stage) and if all nodes acknowledged that then we can finally commit. Postgres support such [[two-phase commit|https://www.postgresql.org/docs/9.6/static/sql-prepare-transaction.html]] procedure. So multi-master captures each commit statement and implicitly transforms it to PREPARE, waits when cohort (all nodes except our) will get that transaction via replication protocol and only after successfull responses from cohort finally commit it.
11+
12+
Also to be able to resist node crashes and network failures ordinary two-phase commit (2PC) is insufficient. When failure happens between PREPARE and COMMIT survived nodes may not have enough information to decide what to do with prepared transaction -- crashed node can already commit or abort that transaction, but didn't notified other nodes about that and such transaction will block resouces (hold locks) until recovery of crashed node. Otherwise if we decide to commit/abort transaction without knowing faled node's decision then we can end up with data inconsistencies in database when failed node will be recovered (e.g. failed node committed transaction but survived node aborted it).
13+
14+
To be able to deal with crashes E3PC commit protocol was used [1][2]. Main idea of 3PC-like protocols is to write intention to commit transaction before actual commit, introducing new message (PRECOMMIT) in protocol between PREPARE and COMMIT messages. That message is not used during normal work, but in case of failure all nodes have enough information to decide what to do with transaction using quorum-based voting procedure. For voting to complete protocol requires majority of nodes to be presenet, hence the rule that cluster of 2N+1 can tolerate N simultaneous failures.
15+
16+
This process summarized on following diagram:
17+
18+
![](mmts_commit.svg)
19+
20+
Here user, connected to a backend (BE) decides to commit his transaction. Multi-master extension hooks that commit and changes it to a PREPARE statement. During transaction execution walsender process (WS) already started to decode transaction to "reorder buffer", and by the time when PREPARE statement happend WS starting sending our transaction to all neighbouring nodes (cohort). Then cohort nodes applies that transaction in walreceiver process (WR) and, after succes, signaling arbbiter process (Arb on diagram, custom background worker implemented in multimaster) to send vote for transaction (prepared) on initiating node.
21+
Arbiter process on initiating node wait until all nodes from cohort will send vote for transaction; after that he send "precommit" messages and waits till all nodes will respond to that with "precommited" message.
22+
When all participating sites answered with "precommited" message arbiter signalling backend to stop waiting and commit our prepared transaction.
23+
After that commit WAL record reaches cohort nodes via walsender/walreceiver connections.
24+
25+
[1] Idit Keidar, Danny Dolev. Increasing the Resilience of Distributed and Replicated Database Systems. http://dx.doi.org/10.1006/jcss.1998.1566
26+
27+
[2] Tim Kempster, Colin Stirling, Peter Thanisch. A more committed quorum-based three phase commit protocol. http://dx.doi.org/10.1007/BFb0056487
28+
29+
30+
## DDL replication
31+
32+
## Failure detection and recovery
33+
34+
35+

0 commit comments

Comments
 (0)