毛子说,我们需要支持PG的多主,于是毛子开始了写代码!
PostgreSQL的多主
多主机是一个扩展,并设置补丁为Postegres数据库,轮流到Postgres的同步无共享集群来提供OLTP可扩展性和高可用性,自动灾难恢复。
特点
- 集群范围内的事务隔离
- 同步逻辑复制
- DDL复制
- 分布式序列
- 容错
- 自动节点恢复
限制
- 提交延迟。逻辑复制当前执行仅仅在本地提交发送数据到用户节点,所以在重写处理用户的情况下,将等待事务处理两次:本地节点与人其他节点(simultaneosly)上。我们计划在将来解决这个问题。
- DDL复制。虽然数据在逻辑层面复制,DDL语句被复制执行分布式使用相同的语句提交。一些复杂的DDL scenarious 包括存储过程和临时临时表都不能正常工作。我们正在证明,与普通的Postgres完全兼容现在的工作。目前,我们正在通过164141 Postgres的回归测试。
- 隔离级别。目前,多主机只支持重复读隔离级别。这是严格比默认读COMMITED,但在提交也增加了序列化失败的概率。序列化水平目前还不支持。
- 每个群集一个数据库。
在PostgreSQL 中毛子提供了两个模块,一个是分布式系统中鼎鼎大名的raft, 另外一个就是数据库领域非同凡响的多主(multimaster)
另外毛子还说了9.7 中要支持多主,于是毛子开始给9.6的Beta 添加代码; 于是乎这神奇的一切都是在9.6 Beta 上发生的
“ 多主PostgreSQL 在集群中所有的节点上拥有相同的副本,并且允许在集群中任意一个节点的写入。的副本相同的数据库复制到群集中的所有节点,并允许写入的每个节点。事务隔离强制执行群集范围内,所以在不同节点上的并发更新的情况下数据库将使用相同的冲突解决规则 (可重复读的隔离级别 mvcc) 作为单个节点使用并发的后端,而且总是处于一致的状态。任何写事务会写给所有的节点,从而导致增加提交延迟的时间同步节点 nedded 之间往返成正比。阅读只交易和没有可衡量的开销在本地执行的查询。复制机制本身基于逻辑解码和早期版本的 pglogical 扩展为社区提供的 2ndQuadrant 团队。
N 个节点的集群可以继续工作时的初始节点大多还活着,可由其他节点访问。这是通过使用 3 阶段提交协议和心跳故障发现机制实现的。重新加入集群的节点,被带回到群集的节点可以快速创汇到实际状态自动自当节点被排除在外的时间当交易日志仍然存在的情况下从群集 (这取决于在 postgres 的checkpoint配置)。
想了解更多关于内部实现的内容,可以阅读内部体系结构(官网也是空的)。 ”
安装指南:
数据库安装,及相关模块安装
git clone https://github.com/postgrespro/postgres_cluster.git
cd postgres_cluster
./configure && make world && make -j 4 install
cd ./contrib/raftable && make install
cd ../../contrib/mmts && make install
配置PostgreSQL 的配置文件
listen_addresses = '*' # what IP address(es) to listen on;
port = 5432 # (change requires restart)
max_connections = 100 # (change requires restart)
shared_buffers = 128MB # min 128kB
dynamic_shared_memory_type = posix
max_prepared_transactions = 200 # should be > 0, because all
# transactions are implicitly two-phase
max_connections = 200
max_worker_processes = 100 # at least (2 * n + p + 1)
# this figure is calculated as:
# 1 raftable worker
# n-1 receiver
# n-1 sender
# 1 mtm-sender
# 1 mtm-receiver
# p workers in the pool
max_parallel_degree = 0
wal_level = logical # multimaster is build on top of
# logical replication and will not work otherwise
max_wal_senders = 10 # at least the number of nodes
wal_sender_timeout = 0
default_transaction_isolation = 'repeatable read'
max_replication_slots = 10 # at least the number of nodes
shared_preload_libraries = '/opt/pgsql/mmts/lib/raftable.so,/opt/pgsql/mmts/lib/multimaster.so'
multimaster.workers = 3
multimaster.max_nodes = 3
multimaster.use_raftable = true
multimaster.ignore_tables_without_pk = 1
multimaster.heartbeat_recv_timeout = 1000
multimaster.heartbeat_send_timeout = 250
multimaster.twopc_min_timeout = 2000
multimaster.queue_size = 10485760 # 10mb
#在另外一台主机上node_id 配置为2
multimaster.node_id = 1 # the 1-based index of the node in the cluster
multimaster.conn_strings = 'dbname=postgres host=192.168.56.103 port=5432 raftport=6666,dbname=postgres user=postgres host=192.168.56.102 raftport=6666'
# comma-separated list of connection strings
multimaster.heartbeat_recv_timeout = 1000
multimaster.heartbeat_send_timeout = 250
multimaster.ignore_tables_without_pk = true
multimaster.twopc_min_timeout = 2000
配置HBA 认证文件
配置流复制trust, 注意生产环境切莫不要这样使用,0.0.0.0/0是全部主机都可以取到流复制 pg_ha.conf
# replication privilege.
#local replication postgres trust
#host replication postgres 127.0.0.1/32 trust
#host replication postgres ::1/128 trust
host replication postgres 0.0.0.0/0 trust
启动数据库
[postgres[@192]() ~]$ /opt/pgsql/mmts/bin/pg_ctl -D /data_mmts -l logfile restart
此时已经支持多主了,多主模块还提供了一些函数;
CREATE EXTENSION multimaster; ----使用该语句导入相关函数
102 上的相关查询
postgres=# SELECt pg_is_in_recovery();
pg_is_in_recovery
-------------------
f
(1 row)
postgres=# \x
Expanded display is on.
postgres=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+-----------------------------
pid | 4446
usesysid | 10
usename | postgres
application_name |
client_addr | 192.168.56.103
client_hostname |
client_port | 37494
backend_start | 2016-09-15 10:10:29.14246-04
backend_xmin |
state | streaming
sent_location | 0/1593640
write_location | 0/1593640
flush_location | 0/1593640
replay_location | 0/1593640
sync_priority | 0
sync_state | async
postgres=#
103 节点的相关查询
postgres=# SELECt pg_is_in_recovery();
-[ RECORD 1 ]-----+--
pg_is_in_recovery | f
postgres=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 2472
usesysid | 10
usename | postgres
application_name |
client_addr | 192.168.56.102
client_hostname |
client_port | 35146
backend_start | 2016-09-15 10:10:29.688946-04
backend_xmin |
state | streaming
sent_location | 0/15938F8
write_location | 0/15938F8
flush_location | 0/15938F8
replay_location | 0/15938F8
sync_priority | 0
sync_state | async