pg_paxos
pg_paxos可用于跨多个PostgreSQL服务器复制表。通过Paxos记录复制表上的每个INSERT / UPDATE / DELETE。当对表执行查询时,pg_paxos首先确保已应用Multi-Paxos日志中的所有先前查询,从而提供。一致性强通过使用的Paxos算法,pg_paxos对于少数节点(读取:服务器)的故障也是健壮的,例如5个中的2个。此实验性的代码网址为: https://github.com/citusdata/pg_paxos/#the-paxos-algorithm
paxos算法
Paxos(K,V)是一个函数,它在某个组(k)的的组中的所有节点上返回相同的值,并且该值是输入之一(v)中。例如,节点可能会调用的Paxos(” leader','primary = node-a')来分配永久组长.paxos(k,v)首先选择提议编号n(通常为0),然后尝试在两个阶段中获得大多数节点接受的值:
- 一)要求大多数节点拒绝具有小于Ñ的数字(或等于较低节点ID)的密钥ķ的提议,并返回任何先前接受的值及其提议编号
B)如果某个值已被一个或多个接受节点,然后v采用具有最高提议编号的值 - 要求第1阶段的响应者接受提议N,其值为V,用于密钥ķ
如果在任何阶段,提议者都无法获得多数人的确认,无论是由于失败还是由于基于提案编号的拒绝,那么它将重新启动,其中n =响应中的最高提案编号+ 1,直到提案成功为止该函数返回诉
- 1A。确保提议者在大多数人中拥有独占访问权限,它基本上是抢占锁定
- 1B。确保一旦多数接受一个值就永远不会改变一个值,因为如果没有至少一个节点具有现有值,则提议者不能获得新的多数
- 如果多数锁没有被抢占,则达成共识,这意味着任何其他提议仍需要为大多数至少一个节点完成1a中,因此将看到图1b中的值
任何后续提议都将在阶段2中使用相同的值,因此的Paxos始终在所有节点上返回相同的值。
paxos源码安装
安装前的准备
主机 | IP |
---|---|
master | 192.168.32.150 |
segment1 | 192.168.32.151 |
segment2 | 192.168.32.152 |
首先要将centOS系统中安装postgreSQL数据库 版本为PostgreSQL-9.6.0
,除此之外明确数据库的两个文件夹的位置bin
和 data
cd /var/postgresql/data
vim pg_hba.conf
#host all all 0.0.0.0/0 trust
vim postgresql.conf
#listen_address='*'
#port = 5432
此外需要关闭防火墙和selinux
systemctl stop firewalld.serice #关闭防火墙
systemctl disable firewalld #禁止防火墙自动启动
setenforce 0 #关闭selinux防火墙
正式开始安装
安装前期准备(master+segment 1+segment 2)
首先从git上将代码克隆到本地
git clone https://github.com/citusdata/pg_paxos.git
cd pg_paxos
PATH=/usr/local/postgresql/bin/:$PATH make
sudo PATH=/usr/local/postgresql/bin/:$PATH make install
安装dblink扩展
#进入postgresql 源代码的目录中,注意是源代码!
cd /home/yiyi/postgresql/contrib/dblink
make && make install
安装dblink后创建扩展
su - postgres #进入postgres用户下
psql
CREATE EXTENSION dblink;
CREATE EXTENSION pg_paxos;
修改配置文件 postgresql.conf
shared_preload_libraries = 'pg_paxos'
pg_paxos.node_id = '独一无二不会混淆的id,自己命名'
修改后需要重启postgresql
#首先进入bin目录下
cd /usr/local/postgresql/bin
#重启postgres
./pg_ctl restart -D /var/postgresql/data/
设置表复制
要使用复制表设置,首先要在所有节点上创建表
CREATE TABLE coordinates (
x int,
y int
);
% 在master + segment1 + segment2上创建
接下来在其中一个节点上,调用paxos_create_group创建一个名为paxos的组,节点本身为唯一成员(使用其外部地址定义为连接字符串 )
# 仅在master 节点运行
SELECT paxos_create_group('foxi', 'host=192.168.32.150');
SELECT paxos_replicate_table('foxi', 'coordinates');
要添加另一个节点 (192.168.32.151 ),连接到节点并使用组的名称。
# 在 segement 1 上运行
SELECT paxos_join_group('foxi', 'host=192.168.32.150', 'host=192.168.32.151');
# 在 segement 2 上运行
SELECT paxos_join_group('foxi', 'host=192.168.32.150', 'host=192.168.32.152');
paxos安装后
如何设置元数据
[root@mlocalhost pg_paxos]$ psql
psql (9.6.0)
Type "help" for help.
postgres=# INSERT INTO coordinates VALUES (1,1);
INSERT 0 1
postgres=# INSERT INTO coordinates VALUES (2,2);
INSERT 0 1
postgres=# SELECT * FROM coordinates ;
x | y
---+---
1 | 1
2 | 2
(2 rows)
postgres=# \q
[root@mlocalhost pg_paxos]$ psql
psql (9.6.0)
Type "help" for help.
postgres=# SELECT * FROM coordinates ;
DEBUG: Executing: INSERT INTO coordinates VALUES (1,1);
CONTEXT: SQL statement "SELECT paxos_apply_log($1,$2,$3)"
DEBUG: Executing: INSERT INTO coordinates VALUES (2,2);
CONTEXT: SQL statement "SELECT paxos_apply_log($1,$2,$3)"
x | y
---+---
1 | 1
2 | 2
(2 rows)
postgres=# UPDATE coordinates SET x = x * 10;
UPDATE 2
postgres=# \q
[root@mlocalhost pg_paxos]$ psql
psql (9.6.0)
Type "help" for help.
postgres=# SELECT * FROM coordinates ;
DEBUG: Executing: INSERT INTO coordinates VALUES (1,1);
CONTEXT: SQL statement "SELECT paxos_apply_log($1,$2,$3)"
DEBUG: Executing: INSERT INTO coordinates VALUES (2,2);
CONTEXT: SQL statement "SELECT paxos_apply_log($1,$2,$3)"
DEBUG: Executing: UPDATE coordinates SET x = x * 10;
CONTEXT: SQL statement "SELECT paxos_apply_log($1,$2,$3)"
x | y
----+---
10 | 1
20 | 2
(2 rows)
更改一致性模型
默认情况下,pg_paxos在每次读取之前向其他节点询问日志中接受的最高轮数。然后,它在日志中应用SQL查询,包括最高可接受的轮数,这确保了强一致性。在某些情况下,低读取延迟可能优于强一致性。pg_paxos.consistency_model设置可以更改为'optimistic',在这种情况下,节点假定它已经了解了先前的写入。乐观一致性模型在没有失败的情况下提供读写一致性,但在发生故障时可能会返回较旧的结果。
SET pg_paxos.consistency_model TO 'optimistic';
SET pg_paxos.consistency_model TO 'strong';
内部表复制功能
执行查询时,在使用表复制时会自动调用以下函数。我们将展示如何明确地调用它们来阐明pg_paxos的内部结构。
paxos_apply_and_append函数(写入时调用)在确保已执行日志中之前的所有查询之后,将SQL查询附加到日志。
SELECT * FROM paxos_apply_and_append(
current_proposer_id := 'node-a/1251',
current_group_id := 'ha_postgres',
proposed_value := 'INSERT INTO coordinates VALUES (3,3)');
paxos_apply_log函数(在SELECT上调用)执行日志中针对给定组的所有SQL查询,这些查询尚未执行,包括整数max_round_num。
SELECT * FROM paxos_apply_log(
current_proposer_id := 'node-a/1252',
current_group_id := 'ha_postgres',
max_round_num := 3);
paxos_max_group_round函数查询大多数主机的最高接受轮数.paxos_max_group_round返回的回合数将大于或等于对paxos_max_group_round调用开始时达成共识(多数已接受)的任何回合。因此,如果节点将日志应用于该轮数,则保证节点看到任何先前的写入 。
SELECT * FROM paxos_max_group_round(
current_group_id := 'ha_postgres');
直接使用paxos功能
您还可以通过直接调用paxos函数使用pg_paxos实现任意分布式日志。以下查询将值'primary = node -a'附加到组ha_postgres的多Paxos日志中:
SELECT * FROM paxos_append(
current_proposer_id := 'node-a/1253',
current_group_id := 'ha_postgres',
proposed_value := 'primary = node-a');
current_proposer_id是一个值,对于给定的组和舍入,在整个群集中应该是唯一的。这主要用于确定当两个提议者提出相同的值时接受哪个提案。
可以使用以下方法检索多的Paxos日志中的最新值:
SELECT * FROM paxos(
current_proposer_id := 'node-a/1254',
current_group_id := 'ha_postgres',
current_round_num := paxos_max_group_round('ha_postgres'));