pg_paxos
pg_paxos可用于跨多個PostgreSQL服務器復制表纬傲。通過Paxos記錄復制表上的每個INSERT / UPDATE / DELETE。當對表執(zhí)行查詢時羊壹,pg_paxos首先確保已應用Multi-Paxos日志中的所有先前查詢,從而提供艺骂。一致性強通過使用的Paxos算法汞舱,pg_paxos對于少數(shù)節(jié)點(讀任槿摇:服務器)的故障也是健壯的,例如5個中的2個昂芜。此實驗性的代碼網(wǎng)址為: https://github.com/citusdata/pg_paxos/#the-paxos-algorithm
paxos算法
Paxos(K莹规,V)是一個函數(shù),它在某個組(k)的的組中的所有節(jié)點上返回相同的值泌神,并且該值是輸入之一(v)中良漱。例如,節(jié)點可能會調用的Paxos(” leader'欢际,'primary = node-a')來分配永久組長.paxos(k母市,v)首先選擇提議編號n(通常為0),然后嘗試在兩個階段中獲得大多數(shù)節(jié)點接受的值:
- 一)要求大多數(shù)節(jié)點拒絕具有小于?的數(shù)字(或等于較低節(jié)點ID)的密鑰?的提議损趋,并返回任何先前接受的值及其提議編號
B)如果某個值已被一個或多個接受節(jié)點患久,然后v采用具有最高提議編號的值 - 要求第1階段的響應者接受提議N,其值為V舶沿,用于密鑰?
如果在任何階段墙杯,提議者都無法獲得多數(shù)人的確認,無論是由于失敗還是由于基于提案編號的拒絕括荡,那么它將重新啟動,其中n =響應中的最高提案編號+ 1溉旋,直到提案成功為止該函數(shù)返回訴
- 1A畸冲。確保提議者在大多數(shù)人中擁有獨占訪問權限,它基本上是搶占鎖定
- 1B观腊。確保一旦多數(shù)接受一個值就永遠不會改變一個值邑闲,因為如果沒有至少一個節(jié)點具有現(xiàn)有值,則提議者不能獲得新的多數(shù)
- 如果多數(shù)鎖沒有被搶占梧油,則達成共識苫耸,這意味著任何其他提議仍需要為大多數(shù)至少一個節(jié)點完成1a中,因此將看到圖1b中的值
任何后續(xù)提議都將在階段2中使用相同的值儡陨,因此的Paxos始終在所有節(jié)點上返回相同的值褪子。
paxos源碼安裝
安裝前的準備
主機 | IP |
---|---|
master | 192.168.32.150 |
segment1 | 192.168.32.151 |
segment2 | 192.168.32.152 |
首先要將centOS系統(tǒng)中安裝postgreSQL數(shù)據(jù)庫 版本為PostgreSQL-9.6.0
,除此之外明確數(shù)據(jù)庫的兩個文件夾的位置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后創(chuàng)建擴展
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/
設置表復制
要使用復制表設置嫌褪,首先要在所有節(jié)點上創(chuàng)建表
CREATE TABLE coordinates (
x int,
y int
);
% 在master + segment1 + segment2上創(chuàng)建
接下來在其中一個節(jié)點上呀枢,調用paxos_create_group創(chuàng)建一個名為paxos的組,節(jié)點本身為唯一成員(使用其外部地址定義為連接字符串 )
# 僅在master 節(jié)點運行
SELECT paxos_create_group('foxi', 'host=192.168.32.150');
SELECT paxos_replicate_table('foxi', 'coordinates');
要添加另一個節(jié)點 (192.168.32.151 )笼痛,連接到節(jié)點并使用組的名稱裙秋。
# 在 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安裝后
如何設置元數(shù)據(jù)
[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在每次讀取之前向其他節(jié)點詢問日志中接受的最高輪數(shù)缨伊。然后摘刑,它在日志中應用SQL查詢,包括最高可接受的輪數(shù)刻坊,這確保了強一致性枷恕。在某些情況下,低讀取延遲可能優(yōu)于強一致性紧唱。pg_paxos.consistency_model設置可以更改為'optimistic'活尊,在這種情況下,節(jié)點假定它已經(jīng)了解了先前的寫入漏益。樂觀一致性模型在沒有失敗的情況下提供讀寫一致性约急,但在發(fā)生故障時可能會返回較舊的結果姨夹。
SET pg_paxos.consistency_model TO 'optimistic';
SET pg_paxos.consistency_model TO 'strong';
內部表復制功能
執(zhí)行查詢時,在使用表復制時會自動調用以下函數(shù)。我們將展示如何明確地調用它們來闡明pg_paxos的內部結構鞋诗。
paxos_apply_and_append函數(shù)(寫入時調用)在確保已執(zhí)行日志中之前的所有查詢之后,將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函數(shù)(在SELECT上調用)執(zhí)行日志中針對給定組的所有SQL查詢晰骑,這些查詢尚未執(zhí)行,包括整數(shù)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函數(shù)查詢大多數(shù)主機的最高接受輪數(shù).paxos_max_group_round返回的回合數(shù)將大于或等于對paxos_max_group_round調用開始時達成共識(多數(shù)已接受)的任何回合纷宇。因此,如果節(jié)點將日志應用于該輪數(shù)蛾方,則保證節(jié)點看到任何先前的寫入 像捶。
SELECT * FROM paxos_max_group_round(
current_group_id := 'ha_postgres');
直接使用paxos功能
您還可以通過直接調用paxos函數(shù)使用pg_paxos實現(xiàn)任意分布式日志。以下查詢將值'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'));