forked from le0pard/postgresql_book
-
Notifications
You must be signed in to change notification settings - Fork 0
/
postgresql_pgpool.tex
531 lines (359 loc) · 41.8 KB
/
postgresql_pgpool.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
\chapter{PgPool-II}
\begin{epigraphs}
\qitem{Имеется способ сделать лучше~--- найди его}{Томас Алва Эдисон}
\end{epigraphs}
\section{Введение}
Pgpool-II~--- это прослойка, работающая между серверами PostgreSQL и клиентами СУБД PostgreSQL. Она предоставляет следующие функции:
\begin{itemize}
\item \textbf{Объединение соединений}
Pgpool-II сохраняет соединения с серверами PostgreSQL и использует их повторно в случае если новое соединение устанавливается с теми же параметрами (т.~е. имя пользователя, база данных, версия протокола). Это уменьшает накладные расходы на соединения и увеличивает производительность системы в целом;
\item \textbf{Репликация}
Pgpool-II может управлять множеством серверов PostgreSQL. Использование функции репликации данных позволяет создание резервной копии данных в реальном времени на 2 или более физических дисков, так что сервис может продолжать работать без остановки серверов в случае выхода из строя диска;
\item \textbf{Балансировка нагрузки}
Если база данных реплицируется, то выполнение запроса SELECT на любом из серверов вернет одинаковый результат. pgpool-II использует преимущество функции репликации для уменьшения нагрузки на каждый из серверов PostgreSQL распределяя запросы \lstinline!SELECT! на несколько серверов, тем самым увеличивая производительность системы в целом. В лучшем случае производительность возрастает пропорционально числу серверов PostgreSQL. Балансировка нагрузки лучше всего работает в случае когда много пользователей выполняют много запросов в одно и то же время.
\item \textbf{Ограничение лишних соединений}
Существует ограничение максимального числа одновременных соединений с PostgreSQL, при превышении которого новые соединения отклоняются. Установка максимального числа соединений, в то же время, увеличивает потребление ресурсов и снижает производительность системы. pgpool-II также имеет ограничение на максимальное число соединений, но <<лишние>> соединения будут поставлены в очередь вместо немедленного возврата ошибки.
\item \textbf{Параллельные запросы}
Используя функцию параллельных запросов можно разнести данные на множество серверов, благодаря чему запрос может быть выполнен на всех серверах одновременно для уменьшения общего времени выполнения. Параллельные запросы работают лучше всего при поиске в больших объемах данных.
\end{itemize}
Pgpool-II общается по протоколу бэкенда и фронтенда PostgreSQL и располагается между ними. Таким образом, приложение базы данных считает что pgpool-II~--- настоящий сервер PostgreSQL, а сервер видит pgpool-II как одного из своих клиентов. Поскольку pgpool-II прозрачен как для сервера, так и для клиента, существующие приложения, работающие с базой данных, могут использоваться с pgpool-II практически без изменений в исходном коде.
\section{Установка и настройка}
Во многих Linux системах pgpool-II может находиться в репозитории пакетов. Для Ubuntu Linux, например, достаточно будет выполнить:
\begin{lstlisting}[language=Bash,label=lst:pgpool3,caption=Установка pgpool-II]
$ sudo aptitude install pgpool2
\end{lstlisting}
\subsection{Настройка}
Параметры конфигурации pgpool-II хранятся в файле \lstinline!pgpool.conf!. Формат файла: одна пара \lstinline!параметр = значение! в строке. При установке pgpool-II автоматически создается файл \lstinline!pgpool.conf.sample!:
\begin{lstlisting}[language=Bash,label=lst:pgpool4,caption=Файлы конфигурации]
$ cp /usr/local/etc/pgpool.conf.sample /usr/local/etc/pgpool.conf
\end{lstlisting}
Pgpool-II принимает соединения только с \lstinline!localhost! на порт 9999. Если требуется принимать соединения с других хостов, установите для параметра \lstinline!listen_addresses! значение <<*>>.
\begin{lstlisting}[label=lst:pgpool5,caption=Файлы конфигурации]
listen_addresses = 'localhost'
port = 9999
\end{lstlisting}
\subsection{Настройка команд PCP}
У pgpool-II есть PCP интерфейс для административных целей (получить информацию об узлах базы данных, остановить pgpool-II, прочее). Чтобы использовать команды PCP, необходима идентификация пользователя. Эта идентификация отличается от идентификации пользователей в PostgreSQL. Имя пользователя и пароль нужно указывать в файле \lstinline!pcp.conf!. В этом файле имя пользователя и пароль указываются как пара значений, разделенных двоеточием (:). Одна пара в строке, пароли зашифрованы в формате хэша md5:
\begin{lstlisting}[label=lst:pgpool6,caption=Настройка команд PCP]
postgres:e8a48653851e28c69d0506508fb27fc5
\end{lstlisting}
Для того чтобы зашифровать пароль в формате md5 хэша используется команда \lstinline!pg_md5!, которая устанавливается как один из исполняемых файлов pgpool-II. \lstinline!pg_md5! принимает текст в параметре командной строки и отображает md5 хэш как результат.
\begin{lstlisting}[label=lst:pgpool8,caption=Настройка команд PCP]
$ /usr/bin/pg_md5 postgres
e8a48653851e28c69d0506508fb27fc5
\end{lstlisting}
Команды PCP выполняются по сети, так что в файле \lstinline!pgpool.conf! должен быть указан номер порта в параметре \lstinline!pcp_port!:
\begin{lstlisting}[label=lst:pgpool9,caption=Настройка команд PCP]
pcp_port = 9898
\end{lstlisting}
\subsection{Подготовка узлов баз данных}
Далее требуется настроить серверы бэкендов PostgreSQL для pgpool-II. Эти серверы могут быть размещены на одном хосте с pgpool-II или на отдельных машинах. Если вы решите разместить серверы на том же хосте, для всех серверов должны быть установлены разные номера портов. Если серверы размещены на отдельных машинах, они должны быть настроены так чтобы могли принимать сетевые соединения от pgpool-II. В данном примере три сервера PostgreSQL размещено в рамках одного хоста вместе с pgpool-II (5432, 5433, 5434 порты соответственно):
\begin{lstlisting}[label=lst:pgpool10,caption=Подготовка узлов баз данных]
backend_hostname0 = 'localhost'
backend_port0 = 5432
backend_weight0 = 1
backend_hostname1 = 'localhost'
backend_port1 = 5433
backend_weight1 = 1
backend_hostname2 = 'localhost'
backend_port2 = 5434
backend_weight2 = 1
\end{lstlisting}
В параметрах \lstinline!backend_hostname!, \lstinline!backend_port!, \lstinline!backend_weight! указывается имя хоста узла базы данных, номер порта и коэффициент для балансировки нагрузки. В конце имени каждого параметра должен быть указан идентификатор узла путем добавления положительного целого числа начиная с 0. Параметры \lstinline!backend_weight! все равны 1, что означает что запросы \lstinline!SELECT! равномерно распределены по трем серверам.
\section{Настройка репликации}
Pgpool-II репликация включает копирование одних и тех же данных на множество узлов базы данных (синхронная репликация). Но данная репликация имеет тот недостаток, что она создаёт дополнительную нагрузку при выполнении всех транзакций, в которых обновляются какие-либо реплики (кроме того, могут возникать проблемы, связанные с доступностью данных).
\subsection{Настройка репликации}
Чтобы включить функцию репликации базы данных установите значение \lstinline!true! для параметра \lstinline!replication_mode! в файле \lstinline!pgpool.conf!.
\begin{lstlisting}[label=lst:pgpool17,caption=Настройка репликации]
replication_mode = true
\end{lstlisting}
Если параметр \lstinline!replication_mode! равен \lstinline!true!, pgpool-II будет отправлять копию принятого запроса на все узлы базы данных.
Если параметр \lstinline!load_balance_mode! равен \lstinline!true!, pgpool-II будет распределять запросы \lstinline!SELECT! между узлами базы данных.
\begin{lstlisting}[label=lst:pgpool18,caption=Настройка репликации]
load_balance_mode = true
\end{lstlisting}
\subsection{Проверка репликации}
После настройки \lstinline!pgpool.conf! и перезапуска pgpool-II, можно проверить репликацию в действии. Для этого создадим базу данных, которую будем реплицировать (базу данных нужно создать на всех узлах):
\begin{lstlisting}[language=Bash,label=lst:pgpool19,caption=Проверка репликации]
$ createdb -p 9999 bench_replication
\end{lstlisting}
Затем запустим \lstinline!pgbench! с параметром \lstinline!-i!. Параметр \lstinline!-i! инициализирует базу данных предопределенными таблицами и данными в них.
\begin{lstlisting}[label=lst:pgpool20,caption=Проверка репликации]
$ pgbench -i -p 9999 bench_replication
\end{lstlisting}
Указанная ниже таблица содержит сводную информацию о таблицах и данных, которые будут созданы при помощи \lstinline!pgbench -i!. Если на всех узлах базы данных перечисленные таблицы и данные были созданы, репликация работает корректно.
\begin{tabular}{ | c | c | }
\hline
Имя таблицы & Число строк \\
\hline
branches & 1 \\
\hline
tellers & 10 \\
\hline
accounts & 100000 \\
\hline
history & 0 \\
\hline
\end{tabular}
Для проверки указанной выше информации на всех узлах используем простой скрипт на shell:
\begin{lstlisting}[label=lst:pgpool21,caption=Проверка репликации]
for port in 5432 5433 5434; do
> echo $port
> for table_name in branches tellers accounts history; do
> echo $table_name
> psql -c "SELECT count(*) FROM $table_name" -p \
> $port bench_replication
> done
> done
\end{lstlisting}
\section{Параллельное выполнение запросов}
Pgpool-II позволяет использовать распределение для таблиц. Данные из разных диапазонов сохраняются на двух или более узлах базы данных параллельным запросом. Более того, одни и те же данные на двух и более узлах базы данных могут быть воспроизведены с использованием распределения.
Чтобы включить параллельные запросы в pgpool-II вы должны установить еще одну базу данных, называемую <<системной базой данных>> (<<System Database>>) (далее будет называться SystemDB). SystemDB хранит определяемые пользователем правила, определяющие какие данные будут сохраняться на каких узлах базы данных. Также SystemDB используется чтобы объединить результаты возвращенные узлами базы данных посредством dblink.
\subsection{Настройка}
Чтобы включить функцию выполнения параллельных запросов требуется установить для параметра \lstinline!parallel_mode! значение \lstinline!true! в файле \lstinline!pgpool.conf!:
\begin{lstlisting}[label=lst:pgpool22,caption=Настройка параллельного запроса]
parallel_mode = true
\end{lstlisting}
Установка параметра \lstinline!parallel_mode! равным \lstinline!true! не запустит параллельные запросы автоматически. Для этого pgpool-II нужна SystemDB и правила определяющие как распределять данные по узлам базы данных. Также SystemDB использует dblink для создания соединений с pgpool-II. Таким образом, нужно установить значение параметра \lstinline!listen_addresses! таким образом чтобы pgpool-II принимал эти соединения:
\begin{lstlisting}[label=lst:pgpool23,caption=Настройка параллельного запроса]
listen_addresses = '*'
\end{lstlisting}
Нужно обратить внимание, что репликация не реализована для таблиц, которые распределяются посредством параллельных запросов. Поэтому:
\begin{lstlisting}[label=lst:pgpool24,caption=Настройка параллельного запроса]
replication_mode = true
load_balance_mode = false
\end{lstlisting}
или
\begin{lstlisting}[label=lst:pgpool25,caption=Настройка параллельного запроса]
replication_mode = false
load_balance_mode = true
\end{lstlisting}
\subsection{Настройка SystemDB}
В основном, нет отличий между простой и системной базами данных. Однако, в системной базе данных определяется функция dblink и присутствует таблица, в которой хранятся правила распределения данных. Таблицу \lstinline!dist_def! необходимо определять. Более того, один из узлов базы данных может хранить системную базу данных, а pgpool-II может использоваться для распределения нагрузки каскадным подключением.
Создадим SystemDB на узле с портом 5432. Далее приведен список параметров конфигурации для SystemDB:
\begin{lstlisting}[label=lst:pgpool26,caption=Настройка SystemDB]
system_db_hostname = 'localhost'
system_db_port = 5432
system_db_dbname = 'pgpool'
system_db_schema = 'pgpool_catalog'
system_db_user = 'pgpool'
system_db_password = ''
\end{lstlisting}
На самом деле, указанные выше параметры являются параметрами по умолчанию в файле \lstinline!pgpool.conf!. Теперь требуется создать пользователя с именем <<pgpool>> и базу данных с именем <<pgpool>> и владельцем <<pgpool>>:
\begin{lstlisting}[language=Bash,label=lst:pgpool27,caption=Настройка SystemDB]
$ createuser -p 5432 pgpool
$ createdb -p 5432 -O pgpool pgpool
\end{lstlisting}
\subsubsection{Установка dblink}
Далее требуется установить dblink в базу данных <<pgpool>>. Dblink~--- один из инструментов включенных в каталог contrib исходного кода PostgreSQL. После того как dblink был установлен в вашей системе мы добавим функции dblink в базу данных <<pgpool>>.
\begin{lstlisting}[language=Bash,label=lst:pgpool29,caption=Установка dblink]
$ psql -c "CREATE EXTENSION dblink;" -p 5432 pgpool
\end{lstlisting}
\subsubsection{Создание таблицы dist\_def}
Следующим шагом мы создадим таблицу с именем \lstinline!dist_def!, в которой будут храниться правила распределения данных. Поскольку pgpool-II уже был установлен, файл с именем \lstinline!system_db.sql! должен быть установлен в \lstinline!/usr/local/share/system_db.sql! (имейте в виду, что на вашей системе каталог установки может быть другой). Файл \lstinline!system_db.sql! содержит директивы для создания специальных таблиц, включая и таблицу \lstinline!dist_def!. Выполним следующую команду для создания таблицы \lstinline!dist_def!:
\begin{lstlisting}[language=Bash,label=lst:pgpool30,caption=Создание таблицы dist\_def]
$ psql -f /usr/local/share/system_db.sql -p 5432 -U pgpool pgpool
\end{lstlisting}
Все таблицы в файле \lstinline!system_db.sql!, включая \lstinline!dist_def!, создаются в схеме \lstinline!pgpool_catalog!. Если вы установили параметр \lstinline!system_db_schema! на использование другой схемы, вам нужно, соответственно, отредактировать файл \lstinline!system_db.sql!. Описание таблицы \lstinline!dist_def! выглядит так как показано ниже:
\begin{lstlisting}[language=SQL,label=lst:pgpool31,caption=Создание таблицы dist\_def]
CREATE TABLE pgpool_catalog.dist_def (
dbname text, -- имя базы данных
schema_name text, -- имя схемы
table_name text, -- имя таблицы
col_name text NOT NULL CHECK (col_name = ANY (col_list)),
-- столбец ключ для распределения данных
col_list text[] NOT NULL, -- список имен столбцов
type_list text[] NOT NULL, -- список типов столбцов
dist_def_func text NOT NULL,
-- имя функции распределения данных
PRIMARY KEY (dbname, schema_name, table_name)
);
\end{lstlisting}
Записи, хранимые в таблице \lstinline!dist_def!, могут быть двух типов:
\begin{itemize}
\item Правило распределения данных (\lstinline!col_name!, \lstinline!dist_def_func!);
\item Мета-информация о таблицах (\lstinline!dbname!, \lstinline!schema_name!, \lstinline!table_name!, \lstinline!col_list!, \lstinline!type_list!);
\end{itemize}
Правило распределения данных определяет как будут распределены данные на конкретный узел базы данных. Данные будут распределены в зависимости от значения столбца \lstinline!col_name!. \lstinline!dist_def_func!~--- это функция, которая принимает значение \lstinline!col_name! в качестве аргумента и возвращает целое число, которое соответствует идентификатору узла базы данных, на котором должны быть сохранены данные. Мета-информация используется для того чтобы переписывать запросы. Параллельный запрос должен переписывать исходные запросы так чтобы результаты, возвращаемые узлами-бэкендами, могли быть объединены в единый результат.
\subsubsection{Создание таблицы replicate\_def}
В случае если указана таблица, для которой производится репликация в выражение SQL, использующее зарегистрированную в \lstinline!dist_def! таблицу путем объединения таблиц, информация о таблице, для которой необходимо производить репликацию, предварительно регистрируется в таблице с именем \lstinline!replicate_def!. Таблица \lstinline!replicate_def! будет создана при обработке файла \lstinline!system_db.sql!. Таблица \lstinline!replicate_def! описана так как показано ниже:
\begin{lstlisting}[language=SQL,label=lst:pgpool31:1,caption=Создание таблицы replicate\_def]
CREATE TABLE pgpool_catalog.replicate_def (
dbname text, -- имя базы данных
schema_name text, -- имя схемы
table_name text, -- имя таблицы
col_list text[] NOT NULL, -- список имен столбцов
type_list text[] NOT NULL, -- список типов столбцов
PRIMARY KEY (dbname, schema_name, table_name)
);
\end{lstlisting}
\subsection{Установка правил распределения данных}
В данном примере будут определены правила распределения данных, созданных программой pgbench, на три узла базы данных. Тестовые данные будут созданы командой \lstinline!pgbench -i -s 3! (т.~е. масштабный коэффициент равен 3). Для этого раздела мы создадим новую базу данных с именем \lstinline!bench_parallel!. В каталоге sample исходного кода pgpool-II вы можете найти файл \lstinline!dist_def_pgbench.sql!. Будем использоваться этот файл с примером для создания правил распределения для pgbench. Выполним следующую команду в каталоге с распакованным исходным кодом pgpool-II:
\begin{lstlisting}[language=Bash,label=lst:pgpool32,caption=Установка правил распределения данных]
$ psql -f sample/dist_def_pgbench.sql -p 5432 pgpool
\end{lstlisting}
В файле \lstinline!dist_def_pgbench.sql! мы добавляем одну строку в таблицу \lstinline!dist_def!. Это функция распределения данных для таблицы \lstinline!accounts!. В качестве столбца-ключа указан столбец \lstinline!aid!.
\begin{lstlisting}[language=SQL,label=lst:pgpool33,caption=Установка правил распределения данных]
INSERT INTO pgpool_catalog.dist_def VALUES (
'bench_parallel',
'public',
'accounts',
'aid',
ARRAY['aid', 'bid', 'abalance', 'filler'],
ARRAY['integer', 'integer', 'integer',
'character(84)'],
'pgpool_catalog.dist_def_accounts'
);
\end{lstlisting}
Теперь мы должны создать функцию распределения данных для таблицы \lstinline!accounts!. Возможно использовать одну и ту же функцию для разных таблиц. Таблица \lstinline!accounts! в момент инициализации данных хранит значение масштабного коэффициента равное 3, значения столбца \lstinline!aid! от 1 до 300000. Функция создана таким образом что данные равномерно распределяются по трем узлам базы данных:
\begin{lstlisting}[language=SQL,label=lst:pgpool34,caption=Установка правил распределения данных]
CREATE OR REPLACE FUNCTION
pgpool_catalog.dist_def_branches(anyelement)
RETURNS integer AS $$
SELECT CASE WHEN $1 > 0 AND $1 <= 1 THEN 0
WHEN $1 > 1 AND $1 <= 2 THEN 1
ELSE 2
END;
$$ LANGUAGE sql;
\end{lstlisting}
\subsection{Установка правил репликации}
Правило репликации~--- это то что определяет какие таблицы должны быть использованы для выполнения репликации. Здесь это сделано при помощи pgbench с зарегистрированными таблицами \lstinline!branches! и \lstinline!tellers!. Как результат, стало возможно создание таблицы \lstinline!accounts! и выполнение запросов, использующих таблицы \lstinline!branches! и \lstinline!tellers!:
\begin{lstlisting}[language=SQL,label=lst:pgpool35,caption=Установка правил репликации]
INSERT INTO pgpool_catalog.replicate_def VALUES (
'bench_parallel',
'public',
'branches',
ARRAY['bid', 'bbalance', 'filler'],
ARRAY['integer', 'integer', 'character(88)']
);
INSERT INTO pgpool_catalog.replicate_def VALUES (
'bench_parallel',
'public',
'tellers',
ARRAY['tid', 'bid', 'tbalance', 'filler'],
ARRAY['integer', 'integer', 'integer', 'character(84)']
);
\end{lstlisting}
Подготовленный файл \lstinline!replicate_def_pgbench.sql! находится в каталоге sample:
\begin{lstlisting}[language=Bash,label=lst:pgpool36,caption=Установка правил репликации]
$ psql -f sample/replicate_def_pgbench.sql -p 5432 pgpool
\end{lstlisting}
\subsection{Проверка параллельного запроса}
После настройки \lstinline!pgpool.conf! и перезапуска pgpool-II возможно провести проверку работоспособности параллельных запросов. Сначала требуется создать базу данных, которая будет распределена. Эту базу данных нужно создать на всех узлах:
\begin{lstlisting}[language=Bash,label=lst:pgpool37,caption=Проверка параллельного запроса]
$ createdb -p 9999 bench_parallel
\end{lstlisting}
Затем запустим pgbench с параметрами \lstinline!-i -s 3!:
\begin{lstlisting}[language=Bash,label=lst:pgpool38,caption=Проверка параллельного запроса]
$ pgbench -i -s 3 -p 9999 bench_parallel
\end{lstlisting}
Один из способов проверить корректно ли были распределены данные~--- выполнить запрос \lstinline!SELECT! посредством pgpool-II и напрямую на бэкендах и сравнить результаты. Если все настроено правильно база данных \lstinline!bench_parallel! должна быть распределена как показано ниже:
\begin{tabular}{ | c | c | }
\hline
Имя таблицы & Число строк \\
\hline
branches & 3 \\
\hline
tellers & 30 \\
\hline
accounts & 300000 \\
\hline
history & 0 \\
\hline
\end{tabular}
Для проверки указанной выше информации на всех узлах и посредством pgpool-II используем простой скрипт на shell. Приведенный ниже скрипт покажет минимальное и максимальное значение в таблице accounts используя для соединения порты 5432, 5433, 5434 и 9999.
\begin{lstlisting}[label=lst:pgpool39,caption=Проверка параллельного запроса]
for port in 5432 5433 5434i 9999; do
> echo $port
> psql -c "SELECT min(aid), max(aid) FROM accounts" \
> -p $port bench_parallel
> done
\end{lstlisting}
\section{Master-slave режим}
Этот режим предназначен для использования pgpool-II с другой репликацией (например streaming, londiste). Информация про БД указывается как для репликации. \lstinline!master_slave_mode! и \lstinline!load_balance_mode! устанавливается в \lstinline!true!. pgpool-II будет посылать запросы \lstinline!INSERT/UPDATE/DELETE! на master базу данных (1 в списке), а \lstinline!SELECT!~--- использовать балансировку нагрузки, если это возможно. При этом, DDL и DML для временной таблицы может быть выполнен только на мастере. Если нужен \lstinline!SELECT! только на мастере, то для этого нужно использовать комментарий \lstinline!/*NO LOAD BALANCE*/! перед \lstinline!SELECT!.
В Master/Slave режиме \lstinline!replication_mode! должен быть установлен \lstinline!false!, а \lstinline!master_slave_mode!~--- \lstinline!true!.
\subsection{Streaming Replication (Потоковая репликация)}
В master-slave режиме с потоковой репликацией, если мастер или слейв упал, возможно использовать отказоустойчивый функционал внутри pgpool-II. Автоматически отключив упавший инстанс PostgreSQL, pgpool-II переключится на следующий слейв как на новый мастер (при падении мастера), или останется работать на мастере (при падении слейва). В потоковой репликации, когда слейв становится мастером, требуется создать триггер файл (который указан в \lstinline!recovery.conf!, параметр \lstinline!trigger_file!), чтобы PostgreSQL перешел из режима восстановления в нормальный. Для этого можно создать небольшой скрипт:
\begin{lstlisting}[label=lst:pgpool40,caption=Скрипт выполняется при падении нода PostgreSQL]
#! /bin/sh
# Failover command for streming replication.
# This script assumes that DB node 0 is primary, and 1 is standby.
#
# If standby goes down, does nothing. If primary goes down, create a
# trigger file so that standby take over primary node.
#
# Arguments: $1: failed node id. $2: new master hostname. $3: path to
# trigger file.
failed_node=$1
new_master=$2
trigger_file=$3
# Do nothing if standby goes down.
if [ $failed_node = 1 ]; then
exit 0;
fi
# Create trigger file.
/usr/bin/ssh -T $new_master /bin/touch $trigger_file
exit 0;
\end{lstlisting}
Работает скрипт просто: если падает слейв~--- скрипт ничего не выполняет, при падении мастера~--- создает триггер файл на новом мастере. Сохраним этот файл под именем \lstinline!failover\_stream.sh! и добавим в \lstinline!pgpool.conf!:
\begin{lstlisting}[label=lst:pgpool41,caption=Что выполнять при падении нода]
failover_command = '/path_to_script/failover_stream.sh %d %H /tmp/trigger_file'
\end{lstlisting}
где \lstinline!/tmp/trigger_file!~--- триггер файл, указанный в конфиге \lstinline!recovery.conf!. Теперь, если мастер СУБД упадет, слейв будет переключен из режима восстановления в обычный и сможет принимать запросы на запись.
\section{Онлайн восстановление}
Pgpool-II в режиме репликации может синхронизировать базы данных и добавлять их как новые ноды. Называется это <<онлайн восстановление>>. Этот метод также может быть использован когда нужно вернуть в репликацию упавший нод базы данных. Вся процедура выполняется в два задания. Несколько секунд или минут клиент может ждать подключения к pgpool, в то время как восстанавливается узел базы данных. Онлайн восстановление состоит из следующих шагов:
\begin{itemize}
\item CHECKPOINT;
\item Первый этап восстановления;
\item Ждем, пока все клиенты не отключатся;
\item CHECKPOINT;
\item Второй этап восстановления;
\item Запуск postmaster (выполнить \lstinline!pgpool_remote_start!);
\item Восстанавливаем инстанс СУБД;
\end{itemize}
Для работы онлайн восстановления потребуется указать следующие параметры:
\begin{itemize}
\item \lstinline!backend_data_directory! - каталог данных определенного PostgreSQL кластера;
\item \lstinline!recovery_user! - имя пользователя PostgreSQL;
\item \lstinline!recovery_password! - пароль пользователя PostgreSQL;
\item \lstinline!recovery_1st_stage_command! - параметр указывает команду для первого этапа онлайн восстановления. Файл с командами должен быть помещен в каталог данных СУБД кластера из соображений безопасности. Например, если \lstinline!recovery_1st_stage_command = 'some_script'!, то pgpool-II выполнит \lstinline!$PGDATA/some_script!. Обратите внимание, что pgpool-II принимает подключения и запросы в то время как выполняется \lstinline!recovery_1st_stage!;
\item \lstinline!recovery_2nd_stage_command! - параметр указывает команду для второго этапа онлайн восстановления. Файл с командами должен быть помещен в каталог данных СУБД кластера из-за проблем безопасности. Например, если \lstinline!recovery_2st_stage_command = 'some_script'!, то pgpool-II выполнит \lstinline!$PGDATA/some_script!. Обратите внимание, что pgpool-II НЕ принимает подключения и запросы в то время как выполняется \lstinline!recovery_2st_stage!. Таким образом, pgpool-II будет ждать пока все клиенты не закроют подключения;
\end{itemize}
\subsection{Streaming Replication (Потоковая репликация)}
В master-slave режиме с потоковой репликацией, онлайн восстановление~--- отличное средство вернуть назад упавший инстанс PostgreSQL. Вернуть возможно только слейв ноды, таким методом не восстановить упавший мастер. Для восстановления мастера потребуется остановить все PostgreSQL инстансы и pgpool-II (для восстановления из резервной копии мастера).
Для настройки онлайн восстановления потребуется:
\begin{itemize}
\item Установить \lstinline!recovery_user!. Обычно это <<postgres>>;
\item Установить \lstinline!recovery_password! для \lstinline!recovery_user! для подключения к СУБД;
\item Настроить \lstinline!recovery_1st_stage_command!. Для этого можно создать скрипт \lstinline!basebackup.sh! и положим его в папку с данными мастера (\lstinline!$PGDATA!), установив ему права на выполнение:
\begin{lstlisting}[label=lst:pgpool44,caption=basebackup.sh]
#! /bin/sh
# Recovery script for streaming replication.
# This script assumes that DB node 0 is primary, and 1 is standby.
#
datadir=$1
desthost=$2
destdir=$3
psql -c "SELECT pg_start_backup('Streaming Replication', true)" postgres
rsync -C -a --delete -e ssh --exclude postgresql.conf --exclude postmaster.pid \
--exclude postmaster.opts --exclude pg_log --exclude pg_xlog \
--exclude recovery.conf $datadir/ $desthost:$destdir/
ssh -T localhost mv $destdir/recovery.done $destdir/recovery.conf
psql -c "SELECT pg_stop_backup()" postgres
\end{lstlisting}
При восстановления слейва, скрипт запускает бэкап мастера и через rsync утилиту передает данные с мастера на слейв. Для этого необходимо настроить ssh так, чтобы \lstinline!recovery_user! мог заходить с мастера на слейв без пароля. Далее добавим скрипт на выполнение для первого этапа онлайн восстановления:
\begin{lstlisting}[label=lst:pgpool45,caption=recovery\_1st\_stage\_command]
recovery_1st_stage_command = 'basebackup.sh'
\end{lstlisting}
\item Оставляем \lstinline!recovery_2nd_stage_command! пустым. После успешного выполнения первого этапа онлайн восстановления, разницу в данных, что успели записаться во время работы скрипта \lstinline!basebackup.sh!, слейв инстанс заберет через WAL файлы с мастера;
\item Устанавливаем C и SQL функции для работы онлайн восстановления на каждый инстанс СУБД:
\begin{lstlisting}[language=Bash,label=lst:pgpool46,caption=Устанавливаем C и SQL функции]
$ cd pgpool-II-x.x.x/sql/pgpool-recovery
$ make
$ make install
$ psql -f pgpool-recovery.sql template1
\end{lstlisting}
\end{itemize}
После этого возможно использовать \lstinline!pcp_recovery_node! для онлайн восстановления упавших слейвов.
\section{Заключение}
PgPool-II~--- прекрасное средство, функционал которого может помочь администраторам баз данных при масштабировании PostgreSQL.