PostgreSQL Replication之第十五章 与Walbouncer 一起工作

与Walbouncer 一起工作

在本书的最后一章,将引导您通向2014年发布的一个工具,称为walbouncer。本书中的大多数技巧说明了如何复制整个数据库实例,如何分片,等等。在最后一章,是关于wabouncer的,它是所有关于过滤事务日志流来选择性地复制数据库对象从一台服务器到到一组(不一定是完全相同的)slave。

本章将涵盖以下主题:

• walbouncer的基本概念

•安装walbouncer

•选择性地复制数据库,表,和表空间

walbouncer 工具适用于 PostgreSQL 9.4 或者更高版本。

walbouncer 的概念

PostgreSQL事务日志的目的是帮助一个在崩溃事件中出现故障的数据库实例恢复自身。它也可以用来复制 整个数据库实例,正如我们在本书中关于同步复制与异步复制的章节所讨论的。

问题在于复制整个数据库实例是必须的。在许多现实世界的场景中,这是一个问题。让我们假设,有一个中心服务器,它包含许多大学的学生学习信息。每个大学都应该有一个数据的副本。作为PostgreSQL9.4,使用一个数据库实例这是不可能的,因为流复制只具有完全复制一个数据库的能力。运行许多实例显然是非常多的工作,也许不是所期望的一套方法。

walbouncer背后的思想是连接到PostgreSQL事务日志并过来它。在这个场景中,slave将只接收数据的一个子集,从而过滤掉可能是规则的关键或者一个安全点的视图的所有数据。在我们的大学的例子中,每个大学将只会有它自己的数据库的复制,因此,没有办法看到其它组织的数据。当涉及到安全系统时,隐藏数据是一个巨大的进步。对于出于分片的目的的walbouncer来说可能是一个使用场景。

下图显示了这是如何工作的:

walbouncer工具是一个位于master和slave之间的一个进程。它连接到master,获取事务日志,并在它被传输到slave之前过滤它。在这个例子中,有两个slave可以用来消耗事务日志,就像普通slave一样。

对地理上分布的数据库系统来说,walbouncer工具是理想的,因为它使我们能够很容易地决定那些数据要去哪里,哪个数据库需要在哪个位置。这里展示了一个基本的方框图:

过滤 XLOG

现在核心的问题是:walbouncer是如何过滤日志的?记住,事务日志的位置是非常关键的,在很多情况下,篡改这些事务日志的位置是很重要的,危险的,一点都不可行的。

解决这个问题的的关键在于PostgreSQL的核心深处。核心知道如何处理仿制的事务日志条目。剪下所有注定不能到达一个特定的服务器的所有数据,仿制的XLOG被注入,代替原来的一个。现在slave可以安全地消耗XLOG了并忽略那些仿制的记录。事实上,这种技术的妙处在于master和slave可以保持不变—不需要修补。所有的工作可以完全由walbouncer来做,它只是简单地作为某种XLOG的代理。

所使用的技术的因果关系如下:

•每个slave将获得相同数目的XLOG记录,不管目标系统中实际更改的数据量

•元数据(系统表)必须被完全地复制,千万不能被留下

•目标系统仍然会看到一个特定的数据库应该存在,但使用它 会失败。

最后一项特别值得注意。记住,系统无法分析特定XLOG记录的语义;它所做的所有 是检查它是否还需要。因此,元数据必须被复制。当一个slave系统尝试读取过滤的数据时,它将接收到一个令人讨厌的错误,该错误表明数据文件丢失。如果不能从磁盘读文件,则会显示错误并回滚。这种行为可能会使一些人跟到困惑,但这是唯一解决潜在技术问题的可能途径。

安装 walbouncer

walbouncer工具可以免费地从Cybertec网站下载(http://www.cybertec.at/postgresql_produkte/walbouncer/)并使用以下步骤安装:

1.为了本书的目的,使用了下面的文件:

wget http://cybertec.at/download/walbouncer-0.9.0.tar.bz2

2. 首先要做的事情是解压tar包,如下:

tar xvfj walbouncer-0.9.0.tar.bz2

3.一旦包已经被解压,您就可以进入该目录。在调用make之前,检查缺失的库是非常重要的。确保支持YAML 。在我的 CentOS测试系统中,下面的命令可以完成该工作:

[[email protected] ~]# yum install libyaml-devel

4.库将通过这些行来安装:

---> Package libyaml-devel.x86_64 0:0.1.4-11.el7_0 will be installed

--->Processing Dependency: libyaml = 0.1.4-11.el7_0 for package: libyaml-devel-0.1.4-11.el7_0.x86_64

5.下一步,只调用make。代码干净地编译。最后,只剩下make install:

[[email protected] walbouncer-0.9.0]# make install

cp walbouncer /usr/local/pgsql/bin/walbouncer

运行walbouncer所需要的二进制包将被复制到您的PostgreSQL二进制目录(在我的例子中, 是 /usr/local/pgsql/).

正如您可以看到的,部署walbouncer是很容易的,并且所有它需要的是几个命令。

配置 walbouncer

一旦代码被成功地部署了,就必须拿出一个简单的配置来告诉walbouncer做什么。为了演示walbouncer是如何工作的,这里已经创建了一个简单的安装程序。在这个例子中,两个数据库存在于master。它们中只有一个最终会在slave上:

$ createdb a

$ createdb b

目标是复制a到slave并跳过其它的。

在开始做基础备份之前,做一个walbouncer的config备份是有意义的。一个基本的配置是非常简单而且容易执行的:

listen_port: 5433

master:

host: localhost

port: 5432

configurations:

- slave1:

filter:

include_databases: [a]

配置有一下组件组成:

•listen_port:这是必要的。它定义了walbouncer使用哪个端口监听。slave可以连接到这个端口并且直接从bouncer流传输事务日志。

•master:下一节将告诉walbouncer去哪里找到它的master。在我们的例子中,master在同一台主机上并且监听5432端口。注意,没有数据库被列出。该系统连接到XLOG流,所以不需要数据库信息。

•configurations:这涵盖了slave配置。可以列出多个slave。对于每一个slave,可以使用几个过滤器。在这个例子中,只包含a数据库;其余的数据库被过滤掉。

创建基础备份

一旦写完了配置,是时候克隆一个初始的数据库实例了。棘手的事情是,没有pg_basebackup之类的工具,它为您做大多数的工作。原因是,pg_basebackup被设计用来复制整个数据库实例。在walbouncer的例子中,思想是在目标系统上只存在部分数据。因此,用户必须回到创建备份的基本方法。选择的方法是执行基础备份的传统方法。

然而,在开始之前,准备好标准流复制的master是很重要的。这包括:

•调整 postgresql.conf (wal_level, wal_keep_segments, max_wal_ senders, 等等)

•在master上调整pg_hba.conf

•在slave上设置数据目录为chmod 700

所有这些步骤都已经在第四章中描述过了,设置异步复制。正如已经提到的,棘手的部分是初始的基础备份。假设数据库必须被复制,就必须找到它的对象ID:

test=# SELECT oid, datname FROM pg_database WHERE datname = ‘a‘;

oid | datname

-------+---------

24576 | a

(1 row)

在这个例子中,对象ID是24576。一般的规则如下:所有OID大于16383的数据库有用户创建。这是唯一可以用来有用地过滤数据库的方法。

现在到maser的数据目录并复制除了基础目录的一切到slave所在的目录。在这个例子中,使用了这个小把戏:没有以a开始的文件名,所以安全地复制以c开始的一切并把备份标签添加到复制进程是可能的。现在,该系统将复制除了基础目录的一切:

cp -Rv [c-z]* backup_label ../slave/

一旦一切都被复制到了slave,在这个例子中这恰好发生在一台服务器上,缺少的基础目录可以在slave目录中创建:

$ mkdir ../slave/base

在下一步中,所有需要的数据库都可以被复制。目前,样本master上的情况如下:

[[email protected] base]$ ls -l

total 72

drwx------ 2 hs hs 8192 Feb 24 11:53 1

drwx------ 2 hs hs 8192 Feb 24 11:52 13051

drwx------ 2 hs hs 8192 Feb 25 11:49 13056

drwx------ 2 hs hs 8192 Feb 25 11:48 16384

drwx------ 2 hs hs 8192 Feb 25 10:32 24576

drwx------ 2 hs hs 8192 Feb 25 10:32 24577

所有大于16383的OID都是有终端用户创建的。在这种情况下,有三个这样的数据库。

因此,所有的系统数据库(template0,template1,和postgres)以及需要的在slave上的数据库可以被复制到基础目录:

cp -Rv 24576 1 13051 13056 ../../slave/base/

[注意,通常情况下,slave在一个远程系统上,所以应该使用rsync或者类似工具。在这个例子中,一起都是在同一个节点来使您的生活更容易。]

重要的事情是,在在大多设置中,基础目录是到目前为止最大的目录。一旦数据被获得,备份可以被停止,如下:

test=# SELECT pg_stop_backup();

NOTICE: WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup

pg_stop_backup

----------------

0/2000238

(1 row)

到目前为止,所有的一切都和 常规的流复制一样—唯一的区别是并不是基础目录的所有目录都实际地同步到slave。

在接下来的步骤中,创建一个简单地recovery.conf文件:

slave]$ cat recovery.conf

primary_conninfo = ‘host=localhost port=5433‘

standby_mode = on

这里最重要的是slave的端口必须写到配置文件中去。slave将再也不会不会直接看到master了,但是会通过walbouncer消耗它所有的XLOG。

启动walbouncer

一旦完成了配置,就可以启动walbouncer了。walbouncer的语法很简单:

$ walbouncer –help

walbouncer工具代理PostgreSQL的流复制连接并有选择性地过滤

Options:

-?, --help Print this message

-c, --config=FILE Read configuration from this file.

-h, --host=HOST Connect to master on this host.

Default localhost

-P, --masterport=PORT Connect to master on this port.

Default 5432

-p, --port=PORT Run proxy on this port. Default 5433

-v, --verbose Output additional debugging information

所有相关的信息都在config文件中,所以可以确保启动:

$ walbouncer -v -c config.ini

[2015-02-25 11:56:57] wbsocket.c INFO: Starting socket on port 5433

选项-v不是强制的。它所做的一切都是给我们多提供一点正在发生的信息。一旦starting socket信息显示出来,就意味着所有的事情都在完美地进行。

最后,可以启动slave了。切换到slave的数据目录并启动它,如下:

slave]$ pg_ctl -D . -o "--port=5444" start

server starting

LOG: database system was shut down in recovery at 2015-02-25 11:59:12 CET

LOG: entering standby mode

LOG: redo starts at 0/2000060

LOG: record with zero length at 0/2000138

INFO: WAL stream is being filtered

DETAIL: Databases included: a

LOG: started streaming WAL from primary at 0/2000000 on timeline 1

LOG: consistent recovery state reached at 0/2000238

LOG: database system is ready to accept read only connections

这里的点表示本地目录(当然,把完整的路径放到这里也是一个很好的想法—绝对地)。接下来是 另外一个技巧:当为了测试的目的在同一台服务器上一次又 一次地同步slave,一遍又一遍地更改端口是很烦人的。选项-O有助于在postgresql.conf中重写配置文件,以便系统可以直接使用其它的端口启动。

[如果PostgreSQL在独立的服务器上启动,这对通过正常的初始化程序来启动服务器当然很有用。]

只要slave开始工作,walbouncer将开始发布更多的日志信息,告诉我们更多关于流的状态:

[2015-02-25 11:58:37] wbclientconn.c INFO: Received conn from 0100007F:54729

[2015-02-25 11:58:37] wbclientconn.c DEBUG1: Sending authentication packet

[2015-02-25 11:58:37] wbsocket.c DEBUG1: Conn: Sending to client 9 bytes of data

[2015-02-25 11:58:37] wbclientconn.c INFO: Start connecting to host=localhost port=5432 user=hs dbname=replication replication=true application_name=walbouncer

FATAL: no pg_hba.conf entry for replication connection from host "::1", user "hs"

一旦这些消息被显示出来,系统就处于运行状态了并且事务日志在从master流向slave。

现在是测试的时候了:

$ psql -h localhost -p 5444 b

FATAL: database "b" does not exist

DETAIL: The database subdirectory "base/24577" is missing.

当一个到过滤的数据库的连接被确立,PostgreSQL将会出错并告诉用户服务请求所需的文件不存在。这正是预期的行为种类—由于缺乏数据请求应该被拒绝。

当连接到是数据库包含一个数据库实例的时候,所有的事情工作起来像一个魔力:

$ psql -h localhost -p 5444 a

psql (9.4.1)

Type "help" for help.

a=#

下一个测试检查数据是否很好地从master复制到了slave。要执行该检查,可以在master上场景一个表:

a=# CREATE TABLE a (aid int);

CREATE TABLE

正如预期的那样,该表将很好地在slave上终止。

a=# \d

List of relations

Schema | Name | Type | Owner

--------+------+-------+-------

public | a | table | hs

(1 row)

该系统现在已经准备就绪并且可以安全的使用。

使用附加配置选项

walbouncer工具可以为用户做的事情远远超出了目前所列出来的。一些额外的配置参数也是可以用的。

第一个例子显示了如果有一个以上的slave可以做什么:

listen_port: 5433

master:

host: localhost

port: 5432

configurations:

- slave1:

match:

application_name: slave1

filter:

include_tablespaces: [spc_slave1]

exclude_databases: [test]

在配置块中,有一个slave1的部分。如果一个slave使用slave1作为application_name(按照application_name列出的条款)连接自身,slave1的配置将被选中。如果这个配置被服务器(可以有很多这样的slave部分)选中,在下一个块中列出的过滤器将被应用。

基本上,每种类型的过滤器有两种体现:include_ 和exclude_。在这个例子中,只包含spc_slave1表空间。最后的设置说,只有test被排除(如果表空间过滤器匹配它们,所有其它数据库被包括)。

当然,这样看描述也是有可能的:

exclude_tablespaces: [spc_slave1]

include_databases: [test]

在种情况下,所有表空间只有spc_slave1被包括。只有系统数据库和数据库test被复制。鉴于这些include_ 和 exclude_ 设置,可以灵活地配置复制什么到那个slave。

请记住,同步复制也需要application_name。如果通过walbouncer传递的application_name参数与在synchronous_standby_names里面列出来的application_name一样,就可以进行同步复制。

正如您可以看到的,application_name这里用于两个目的:它决定使用哪些config块,并告诉master需要哪个级别的复制。

调整过滤规则

经常被问的一个问题是看,是否可以调整过滤规则。对象随后可能被添加,或者对象可能被删除。在许多情况下,这是人们经常问的一个很常见的场景。

改变一个walbouncer设置的配置看起来并不简单。核心问题是同步XLOG并确保所有相关对象准备就绪。让我们一个一个地通过核心挑战。

删除与过滤对象

基本上,删除对象是相当简单。第一件事就是关掉slave以及walbouncer。一旦这样做了,那些不再需要的对象可以从slave的文件系统物理地删掉。这里重要的部分是找到那些对象。再次,这里选择的方法是挖掘系统表。所涉及的核心系统表或者视图如下:

•pg_class: 该表包含一系列对象 (表, 索引, 等等).从该表中取出对象的表示是很重要的。

•pg_namespace:这是用于获取模式的信息的。

•pg_inherit: 继承使用的信息在这表中。

没有一个关于如何找到所有这些对象的总指南,因为事情高度取决于应用的过滤类型。

准备好适当的SQL查询来找到这些必须要被删除的对象(文件)的最简单的方式是和psql一起使用选项-E,它显示在反斜杠命令后面所有的SQL代码。前端的SQL代码可以派上用场。下面是一些示例输出:

test=# \q

[email protected]:~$ psql test -E

psql (9.4.1)

Type "help" for help.

test=# \d

********* QUERY **********

SELECT n.nspname as "Schema",

c.relname as "Name",

CASE c.relkind WHEN ‘r‘ THEN ‘table‘ WHEN ‘v‘ THEN ‘view‘ WHEN ‘m‘ THEN ‘materialized view‘ WHEN ‘i‘ THEN ‘index‘ WHEN ‘S‘ THEN ‘sequence‘ WHEN ‘s‘ THEN ‘special‘ WHEN ‘f‘ THEN ‘foreign table‘ END as "Type",

pg_catalog.pg_get_userbyid(c.relowner) as "Owner"

FROM pg_catalog.pg_class c

LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace

WHERE c.relkind IN (‘r‘,‘v‘,‘m‘,‘S‘,‘f‘,‘‘)

AND n.nspname <> ‘pg_catalog‘

AND n.nspname <> ‘information_schema‘

AND n.nspname !~ ‘^pg_toast‘

AND pg_catalog.pg_table_is_visible(c.oid)

ORDER BY 1,2;

**************************

List of relations

Schema | Name | Type | Owner

--------+--------------------+-------+-------

...

一旦文件从基础目录被删除,walbouncer和slave实例可以可以被重新启动。请记住,walbouncer是一个用来使常规流更强大的工具。因此,slave仍然是只读的,并且是不可能使用DELET和DROP之类的命令的。您真的必须从磁盘删除文件。

添加对象到slaves

添加对象是目前最复杂的任务。因此,强烈推荐使用更安全,更简单的方法来 解决这个问题。最安全和最可靠的方法是完全同步一个实例,这需要新的对象。

简单地使用本章前面所描述的机制,以避免所有的陷阱。

总结

在本章中,讨论了walbouncer的工作,一个用于过滤事务日志的工具。除了安装过程,对所有的配置选项和一个基本设置进行的概述。

您学会了如何建立地理分布的设置。

时间: 2024-11-05 12:21:17

PostgreSQL Replication之第十五章 与Walbouncer 一起工作的相关文章

PostgreSQL Replication之第十四章 扩展与BDR

在这一章中,将向您介绍一个全新的技术,成为BDR.双向复制(BDR),在PostgreSQL的世界里,它绝对是一颗冉冉升起的新星.在不久的将来,许多新的东西将会被看到,并且人们可以期待一个蓬勃发展的项目. 本章将是关于如下这些主题: •理解 BDR 复制概念 •安装 BDR •设置一个简单的集群 •修改集群和故障转移 •了解 BDR 的性能 在挖掘所有的技术细节之前,理解 BDR 方面的基本技术是非常重要的.           理解 BDR 复制概念 过去,在9.0被引进之前,人们不得不使用S

深入浅出Zabbix 3.0 -- 第十五章 Zabbix 协议与API

今天是六.一儿童节,祝小朋友们节日快乐!发完此文就带我家小朋友出去玩耍了. 第十五章 Zabbix 协议与API 本章将介绍和开发相关的Zabbix协议和API的内容,通过对Zabbix协议和API的深入了解,你可以利用Zabbix协议编写客户端程序并将其嵌入的产品或系统中,并将数据发送到Zabbix server,这在无法安装Zabbixagent等程序的场景(例如专用的嵌入式系统)中非常有用.你也可以利用Zabbix API开发自己的业务系统,或灵活的与现有系统整合集成. 15.1 Zabb

第十五章 文件属性类的实现

                  第十五章    文件属性类的实现        根用户的权限也不能是无限大.必须考虑到保护用户的隐私!用户的文件内容.程序代码可设置为根用户也不能观看,只能是文件拥有者可以查看.修改.但根用户可以删除一切非根用户的文件.也可以查看用户的目录.所以,i_mode字符更改如下:      BU16 i_mode; // 描述文件的访问权限:文件的读.写.执行权限  // i_mode.15-13  ftype; 文件类型: 0-符号软连接文件, // 1-硬连接文

C和指针 (pointers on C)——第十五章:输入输出函数

第十五章 输入输出函数 这一章读完的第一感觉就是"呵呵". 如果说上过C语言课,基本上scanf()/printf()算是用的比较熟练了.尤其是那些抽象的格式说明.还有scanf()为什么要加括号. 读过本书前面的内容的话,getchar(),putchar(),gets(),puts()这些应该也问题不大. 再如果的话,你学过计算机图形学,你玩过OpenGL,听说过双缓存机制,那么fflush()也肯定弄明白了. 再加上FILE的操作,输入输出定位刷新删除改名,流的概念. 这一章就会

第十五章 链表

/** 数组与链表的区别:数组易随机访问,链表易插入和删除 链表组成:储存数据元素的数据域,储存下一结点地址的指针域 链表易于插入与删除 lists 的用法????????????????????? *///建立一个图书链表 #include<iostream> #include <string> using namespace std; struct book //第一步: 用于建立节点. class 默认为私有 struct 默认为公有 //节点组成:①数据域 ②指针域(*ne

java(第十五章)

第十五章 一.字符串类String 1.String是一个类,位于java.lang包中 2.创建一个字符串对象的2种方式: String 变量名="值"; String 对象名=new String("值"); 3.字符串的常用方法 3.1 字符串长度--length() 3.2 判断值是否相等 equals() 3.3 判断字符串对象地址是否相同 == 3.4 忽略 大小写 判断 equalsIgnoreCase() 3.5 大小写转换 toLowerCase(

CSS3秘笈复习:十三章&amp;十四章&amp;十五章&amp;十六章&amp;十七章

第十三章 1.在使用浮动时,源代码的顺序非常重要.浮动元素的HTML必须处在要包围它的元素的HTML之前. 2.清楚浮动: (1).在外围div的底部添加一个清除元素:clear属性可以防止元素包围浮动元素.关键字:left.right或both. (2).浮动外围元素:让包含浮动元素的<div>也浮动.选择这种方法一定要在浮动容器后面的任何元素中添加一个clear属性,确保浮动元素落到容器的下方. (3).利用overflow : hidden.另一种常见的方法是在外围的样式中添加以下属性:

第十五章 文正学院成绩录入系统

这是13年上半年给文正学院做的一个成绩录入系统,只需要实现成绩录入的功能,嫁接到文正教务系统中.实现的功能如图所示. 王川 2014/5/30 第十五章 文正学院成绩录入系统,布布扣,bubuko.com

C++ Primer Plus学习:第十五章

第十五章 友元.异常和其他 友元 友元类 表 0-1 class Tv { public: friend class Remote; } Remote类可以使用Tv的数据成员,Remote类在Tv类后定义 . 友元成员函数 表 0-2 class Tv; //前向声明 class Remote { public: void chanup(Tv &t); } class Tv { public: friend void Remote::set_chan(Tv& t, int c); } 异常