[笔记] postgresql 流复制(streaming replication)

基本环境说明:

os:FreeBSD 9.3
postgresql version:9.3.6
master:192.168.56.101
standby:192.168.56.102

安装过程略,基于pkg包

1.配置master端

# psql -U pgsql -d postgres -c "CREATE USER rep REPLICATION LOGIN ENCRYPTED PASSWORD 'password';"

# cd /usr/local/pgsql # vim data/postgresql.conf listen_addresses
= '*' wal_level = 'hot_standby' max_wal_senders = 1 # vim data/pg_hba.conf host replication rep 192.168.56.102/32 md5

修改完配置需要重启postgresql
# /usr/local/etc/rc.d/postgresql restart

2.复制数据至standby端

master端操作:
# psql -U pgsql -d postgres -c "select pg_start_backup('backup')"

# cd /usr/local/pgsql
# tar zcf data.tgz data
# scp data.tgz 192.168.56.102:/usr/local/pgsql

# psql -U pgsql postgres -c "select pg_stop_backup()"

3.配置standby端

# /usr/local/etc/rc.d/postgresql stop

# cd /usr/local/pgsql
# rm -r data
# tar zxf data.tgz
# rm -r data/postmaster.pid data/pg_xlog/* data/backup_label

# vim data/postgresql.conf
hot_standby = on
--------删除master端的三条配置语句------------
#listen_addresses = '*'
#wal_level = 'hot_standby'
#max_wal_senders = 1
-------------------------------------------

# vim data/recovery.conf
standby_mode = 'on'
primary_conninfo = 'host=192.168.56.101 port=5432 user=rep password=password'

# vim data/pg_hba.conf
---------删除master端的一条配置文句-----------
#host replication rep 192.168.56.102/32 md5
-------------------------------------------
# /usr/local/etc/rc.d/postgresql start

4.测试数据是否配置成功

master端
# createdb -U pgsql mydb
# psql -U pgsql mydb
mydb=# create table foo(id bigint);
mydb=# insert into foo select * from generate_series(1,100000);
mydb=# select * from pg_stat_replication; standby端 # psql
-U pgsql mydb mydb=# select count(*) from foo;

 

 

参考地址:

https://www.byvoid.com/zhs/blog/postgresql-wal-replication

http://blog.sciencenet.cn/home.php?mod=space&uid=419883&do=blog&id=537939

实现原理

主服务器在接受到每个事务请求时,将数据改动用预写日志(WAL)记录。具体而言,事务采用两段提交(Two Phase Commit),即先将改动写入预写日志,然后再实际改动数据库。这样可以保证预写日志的时间戳永远不落后于数据库,即便是正在写入时服务器突然崩溃,重启以后也可以依据预写日志将数据恢复,因为预写日志保留了比数据库记录中更新的版本。PostgreSQL的异步复制解决方案正是利用了预写日志,将预写日志从主服务器(Master Sever)传输到备用服务器(Standby Server),然后在备用服务器上回放(Replay)出预写日志中记录改动,从而实现主从复制。PostgreSQL使用了两种方式传输预写日志:存档式(archive)和流式(streaming)。

存档式复制的原理是主服务器将预写日志主动拷贝到一个安全的位置(可以直接到备用服务器,也可以是第三台服务器),同时备用服务器定期扫描这个位置,并将预写日志拷贝到备用服务器端然后再回放。这样即使主服务器崩溃了,备用服务器也可以从这个安全的位置获取到一份完整的记录,以确保任何数据不会丢失。而流式复制则简化了这一个步骤,由主服务器直接通过TCP协议向备用服务器传输日志,避免了两次复制的开销,有利于减小备用服务器和主服务器直接的数据延时。但当主服务器崩溃时,未被传输到备用服务器的日志则会丢失,造成数据损失。PostgreSQL支持存档式和流式两种模式的混合,当两种模式都开启时,备用服务器会定期检查是否有存档已经到达指定的位置,并回放日志。一旦检测到指定的位置没有新的日志,则会切换到流式模式试图直接从网络传输日志,接着再检查存档,不断重复这一循环。

 

standby端启动报错:

May 22 05:43:51 93b postgres[634]: [3-1] FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000000000000002 has already been removed

这是因为standby端启动时,会从上文data.tgz记录的wal位置到master端的data/pg_xlog目录下查找文件,而master端的data/pg_xlog日志文件,在standby端恢复数据的过程中已经被master端更新操作覆盖替换掉,已找不到000000010000000000000002该文件。

解决方法:重新去master端备份数据复制到standby重做,若测试环境下记得不要在完成配置standby端前,往master端更新数据。实际环境下未测试。

posted @ 2015-05-25 16:42  金枪语  阅读(1442)  评论(0编辑  收藏  举报