在PostgreSQL上搭建pg_paxos

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),然后尝试在两个阶段中获得大多数节点接受的值:

  1. 一)要求大多数节点拒绝具有小于Ñ的数字(或等于较低节点ID)的密钥ķ的提议,并返回任何先前接受的值及其提议编号
    B)如果某个值已被一个或多个接受节点,然后v采用具有最高提议编号的值
  2. 要求第1阶段的响应者接受提议N,其值为V,用于密钥ķ

如果在任何阶段,提议者都无法获得多数人的确认,无论是由于失败还是由于基于提案编号的拒绝,那么它将重新启动,其中n =响应中的最高提案编号+ 1,直到提案成功为止该函数返回诉

  • 1A。确保提议者在大多数人中拥有独占访问权限,它基本上是抢占锁定
  • 1B。确保一旦多数接受一个值就永远不会改变一个值,因为如果没有至少一个节点具有现有值,则提议者不能获得新的多数
    1. 如果多数锁没有被抢占,则达成共识,这意味着任何其他提议仍需要为大多数至少一个节点完成1a中,因此将看到图1b中的值

任何后续提议都将在阶段2中使用相同的值,因此的Paxos始终在所有节点上返回相同的值。

paxos源码安装

安装前的准备

主机IP
master192.168.32.150
segment1192.168.32.151
segment2192.168.32.152

首先要将centOS系统中安装postgreSQL数据库 版本为PostgreSQL-9.6.0,除此之外明确数据库的两个文件夹的位置bindata

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'));
    原文作者:狐狸的面包
    原文地址: https://www.jianshu.com/p/07f0f28e4ea7
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞