Postgres的的-XL是一个基于PostgreSQL的数据库的横向扩展开源SQL数据库集群。
1、Global Transaction Monitor (GTM)
全局事务管理器,确保群集范围内的事务一致性。 GTM负责发放事务ID和快照作为其多版本并发控制的一部分。集群可选地配置一个备用GTM,以改进可用性。此外,可以在协调器间配置代理GTM, 可用于改善可扩展性,减少GTM的通信量。
2、GTM Standby
GTM的备节点,在pgxc,pgxl中,GTM控制所有的全局事务分配,如果出现问题,就会导致整个集群不可用,为了增加可用性,增加该备用节点。当GTM出现问题时,GTM Standby可以升级为GTM,保证集群正常工作。
3、GTM-Proxy
GTM需要与所有的Coordinators通信,为了降低压力,可以在每个Coordinator机器上部署一个GTM-Proxy。
4、Coordinator
协调员管理用户会话,并与GTM和数据节点进行交互。协调员解析,并计划查询,并给语句中的每一个组件发送下一个序列化的全局性计划。 为节省机器,通常此服务和数据节点部署在一起。
5、Data Node
数据节点是数据实际存储的地方。数据的分布可以由DBA来配置。为了提高可用性,可以配置数据节点的热备以便进行故障转移准备。
GTM是全局性的事物管理器,那么整个分布式数据库集群工作时只有一个而且缺一不可,考虑到服务器其他不必要因素导致GTM挂掉,所以应该将GTM单独部署一台,即便如此,一旦GTM挂掉整个集群依旧不可用。为了实现高可用,所以我们需要最好至少集群中存在一个GTM的备份节点也就是GTM Standby。GTM需要通过Coordinator和集群所有数据节点进行交互从而实现分布式数据库事物的可靠性,因此为了减轻GTM压力,我们最好能够增加GTM的代理节点,也就是GTM-Proxy, 当然也可以不存在它,为了提高性能,一般推荐有多少个协调器节点就部署多少个GTM代理。而协调器作为GTM和数据节点的交互桥梁,为了减少不必要的网络消耗并提高数据库性能,有多少个数据节点就有多少个协调器,因为每个协调器都可以和整个集群的GTM和数据节点交互,所以每个协调器都可以作为集群的入口而且集群只要有一个运行的协调器就可以支撑。数据节点作为真实存储数据的各个数据库,以水平分库的方式分散存储着整个集群的完整数据。经测试postgresxl默认以数据库节点数量取模均衡的存储数据,因为每个数据节点的数据都是独一无二的,一旦其中一个数据节点出问题,就会影响整个集群的数据的真实性和完整性,因此最好能够每个数据节点增加其备份节点。此外,我们在处理mysql数据库压力时,经常会使用采用读写分离,并定期进行数据库的数据同步。因此,如果能够将主备和读写分离同步实现或许会更好。此外如果需要对集群实现负载均衡和管理,可以采用Haproxy。
综上所述,我们可以大致了解到实际上Postgres-XL的组件实际上就三件东西,GTM,Coordinator ,Data Node 等其他一些都是助攻。
本次集群的实现目标,本次主要做测试,因此,我会使用三台服务器,其中一台运行GTM、另外两台作为集群节点各自部署Coordinator、Datanode、GTM Standby。
主机名 | 地址 | 角色 | 端口号 | 节点名称 | 数据目录 |
Pg1 |
192.168.0.197 | GTM | 6666 | gtm | /home/postgres/DATA/gtm |
pg2 |
192.168.0.133 | Coordinator | 5432 | coord1 | /home/postgres/DATA/coord1 |
Datanode | 5433 | Datanode1 | /home/postgres/DATA/dn1 |
||
GTM-Proxy | 6666 |
|
|||
pg3 |
192.168.0.132 | Coordinator | 5432 | coord2 | /home/postgres/DATA/coord2 |
Datanode | 5433 | Datanode2 | /home/postgres/DATA/dn2 |
||
GTM-Proxy | 6666 |
|
0)sudo apt-get install make
1)sudo apt-get install flex
2)sudo apt-get install bison
3)sudo apt-get install libreadline6-dev
4)sudo apt-get install openjade
5)sudo apt-get install docbook-dsssl
0) 添加用户:sudo adduser postgres
注意:如此此前没有这个用户,按步骤设置密码,既可以不进行1) 。
1) 修改用户密码,我这里都设置成123456:sudo passwd postgres
2) su postgres
3) mkdir ~/.ssh
4) 只赋予拥有者有读、写、执行权限 : chmod 700 ~/.ssh
说明:此步骤是让GTM可以免密码登陆所有集群节点。
0). su postgres
1). ssh-keygen -t rsa
注意:弹出框,一顿enter健下去。但是如果你修改了ip,操作时,要将整个 ~/.ssh 删除,然后重新操作。
2). cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
3). 拥有者读写权限:chmod 600 ~/.ssh/authorized_keys
说明:后面4、5就是给集群所有节点传输密钥
4). scp ~/.ssh/authorized_keys postgres@pg2:~/.ssh/
5). scp ~/.ssh/authorized_keys postgres@pg3:~/.ssh/
6). 分别测试是否可以免密码登录,有反馈时间信息就ok。:ssh postgres@pg3 date、ssh postgres@pg2 date
0). 切换至普通用户或者root用户执行:su
说明:https://www.postgres-xl.org/,去此官网下载postgres-xl,目前最新发行版9.5
1). 解压:tar -zxvf postgres-xl-9.5r1.4.tar.gz
2). ./configure --prefix=/home/postgres/pgxl9.5/
3). make
注意:部分ubuntu会在2)后出现“configure: error: zlib library not found” ,缺少zlib库,并导致无法make
请执行:sudo apt-get install zlib1g;sudo apt-get install zlib1g.dev
4). sudo make install
5). cd contrib/
注意:这里是一些类似扩展的东西,也可以不安装。
6). make
7). sudo make install
8). su postgres
9). 进入postgres家目录:cd
10). vi .bashrc
文件末尾添加如下配置:
export PGHOME=/home/postgres/pgxl9.5
export LD_LIBRARY_PATH=$PGHOME/lib:$LD_LIBRARY_PATH
export PATH=$PGHOME/bin:$PATH
11).使生效:source .bashrc
12).测试:echo $PGHOME
0). 切回普通用户下:cd /home/postgres
1). 创建我们规划的数据目录:mkdir DATA
2). 赋予权限:sudo chown -R postgres.postgres /home/postgres
在pg1机器上,切换到postgres用户下执行初始化:
0). su postgres
1).初始化全局事物管理器: initgtm -Z gtm -D /home/postgres/DATA/gtm
2). 修改GTM配置文件:vi /home/postgres/DATA/gtm/gtm.conf
修改如下地方:
nodename = 'gtm' #节点名称,任意指定,不能与其他节点重复
listen_addresses = '*' #GTM监听的ip地址,*代表监听所有的集群ip
port =6666 #gtm监控的端口号
startup = ACT #act代表gtm是主库,如果是standy,设置为'STANDBY'
说明:按照规划,我在每个节点上都安装了GTM Proxy,先于pg2上执行
0). su - postgres
1). 初始化gtm_proxy:initgtm -Z gtm_proxy -D /home/postgres/DATA/gtm_proxy --nodename gtm_proxy1
注意:如果 --nodename gtm_proxy1 这部分执行失败,去掉即可 ,我是在配置文件中直接配置的。
2). vim /home/postgres/DATA/gtm_proxy/gtm_proxy.conf
3). vi /home/postgres/DATA/gtm/gtm_proxy.conf
nodename='gtm_proxy1'
port=6666
gtm_host='pg1'
gtm_port=6666
说明:正如步骤7开始的说明,我们每个节点都安装了GTM代理,所以我们还需要在pg3上进行同样的步骤,切记在pg3上请将所有gtm_proxy1改为gtm_proxy2
说明:按照规划,我在每个节点上都安装了Coordinator,先于pg2上执行
0)在家目录执行如下代码切换之postgres用户: su - postgres
1). 初始化Coordinator:initdb -D /home/postgres/DATA/coord --nodename coord1 -E UTF8 --locale=C -U postgres -W
注意执行这句时会弹出:”Enter new superuser password: “,请输入密码,我这里使用的是123456
2).vi /home/postgres/DATA/coord/postgresql.conf
找到如下内容进行修改:
# - Connection Settings -
listen_addresses = '*'
port = 5432
max_connections = 100
# DATA NODES AND CONNECTION POOLING
#----------------------------------
pooler_port = 6667
max_pool_size = 100
# GTM CONNECTION
#--------------------------
gtm_host = 'pg1' #gtm所在的主机地址
gtm_port = 6666 #gtm配置中,gtm端口号配置为6666
pgxc_node_name = 'coord1'
3).设置pg_hba.conf文件: vi /home/postgres/DATA/coord/pg_hba.conf
找到如下内容进行修改:
# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all 0.0.0.0/0 trust
# IPv6 local connections:
host all all ::1/128 trust
说明:正如步骤8开始的说明,我们每个节点都安装了Coordinator,所以我们还需要在pg3上进行同样的步骤,于pg3上执行上述步骤,将所有coord1的地方修改未coord2。
说明:按照规划,我在每个节点上都安装了datanode,先于pg2上执行。
1). pg2中初始化dn1,要在postgres用户下执行,并切换至家目录:su - postgres
2). 初始化datanode:initdb -D /home/postgres/DATA/dn --nodename dn1 -E UTF8 --locale=C -U postgres -W
注意执行这句时会弹出:”Enter new superuser password: “,请输入自己想要的的密码,我这里统一使用123456
3). vi /home/postgres/DATA/dn/postgresql.conf
找到如下内容进行修改:
CONNECTIONS AND AUTHENTICATION
#------------------------------------
listen_addresses = '*'
port =5433
max_connections = 100
# DATA NODES AND CONNECTION POOLING
#----------------------------------------------
pooler_port = 6668 # 同一台机器要使用不同的连接池端口,如coord1与dn1部署同一个机器,coord1是6667,dn1是6668
max_pool_size = 100
# GTM CONNECTION
#-----------------------------
gtm_host = 'pg1'
gtm_port = 6666 #gtm端口号
pgxc_node_name = 'dn1'
4).配置pg_hba.conf:vi /home/postgres/DATA/dn/pg_hba.conf
找到如下内容进行修改:
# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all 0.0.0.0/0 trust
# IPv6 local connections:
host all all ::1/128 trust
说明:再次在pg3上执行以上所有步骤,请将所有的dn1修改未dn2
说明:postgresxl是有提供一个pgxc_ctl脚本读取配置自动化启动服务,本次测试我们采用自己启动的方式,后期会补充。
集群启动顺序是GTM-GTM Standby-GTM-Proxy-Datanodes-Coordinators
1).在pg1上,在postgres用户下,家目录里面启动gtm: gtm_ctl start -Z gtm -D /home/postgres/DATA/gtm
注意如果出现:server starting,则表示成功!!!!
2).在pg2机器上,在postgres用户下,家目录里面启动gtm-proxy:gtm_ctl start -Z gtm_proxy -D /home/postgres/DATA/gtm_proxy
注意如果出现:server starting,则表示成功!!!!
3).在pg3机器上,执行2).中的操作。
4).在pg2机器上,在postgres用户下,家目录里面启动datanode:pg_ctl start -Z datanode -D /home/postgres/DATA/dn
注意:会输出如下信息,则表示成功
LOG: MultiXact member wraparound protections are now enabled
LOG: database system is ready to accept connections
LOG: autovacuum launcher started
LOG: cluster monitor started
5).在pg3机器上,执行4).中的操作。
6).在pg2机器上,在postgres用户下,家目录里面启动coordinator:pg_ctl start -Z coordinator -D /home/postgres/DATA/coord
注意:会输出如下信息,则表示成功
LOG: MultiXact member wraparound protections are now enabled
LOG: database system is ready to accept connections
LOG: autovacuum launcher started
LOG: cluster monitor started
7).在pg3机器上,执行6).中的操作。
说明:在上面安装步骤顺利进行完之后,接下来我们开始使用和测试整个数据库集群。当然请记得协调器是整个集群的入口。
1) 以postgres用户下进入pg2,并进入数据库。规划中coord1配置端口号是5432
psql -p 5432
2)进入数据库后,我们先查询集群节点,并写入我们规划的集群,并使它重新加载生效。
psql (PGXL 9.5r1.3, based on PG 9.5.4 (Postgres-XL 9.5r1.3))
Type "help" for help.
postgres=# select * from pgxc_node;
postgres=# alter node coord1 with (type=coordinator,host='pg2', port=5432);
postgres=# create node coord2 with (type=coordinator,host='pg3', port=5432);
postgres=# create node dn1 with (type=datanode, host='pg2',port=5433,primary,preferred);
postgres=# create node dn2 with (type=datanode, host='pg3',port=5433);
postgres=#select pgxc_pool_reload();
postgres=# select * from pgxc_node;
3) 再以postgres用户下进入pg3,并进入数据库,并执行类似的操作。规划中coord2配置端口号是5432
psql -p 5432
4) 操作数据库
psql (PGXL 9.5r1.3, based on PG 9.5.4 (Postgres-XL 9.5r1.3))
Type "help" for help.
postgres=# select * from pgxc_node;
postgres=# create node coord1 with (type=coordinator,host='pg2', port=5432);
postgres=# alter node coord2 with (type=coordinator,host='pg3', port=5432);
postgres=# create node dn1 with (type=datanode, host='pg2',port=5433,primary,preferred);
postgres=# create node dn2 with (type=datanode, host='pg3',port=5433);
postgres=#select pgxc_pool_reload();
postgres=# select * from pgxc_node;
5) 以postgres用户下进入pg2,并进入数据库。规划中datanode1配置端口号是5433
psql -p 5433
6) 并操作数据库
psql (PGXL 9.5r1.3, based on PG 9.5.4 (Postgres-XL 9.5r1.3))
Type "help" for help.
postgres=# select * from pgxc_node;
postgres=# create node coord1 with (type=coordinator,host='pg2', port=5432);
postgres=# create node coord2 with (type=coordinator,host='pg3', port=5432);
postgres=# alter node dn1 with (type=datanode, host='pg2',port=5433,primary,preferred);
postgres=# create node dn2 with (type=datanode, host='pg3',port=5433);
postgres=#select pgxc_pool_reload();
postgres=# select * from pgxc_node;
7) 以postgres用户下进入pg2,并进入数据库。规划中datanode2配置端口号是5433
psql -p 5433
8) 并操作数据库
psql (PGXL 9.5r1.3, based on PG 9.5.4 (Postgres-XL 9.5r1.3))
Type "help" for help.
postgres=# select * from pgxc_node;
postgres=# create node coord1 with (type=coordinator,host='pg2', port=5432);
postgres=# create node coord2 with (type=coordinator,host='pg3', port=5432);
postgres=# create node dn1 with (type=datanode, host='pg2',port=5433,primary,preferred);
postgres=# alter node dn2 with (type=datanode, host='pg3',port=5433);
postgres=#select pgxc_pool_reload();
postgres=# select * from pgxc_node;
说明: 集群到此已经按照我们的规划配置完毕!!!!,下面我们开始测试。
说明:从前面我们了解到每个协调器都可以作为集群的入口,而数据节点实际上都是只读的。我们的集群有两个协调器,因此我们可以随便选择一个协调器作为集群测试进行使用,这里我使用的是pg2中coord1节点。
1)、使用postgres用户进入pg2,并进入数据库:psql -p 5432
2)、操作数据库:
psql (PGXL 9.5r1.3, based on PG 9.5.4 (Postgres-XL 9.5r1.3))
Type "help" for help.
postgres=# create table t1(id integer, name varchar(20)); #说明:无论从哪一个集群的入口建表,实际上是给整个集群都建表。
postgres=# insert into t1 values(1,'测试1');
postgres=# insert into t1 values(2,'测试2');
postgres=# insert into t1 values(3,'测试3');
postgres=# insert into t1 values(4,'测试4');
3)、这时候我们的集群已经有了表,并且有了几条数据。
当我们从集群另外的pg3中coord2进入并查询数据,同样可以查询到刚插入的数据。
但如果我们直接从集群的每个数据节点进入,并执行查询,只能查询到部分数据,这里我们实际看到集群中的数据节点实际上轮流存储的。ok,至此我们的测试已经完成了。