forked from le0pard/postgresql_book
-
Notifications
You must be signed in to change notification settings - Fork 1
/
postgresql_replication_londiste.tex
332 lines (274 loc) · 16.3 KB
/
postgresql_replication_londiste.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
\section{Londiste}
\subsection{Введение}
Londiste представляет собой движок для организации репликации, написанный на языке python.
Основные принципы: надежность и простота использования. Из-за этого данное решение имеет меньше функциональности,
чем Slony-I. Londiste использует в качестве транспортного механизма очередь PgQ (описание этого более чем интересного
проекта остается за рамками данной главы, поскольку он представляет интерес скорее для низкоуровневых программистов
баз данных, чем для конечных пользователей~--- администраторов СУБД PostgreSQL). Отличительными особенностями решения являются:
\begin{itemize}
\item возможность потабличной репликации
\item начальное копирование ничего не блокирует
\item возможность двухстороннего сравнения таблиц
\item простота установки
\end{itemize}
К недостаткам можно отнести:
\begin{itemize}
\item отсутствие поддержки каскадной репликации, отказоустойчивости(failover) и переключение между
серверами (switchover) (все это обещают к 3 версии реализовать
\footnote{http://skytools.projects.postgresql.org/skytools-3.0/doc/skytools3.html})
\end{itemize}
\subsection{Установка}
На серверах, которые мы настраиваем расматривается ОС Linux, а именно Ubuntu Server.
Автор данной книги считает, что под другие операционные системы (кроме Windows) все мало чем будет отличаться,
а держать кластера PostgreSQL под ОС Windows, по меньшей мере, неразумно.
Поскольку Londiste~--- это часть Skytools, то нам нужно ставить этот пакет. На таких системах, как Debian или Ubuntu skytools
можно найти в репозитории пакетов и поставить одной командой:
\begin{verbatim}
$sudo aptitude install skytools
\end{verbatim}
Но все же лучше скачать самую последнюю версию пакета с официального сайта~--- http://pgfoundry.org/projects/skytools.
На момент написания статьи последняя версия была 2.1.11. Итак, начнем:
\begin{verbatim}
$wget http://pgfoundry.org/frs/download.php/2561/
skytools-2.1.11.tar.gz
$tar zxvf skytools-2.1.11.tar.gz
$cd skytools-2.1.11/
# это для сборки deb пакета
$sudo aptitude install build-essential autoconf \
automake autotools-dev dh-make \
debhelper devscripts fakeroot xutils lintian pbuilder \
python-dev yada
# ставим пакет исходников для postgresql 8.4.x
$sudo aptitude install postgresql-server-dev-8.4
# python-psycopg нужен для работы Londiste
$sudo aptitude install python-psycopg2
# данной командой я собираю deb пакет для
# postgresql 8.4.x (для 8.3.x например будет "make deb83")
$sudo make deb84
$cd ../
# ставим skytools
$dpkg -i skytools-modules-8.4_2.1.11_i386.deb
skytools_2.1.11_i386.deb
\end{verbatim}
Для других систем можно собрать Skytools командами
\begin{verbatim}
$./configure
$make
$make install
\end{verbatim}
Дальше проверим, что все у нас правильно установилось
\begin{verbatim}
$londiste.py -V
Skytools version 2.1.11
$pgqadm.py -V
Skytools version 2.1.11
\end{verbatim}
Если у Вас похожий вывод, значит все установленно правильно и можно приступать к настройке.
\subsection{Настройка}
Обозначения:
\begin{itemize}
\item host1~--- мастер;
\item host2~--- слейв;
\end{itemize}
\subsubsection{Настройка ticker-а}
Londiste требуется ticker для работы с мастер базой данных, который может быть запущен и на другой машине.
Но, конечно, лучше его запускать на той же, где и мастер база данных. Для этого мы настраиваем специальный
конфиг для ticker-а (пусть конфиг будет у нас /etc/skytools/db1-ticker.ini):
\begin{verbatim}
[pgqadm]
# название
job_name = db1-ticker
# мастер база данных
db = dbname=P host=host1
# Задержка между запусками обслуживания
# (ротация очередей и т.п.) в секундах
maint_delay = 600
# Задержка между проверками наличия активности
# (новых пакетов данных) в секундах
loop_delay = 0.1
# log и pid демона
logfile = /var/log/%(job_name)s.log
pidfile = /var/pid/%(job_name)s.pid
\end{verbatim}
Теперь необходимо инсталлировать служебный код (SQL) и запустить ticker как демона для базы данных.
Делается это с помощью утилиты pgqadm.py следующими командами:
\begin{verbatim}
pgqadm.py /etc/skytools/db1-ticker.ini install
pgqadm.py /etc/skytools/db1-ticker.ini ticker -d
\end{verbatim}
Проверим, что в логах (/var/log/skytools/db1-tickers.log) всё нормально. На данном этапе там должны быть редкие записи (раз в минуту).
Если нам потребуется остановить ticker, мы можем воспользоватся этой командой:
\begin{verbatim}
pgqadm.py /etc/skytools/db1-ticker.ini ticker -s
\end{verbatim}
или если потребуется <<убить>> ticker:
\begin{verbatim}
pgqadm.py /etc/skytools/db1-ticker.ini ticker -k
\end{verbatim}
\subsubsection{Востанавливаем схему базы}
Londiste не умеет переносить изменения структуры базы данных.
Поэтому на всех slave базах данных перед репликацией должна быть создана такая же структура БД, что и на мастере.
\subsubsection{Создаём конфигурацию репликатора}
Для каждой из реплицируемых баз создадим конфигурационные файлы
(пусть конфиг будет у нас /etc/skytools/db1-londiste.ini):
\begin{verbatim}
[londiste]
# название
job_name = db1-londiste
# мастер база данных
provider_db = dbname=db1 port=5432 host=host1
# слейв база данных
subscriber_db = dbname=db1 host=host2
# Это будет использоваться в качестве
# SQL-идентификатора, т.ч. не используйте
# точки и пробелы.
# ВАЖНО! Если есть живая репликация на другой слейв,
# именуем очередь так-же
pgq_queue_name = db1-londiste-queue
# log и pid демона
logfile = /var/log/%(job_name)s.log
pidfile = /var/run/%(job_name)s.pid
# рзмер лога
log_size = 5242880
log_count = 3
\end{verbatim}
\subsubsection{Устанавливаем Londiste в базы на мастере и слейве}
Теперь необходимо установить служебный SQL для каждой из созданных в предыдущем
пункте конфигураций.
Устанавливаем код на стороне мастера:
\begin{verbatim}
londiste.py /etc/skytools/db1-londiste.ini provider install
\end{verbatim}
и подобным образом на стороне слейва:
\begin{verbatim}
londiste.py /etc/skytools/db1-londiste.ini subscriber install
\end{verbatim}
После этого пункта на мастере будут созданы очереди для репликации.
\subsubsection{Запускаем процессы Londiste}
Для каждой реплицируемой базы делаем:
\begin{verbatim}
londiste.py /etc/skytools/db1-londiste.ini replay -d
\end{verbatim}
Таким образом запустятся слушатели очередей репликации, но, т.к. мы ещё не
указывали какие таблицы хотим реплицировать, они пока будут работать в холостую.
Убедимся что в логах нет ошибок (/var/log/db1-londistes.log).
\subsubsection{Добавляем реплицируемые таблицы}
Для каждой конфигурации указываем что будем реплицировать с мастера:
\begin{verbatim}
londiste.py /etc/skytools/db1-londiste.ini provider add --all
\end{verbatim}
и что со слейва:
\begin{verbatim}
londiste.py /etc/skytools/db1-londiste.ini subscriber add --all
\end{verbatim}
В данном примере я использую спец-параметр <<--all>>, который означает все таблицы,
но вместо него вы можете перечислить список конкретных таблиц, если не хотите
реплицировать все.
\subsubsection{Добавляем реплицируемые последовательности (sequence)}
Так же для всех конфигураций.
Для мастера:
\begin{verbatim}
londiste.py /etc/skytools/db1-londiste.ini provider add-seq --all
\end{verbatim}
Для слейва:
\begin{verbatim}
londiste.py /etc/skytools/db1-londiste.ini subscriber add-seq --all
\end{verbatim}
Точно также как и с таблицами можно указать конкретные последовательности вместо <<--all>>.
\subsubsection{Проверка}
Итак, всё что надо сделано. Теперь Londiste запустит так называемый bulk copy
процесс, который массово (с помощью COPY) зальёт присутствующие на момент
добавления таблиц данные на слейв, а затем перейдёт в состояние обычной репликации.
Мониторим логи на предмет ошибок:
\begin{verbatim}
less /var/log/db1-londiste.log
\end{verbatim}
Если всё хорошо, смотрим состояние репликации. Данные уже синхронизированы для
тех таблиц, где статус отображается как "ok".
\begin{verbatim}
londiste.py /etc/skytools/db1-londiste.ini subscriber tables
Table State
public.table1 ok
public.table2 ok
public.table3 in-copy
public.table4 -
public.table5 -
public.table6 -
...
\end{verbatim}
Для удобства представляю следующий трюк с уведомление в почту об окончании
первоначального копирования (мыло поменять на своё):
\begin{verbatim}
(
while [ $(
python londiste.py /etc/skytools/db1-londiste.ini subscriber tables |
tail -n+2 | awk '{print $2}' | grep -v ok | wc -l) -ne 0 ];
do sleep 60; done; echo '' | mail -s 'Replication done EOM' user@domain.com
) &
\end{verbatim}
\subsection{Общие задачи}
\subsubsection{Добавление всех таблиц мастера слейву}
Просто используя эту команду:
\begin{verbatim}
londiste.py <ini> provider tables | xargs londiste.py <ini> subscriber add
\end{verbatim}
\subsubsection{Проверка состояния слейвов}
Этот запрос на мастере дает некоторую информацию о каждой очереди и слейве.
\begin{verbatim}
SELECT queue_name, consumer_name, lag, last_seen
FROM pgq.get_consumer_info();
\end{verbatim}
<<lag>> столбец показывает отставание от мастера в синхронизации,
<<last\_seen>>~--- время последней запроса от слейва. Значение этого столбца не должно быть больше,
чем 60 секунд для конфигурации по умолчанию.
\subsubsection{Удаление очереди всех событий из мастера}
При работе с Londiste может потребоватся удалить все ваши настройки для того, чтобы начать все заново.
Для PGQ, чтобы остановить накопление данных, используйте следующие API:
\begin{verbatim}
SELECT pgq.unregister_consumer('queue_name', 'consumer_name');
\end{verbatim}
Или воспользуйтесь pgqadm.py:
\begin{verbatim}
pgqadm.py <ticker.ini> unregister queue_name consumer_name
\end{verbatim}
\subsubsection{Добавление столбца в таблицу}
Добавляем в следующей последовательности:
\begin{enumerate}
\item добавить поле на все слейвы
\item BEGIN; -- на мастере
\item добавить поле на мастере
\item SELECT londiste.provider\_refresh\_trigger('queue\_name', 'tablename');
\item COMMIT;
\end{enumerate}
\subsubsection{Удаление столбца из таблицу}
\begin{enumerate}
\item BEGIN; -- на мастере
\item удалить поле на мастере
\item SELECT londiste.provider\_refresh\_trigger('queue\_name', 'tablename');
\item COMMIT;
\item Проверить <<lag>>, когда londiste пройдет момент удаления поля
\item удалить поле на всех слейвах
\end{enumerate}
Хитрость тут в том, чтобы удалить поле на слейвах только тогда, когда больше нет событий в очереди на это поле.
\subsection{Устранение неисправностей}
\subsubsection{Londiste пожирает процессор и lag растет}
Это происходит, например, если во время сбоя админ забыл перезапустить ticker. Или когда вы сделали большой
UPDATE или DELETE в одной транзакции, но теперь что бы реализовать каждое собитие в этом запросе создаются
транзакции на слейвах \dots
Следующий запрос позволяет подсчитать, сколько событий пришло в pgq.subscription в колонках sub\_last\_tick и sub\_next\_tick.
\begin{verbatim}
SELECT count(*)
FROM pgq.event_1,
(SELECT tick_snapshot
FROM pgq.tick
WHERE tick_id BETWEEN 5715138 AND 5715139
) as t(snapshots)
WHERE txid_visible_in_snapshot(ev_txid, snapshots);
\end{verbatim}
В нашем случае, это было более чем 5 миллионов и 400 тысяч событий. Многовато. Чем больше событий
с базы данных требуется обработать Londiste, тем больше ему требуется памяти для этого. Мы можем сообщить
Londiste не загружать все события сразу. Достаточно добавить в INI конфиг ticker-а следующую настройку:
\begin{verbatim}
pgq_lazy_fetch = 500
\end{verbatim}
Теперь Londiste будет брать максимум 500 событий в один пакет запросов. Остальные попадут в следующие пакеты запросов.