nilfs (a continuent snapshot file system) used with PostgreSQL

NILFS 是NTT开发的一个文件系统, 持续的提供快照, 为误操作提供回滚可能. 
相比lvm的快照, nilfs更有利于SSD环境. 因为在写频繁的环境中不需要大量的cow. 
简介 : 
http://nilfs.sourceforge.net/en/
NILFS is a log-structured file system supporting versioning of the entire file system and continuous snapshotting which allows users to even restore files mistakenly overwritten or destroyed just a few seconds ago.

NILFS was developed by NTT Laboratories and published as an open-source software under GPL license, and now available as a part of Linux kernel.

This site provides information and source code of programs related to the NILFS filesystem.
2.6.30以后的内核, 已经包含了nilfs, 用户只需要下载对应的管理包即可.

NILFS was merged into the Linux kernel 2.6.30. For the 2.6.30 kernel or later, you only need to download the utility package.

Userland utilities  nilfs-utils-2.2.0.tar.bz2  Apr 8, 2014 JST.

Include SET_SUINFO ioctl support which helps to reduce unfruitful segment cleaning, and lssu command is enhanced to help analysys of the ratio of in-used blocks for every segment.
For changes from past versions, see ChangeLog.

The latest version of nilfs-utils 2.0 series is as follows:


结合PostgreSQL使用的话, 可以实现异步流复制主备切换后, 老的主库因为XLOG相异导致无法直接切换为备库的场景.
老唐写了一篇文章, 详细的介绍这块功能, 请参考.
以下内容转载自老唐的blog.

引言:

我们知道在使用PostgreSQL的流复制做的高可用方案,即使使用同步的流复制,当主库由于操作系统或硬盘故障宕机时,当我们把备机提升为主库后,原主库通常无法转成备库。这是因为,在流复制的同步过程中,当有大量更新时,主库总是比备库超前一点,当切换后,备库提升为主库后,原主库就无法变成与新主库的Standby,如下图所示:

old_master_can_not_connect_promoted_slave.png

如果我们能把原主库回滚一段时间,让其与备库在同一个时间序列上,这时我们就可以把原主库变成新主库的备库了,如下图所示:

rollback_old_master_can_connect_promoted_slave.png

那么如何把原先的主库回滚到前一阶段呢?这就用到了本文讲的nilfs文件系统。有人说,不用nilfs文件系统,使用Linux下的LVM的快照功能也能实现这个回滚的功能,如每5分钟建一个快照,始终保持两个快照,这样我总是能把主库回滚到5分钟前的状态,这样也能实现这个回滚的功能。但LVM的快照功能会对性能有较大的影响。LVM的快照功能是通过COW(copy on write)来实现的,也就是当打开快照功能后,当写一个数据时,需要把旧数据拷贝到快照的空间中,这时相当于把写放大的一倍。于是有人就想如果每次写入新数据时,都不要覆盖旧数据,写到新的地方去,就象PostgreSQL表本身实现的多版本一样,这样就不能有这么大的性能损耗了。nilfs文件系统就是这样的一种文件系统。nilfs原本是为flash或SSD来设计的文件系统,对于SSD来说,重写代价比较大,所以每次写都写到新的地方,这样就能提高写的性能。这刚好能满足我们的这个需要。

本文后面就详细讲解如何使用nilfs实现如上的功能。

1. 本文所使用的测试环境

主库:192.168.56.11,db01
主库:192.168.56.12,db02

操作系统都是ubuntu12.04 server 数据库都安装在操作系统用户osdba下。

2. 初始化环境

在192.168.56.11和192.168.56.12上都做以下的操作。

为了使用nilfs,先安装nilfs的相关软件包:

sudo aptitude install nilfs-tools

我们的数据库数据目录在/home/osdba/pgdata下,我们格式化一个nilfs的文件系统,挂载到/home/osdba/pgdata下:

sudo mkfs -t nilfs2 -L pgdata  /dev/sdb1
sudo mount /dev/sdb1 /home/osdba/pgdata
sudo chown -R osdba:osdba pgdata
sudo chmod 700 pgdata
sudo rm /home/osdba/pgdata/.nilfs

编译安装PostgreSQL,具体可见:Linux下的PostgreSQL简单安装手册

安装完后,在.bashrc后面设置了:

export LD_LIBRARY_PATH=/home/osdba/pgsql/lib:$LD_LIBRARY_PATH
export PATH=/home/osdba/pgsql/bin:$PATH
export PGDATA=/home/osdba/pgdata
alias pgstart='pg_ctl -D $PGDATA start'
alias pgstop='pg_ctl -D $PGDATA stop -m fast'

3. 建主库

执行下面的命令,把数据库建起来:

initdb -k 

改动/home/osdba/pgdata/postgresql.conf的配置如下:

listen_addresses = '*'
wal_level = hot_standby
max_wal_senders = 5
hot_standby = on
logging_collector = on

改动/home/osdba/pgdata/pg_hba.conf的配置如下:

host    all             all          192.168.56.0/24         md5
host    replication     osdba        192.168.56.0/24         md5

启动数据库:

pgstart

在主库上把数据库超级用户osdba,设置一个密码,以便于后面建备库时使用密码连接主库:

osdba@db01:~$ psql postgres
psql (9.3.3)
Type "help" for help.

postgres=# alter user osdba password '123456';
ALTER ROLE
postgres=# 

4. 建备库

使用pg_basebackup建备库,执行如下命令:

pg_basebackup -h 192.168.56.11 -U osdba -F p -P -x -R -D /home/osdba/pgdata -l osdbabackup

实际执行过程如下:

osdba@db02:~$ pg_basebackup -h 192.168.56.11 -U osdba -F p -P -x -R -D /home/osdba/pgdata -l osdbabackup
Password: 
36002/36002 kB (100%), 1/1 tablespace

这样备库就建好了,后面我们配置备库,新建备库的/home/osdba/pgdata/recovery.conf文件,其内容如下:

recovery_target_timeline = 'latest'
standby_mode = 'on'
primary_conninfo = 'application_name=standby01 user=osdba password=123456 host=192.168.56.11 port=5432 sslmode=disable sslcompression=1'

启动备库:

osdba@db02:~$ pgstart
server starting
osdba@db02:~$ LOG:  redirecting log output to logging collector process
HINT:  Future log output will appear in directory "pg_log".
osdba@db02:~$ psql postgres
psql (9.3.3)
Type "help" for help.

postgres=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 t
(1 row)

这样环境就完全搭建好了。

5. 做测试

为了让测试更真实,我们运行pgbench不断的产生一些读写,然后做切换。 先初始化pgbench:

pgbench -i -h 192.168.56.11 postgres

启动pgbench的压力测试:

pgbench -h 192.168.56.11 -c 10 -T 1800 postgres

这时我们按192.168.56.11的电源,让其关机,模拟这台机器出故障的情况。同时记录时间。我们关机的时间为:

osdba@osdba-laptop:~$ date
2014年 03月 03日 星期一 23:28:46 CST

我们然后把备库192.168.56.12提升为主库:

osdba@db02:~$ pg_ctl promote
server promoting
osdba@db02:~$ psql postgres
psql (9.3.3)
Type "help" for help.

postgres=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 f
(1 row)

可以看到192.168.56.12已变成主库了。

这时我们需要把原先的主库192.168.56.11变成192.168.56.12的备库。把192.168.56.11重新开机,并把nilfs再mount上来:

sudo mount /dev/sdb1 /home/osdba/pgdata

这时我们只需要把192.168.56.11上的文件系统回滚到刚才关机前的一个时间,这个时间的WAL日志已同步到192.168.56.12上就可以了,我们先看nilfs的checkpoint点,nilfs会自动产生很多个checkpoint点,每个checkpoint点都可以转换成快照,然后就可以把快照mount上来。因为nilfs没有提供直接把文件系统回滚到一个快照点的功能,把nilfs回滚到快照点的方法是把快照点mount上来,然后使用rsync把快照的数据同步到当前的文件系统中。

下面的操作在192.168.56.11机器上: 我们先查看一下我们要回滚到文件系统的哪个checkpoint点,使用nilfs的lscp命令,如下所示:

osdba@db01:~$ lscp
                 CNO        DATE     TIME  MODE  FLG     NBLKINC       ICNT
                   1  2014-03-03 23:06:21   cp    -           11          2
                   2  2014-03-03 23:06:55   cp    -            8          2
......................
......................
                9935  2014-03-03 23:28:40   cp    -           19        806
                9936  2014-03-03 23:28:41   cp    -           19        806
                9937  2014-03-03 23:28:41   cp    -           19        806
.....................

估计回滚到9935这个checkpoint应该是可以的,执行下面命令把这个checkpoint转换到snapshot

sudo chcp ss /dev/sdb1 9935

然后挂载上来:

mkdir /home/osdba/snap
sudo mount -t nilfs2 -o ro,cp=9935 /dev/sdb1 /home/osdba/snap

注意挂载snapshot的方法是"-o ro,cp=9935",“ro”表示只读,“cp=9935”表示挂载哪个snapshot。

把快照的数据同步到当前的文件系统中:

rsync -axv --delete /home/osdba/snap/ /home/osdba/pgdata/ 

把192.168.56.11上的数据库转成备库,建/home/osdba/pgdata/recovery.conf,内容如下:

recovery_target_timeline = 'latest'
standby_mode = 'on'
primary_conninfo = 'application_name=standby01 user=osdba password=123456 host=192.168.56.12 port=5432 sslmode=disable sslcompression=1'

启动192.168.56.11上的数据库,这样就完成了切换。这时192.168.56.11转换成了192.168.56.12的备库了。我们可以到192.168.56.12上看同步的情况 :

postgres=# select * from pg_stat_replication;
 pid  | usesysid | usename | application_name |  client_addr  | client_hostname | client_port |         backend_start         |   state   | sent_
location | write_location | flush_location | replay_location | sync_priority | sync_state 
------+----------+---------+------------------+---------------+-----------------+-------------+-------------------------------+-----------+------
---------+----------------+----------------+-----------------+---------------+------------
 1267 |       10 | osdba   | standby01        | 192.168.56.11 |                 |       40594 | 2014-03-03 23:47:59.920158+08 | streaming | 0/51D
1E70     | 0/51D1E70      | 0/51D1E70      | 0/51D1E70       |             0 | async
(1 row)

上面的信息可以看出192.168.56.11上的备库已经连接到192.168.56.12上,同步也正常。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值