WAL-G: нусхабардорӣ ва барқарорсозии DBMS PostgreSQL

Кайҳо боз маълум аст, ки нусхабардорӣ ба партовҳои SQL (бо истифода аз pg_dump ё pg_dumpall) фикри хуб нест. Барои нусхабардории DBMS PostgreSQL, беҳтар аст, ки фармонро истифода баред pg_basebackup, ки нусхаи бинарии гузоришҳои WAL-ро месозад. Аммо вақте ки шумо ба омӯзиши тамоми раванди эҷоди нусхабардорӣ ва барқарорсозӣ шурӯъ мекунед, шумо хоҳед фаҳмид, ки шумо бояд ҳадди аққал як ду велосипедҳои сечархаро нависед, то ин кор кунад ва ҳам дар боло ва ҳам дар поён шуморо дард надиҳад. Барои сабук кардани ранҷу азоб, WAL-G таҳия карда шуд.

ВАЛ-Г асбобест, ки дар Go барои нусхабардорӣ ва барқарорсозии пойгоҳи додаҳои PostgreSQL навишта шудааст (ва ба наздикӣ MySQL/MariaDB, MongoDB ва FoundationDB). Он кор бо нигаҳдории Amazon S3 (ва аналогҳо, масалан, Yandex Object Storage), инчунин Google Cloud Storage, Azure Storage, Swift Object Storage ва танҳо бо системаи файлиро дастгирӣ мекунад. Тамоми танзимот ба қадамҳои оддӣ рост меояд, аммо аз сабаби он, ки мақолаҳо дар бораи он дар Интернет парокандаанд, дастури мукаммали тарзи кор вуҷуд надорад, ки тамоми қадамҳоро аз аввал то ба охир дар бар гирад (якчанд паёмҳо дар Habre, вале дар он чо бисьёр нуктахо аз даст дода шудаанд).

WAL-G: нусхабардорӣ ва барқарорсозии DBMS PostgreSQL

Ин мақола пеш аз ҳама барои ба низом даровардани донишҳои ман навишта шудааст. Ман DBA нестам ва ман метавонам худро дар ҷое бо забони оддӣ баён кунам, аз ин рӯ ҳама гуна ислоҳҳо хуш омадед!

Алоҳида, ман қайд мекунам, ки ҳама чиз дар зер мувофиқ аст ва барои PostgreSQL 12.3 дар Ubuntu 18.04 санҷида шудааст, ҳама фармонҳо бояд ҳамчун корбари имтиёзнок иҷро карда шаванд.

параметр

Ҳангоми навиштани ин мақола, версияи устувори WAL-G аст v0.2.15 (марти 2020). Ин аст он чизе ки мо истифода хоҳем кард (аммо агар шумо хоҳед, ки онро худатон аз филиали асосӣ созед, пас анбори github ҳама дастурҳоро барои ин дорад.). Барои зеркашӣ ва насб шумо бояд амалҳои зеринро иҷро кунед:

#!/bin/bash

curl -L "https://github.com/wal-g/wal-g/releases/download/v0.2.15/wal-g.linux-amd64.tar.gz" -o "wal-g.linux-amd64.tar.gz"
tar -xzf wal-g.linux-amd64.tar.gz
mv wal-g /usr/local/bin/

Пас аз ин, шумо бояд аввал WAL-G-ро танзим кунед ва баъд худи PostgreSQL.

Насб кардани WAL-G

Барои мисоли нигоҳдории нусхаҳои эҳтиётӣ, Amazon S3 истифода мешавад (зеро он ба серверҳои ман наздиктар аст ва истифодаи он хеле арзон аст). Барои кор бо он ба шумо "сатил s3" ва калидҳои дастрасӣ лозим аст.

Ҳама мақолаҳои қаблӣ дар бораи WAL-G конфигуратсияро бо истифода аз тағирёбандаҳои муҳити зист истифода бурданд, аммо бо ин нашр танзимотро метавон дар файли .walg.json дар феҳристи хонагии корбари postgres. Барои сохтани он, скрипти зерини bash -ро иҷро кунед:

#!/bin/bash

cat > /var/lib/postgresql/.walg.json << EOF
{
    "WALG_S3_PREFIX": "s3://your_bucket/path",
    "AWS_ACCESS_KEY_ID": "key_id",
    "AWS_SECRET_ACCESS_KEY": "secret_key",
    "WALG_COMPRESSION_METHOD": "brotli",
    "WALG_DELTA_MAX_STEPS": "5",
    "PGDATA": "/var/lib/postgresql/12/main",
    "PGHOST": "/var/run/postgresql/.s.PGSQL.5432"
}
EOF
# обязательно меняем владельца файла:
chown postgres: /var/lib/postgresql/.walg.json

Биёед ман каме дар бораи ҳамаи параметрҳоро шарҳ диҳам:

  • WALG_S3_PREFIX - роҳ ба сатили S3-и шумо, ки дар он нусхаҳои эҳтиётӣ бор карда мешаванд (шумо метавонед ба реша ё ҷузвдон);
  • AWS_ACCESS_KEY_ID - калиди дастрасӣ дар S3 (дар сурати барқароршавӣ дар сервери санҷишӣ, ин калидҳо бояд Сиёсати ReadOnOnly дошта бошанд! Ин ба таври муфассал дар фасли барқарорсозӣ тавсиф шудааст.);
  • AWS_SECRET_ACCESS_KEY – калиди махфӣ дар нигаҳдории S3;
  • WALG_COMPRESSION_METHOD – усули фишурдасозӣ, беҳтар аст, ки Бротлиро истифода баред (зеро ин миёнаи тиллоӣ байни андозаи ниҳоӣ ва суръати фишурда/декомпрессия аст);
  • WALG_DELTA_MAX_STEPS – шумораи «дельтаҳо» пеш аз сохтани нусхаи пурра (онҳо вақт ва андозаи маълумоти зеркашидаро сарфа мекунанд, аммо метавонанд раванди барқароркуниро каме суст кунанд, аз ин рӯ истифодаи арзишҳои калон тавсия дода намешавад);
  • PGDATA - роҳ ба директория бо маълумоти базаи шумо (шумо метавонед тавассути иҷро кардани фармон пайдо кунед pg_lsclusters);
  • PGHOST – пайваст шудан ба пойгоҳи додаҳо, бо нусхаи эҳтиётии маҳаллӣ, беҳтар аст, ки онро тавассути розеткаи unix иҷро кунед, тавре ки дар ин мисол аст.

Дигар параметрҳоро дар ҳуҷҷатҳо пайдо кардан мумкин аст: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

Танзими PostgreSQL

Барои он ки бойгонӣ дар дохили пойгоҳи додаҳо сабтҳои WAL-ро ба абр бор кунад ва онҳоро аз онҳо барқарор кунад (агар лозим бошад), шумо бояд дар файли конфигуратсия якчанд параметрҳоро муқаррар кунед /etc/postgresql/12/main/postgresql.conf. Танҳо барои шурӯъкунандагон шумо бояд боварӣ ҳосил кунедки ҳеҷ яке аз танзимоти дар поён овардашуда ба арзишҳои дигар муқаррар карда нашудаанд, то вақте ки конфигуратсия аз нав бор карда мешавад, DBMS аз кор набарояд. Шумо метавонед ин параметрҳоро бо истифода аз:

#!/bin/bash

echo "wal_level=replica" >> /etc/postgresql/12/main/postgresql.conf
echo "archive_mode=on" >> /etc/postgresql/12/main/postgresql.conf
echo "archive_command='/usr/local/bin/wal-g wal-push "%p" >> /var/log/postgresql/archive_command.log 2>&1' " >> /etc/postgresql/12/main/postgresql.conf
echo “archive_timeout=60” >> /etc/postgresql/12/main/postgresql.conf
echo "restore_command='/usr/local/bin/wal-g wal-fetch "%f" "%p" >> /var/log/postgresql/restore_command.log 2>&1' " >> /etc/postgresql/12/main/postgresql.conf

# перезагружаем конфиг через отправку SIGHUP сигнала всем процессам БД
killall -s HUP postgres

Тавсифи параметрҳои муқарраршуда:

  • сатҳи баланд – чӣ қадар маълумотро дар logs WAL нависед, “реплика” – ҳама чизро нависед;
  • архив_режим – имкони зеркашии гузоришҳои WAL бо истифода аз фармон аз параметр архив_фармон;
  • архив_фармон – фармон барои бойгонӣ кардани журнали анҷомёфтаи WAL;
  • archive_timeout – бойгонии гузоришҳо танҳо пас аз анҷоми он анҷом дода мешавад, аммо агар сервери шумо ба пойгоҳи додаҳо маълумоти камро тағир диҳад/илова кунад, дар ин ҷо дар тӯли сонияҳо маҳдудият муқаррар кардан дуруст аст, ки пас аз он фармони бойгонӣ маҷбурӣ даъват карда мешавад (Ман дар ҳар сония ба база бо шиддат менависам, бинобар ин ман қарор додам, ки ин параметрро дар истеҳсолот муқаррар накунам);
  • барқарор_фармон – фармони барқарор кардани сабти WAL аз нусха истифода мешавад, агар дар “захираи пурра” (захираи асосӣ) тағйироти охирин дар пойгоҳи додаҳо мавҷуд набошад.

Шумо метавонед дар бораи ҳамаи ин параметрҳо дар тарҷумаи ҳуҷҷатҳои расмӣ маълумоти бештар гиред: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Муқаррар кардани ҷадвали эҳтиётӣ

Новобаста аз он ки касе гӯяд, роҳи аз ҳама мувофиқ барои идора кардани он cron аст. Ин аст он чизе ки мо барои сохтани нусхаҳои эҳтиётӣ танзим мекунем. Биёед бо фармони эҷоди нусхаи пурра оғоз кунем: дар wal-g ин далели оғозёбӣ аст нусхабардорӣ-пуш. Аммо аввал, беҳтар аст, ки ин фармонро аз корбари postgres дастӣ иҷро кунед, то боварӣ ҳосил кунед, ки ҳама чиз хуб аст (ва хатогиҳои дастрасӣ вуҷуд надорад):

#!/bin/bash

su - postgres -c '/usr/local/bin/wal-g backup-push /var/lib/postgresql/12/main'

Далелҳои оғозёбӣ роҳро ба феҳристи додаҳо нишон медиҳанд - Ман ба шумо хотиррасон мекунам, ки шумо метавонед онро тавассути иҷро пайдо кунед pg_lsclusters.

Агар ҳама чиз бе хатогӣ сурат гирад ва маълумот ба нигаҳдории S3 бор карда шуда бошад, пас шумо метавонед оғозкунии давриро дар crontab танзим кунед:

#!/bin/bash

echo "15 4 * * *    /usr/local/bin/wal-g backup-push /var/lib/postgresql/12/main >> /var/log/postgresql/walg_backup.log 2>&1" >> /var/spool/cron/crontabs/postgres
# задаем владельца и выставляем правильные права файлу
chown postgres: /var/spool/cron/crontabs/postgres
chmod 600 /var/spool/cron/crontabs/postgres

Дар ин мисол, раванди нусхабардорӣ ҳар рӯз соати 4:15 оғоз мешавад.

Нест кардани нусхаҳои кӯҳна

Эҳтимол, ба шумо лозим нест, ки комилан нусхаҳои эҳтиётии давраи мезозойро нигоҳ доред, аз ин рӯ ба таври даврӣ "тоза кардани" нигаҳдории шумо муфид хоҳад буд (ҳам "нусхаҳои пурра" ва ҳам гузоришҳои WAL). Мо инро ҳама тавассути вазифаи cron иҷро мекунем:

#!/bin/bash

echo "30 6 * * *    /usr/local/bin/wal-g delete before FIND_FULL $(date -d '-10 days' '+%FT%TZ') --confirm >> /var/log/postgresql/walg_delete.log 2>&1" >> /var/spool/cron/crontabs/postgres
# ещё раз задаем владельца и выставляем правильные права файлу (хоть это обычно это и не нужно повторно делать)
chown postgres: /var/spool/cron/crontabs/postgres
chmod 600 /var/spool/cron/crontabs/postgres

Cron ин вазифаро ҳар рӯз соати 6:30 иҷро мекунад ва ҳама чизро (нусхаҳои пурра, делтаҳо ва WAL) нест мекунад, ба истиснои нусхаҳо дар 10 рӯзи охир, аммо ҳадди аққал як нусхаи эҳтиётӣ боқӣ мемонад. ба санаи муайян, то ки ягон нуқтаи после санаҳо ба PITR дохил карда шуданд.

Барқароркунӣ аз нусхабардорӣ

Ба касе пӯшида нест, ки калиди базаи солим ин барқарорсозии давравӣ ва тафтиши якпорчагии маълумот дар дохили он мебошад. Ман ба шумо мегӯям, ки чӣ тавр бо истифода аз WAL-G дар ин бахш барқарор карда шавад ва мо дар бораи чекҳо баъдтар сӯҳбат хоҳем кард.

Бояд алоҳида қайд кард ки барои барқарор кардан дар муҳити озмоишӣ (ҳар чизе, ки истеҳсол нест) ба шумо лозим аст, ки ҳисоби танҳо барои хонданро дар S3 истифода баред, то тасодуфан нусхаҳои эҳтиётиро аз нав нанависед. Дар мавриди WAL-G, шумо бояд ҳуқуқҳои зеринро барои корбари S3 дар Сиёсати гурӯҳ муқаррар кунед (Таъсири: Иҷозат диҳед): s3: GetObject, s3: ListBucket, s3:GetBucketLocation. Ва, албатта, фаромӯш накунед, ки танзим кунед archive_mode=хомӯш дар файли танзимот postgresql.conf, ба тавре ки базаи санҷиши шумо намехоҳад оромона нусхабардорӣ карда шавад.

Барқароркунӣ бо ҳаракати ночизи даст анҷом дода мешавад нест кардани ҳама маълумоти PostgreSQL (аз ҷумла корбарон), аз ин рӯ, ҳангоми иҷро кардани фармонҳои зерин хеле эҳтиёт шавед.

#!/bin/bash

# если есть балансировщик подключений (например, pgbouncer), то вначале отключаем его, чтобы он не нарыгал ошибок в лог
service pgbouncer stop
# если есть демон, который перезапускает упавшие процессы (например, monit), то останавливаем в нём процесс мониторинга базы (у меня это pgsql12)
monit stop pgsql12
# или останавливаем мониторинг полностью
service monit stop
# останавливаем саму базу данных
service postgresql stop
# удаляем все данные из текущей базы (!!!); лучше предварительно сделать их копию, если есть свободное место на диске
rm -rf /var/lib/postgresql/12/main
# скачиваем резервную копию и разархивируем её
su - postgres -c '/usr/local/bin/wal-g backup-fetch /var/lib/postgresql/12/main LATEST'
# помещаем рядом с базой специальный файл-сигнал для восстановления (см. https://postgrespro.ru/docs/postgresql/12/runtime-config-wal#RUNTIME-CONFIG-WAL-ARCHIVE-RECOVERY ), он обязательно должен быть создан от пользователя postgres
su - postgres -c 'touch /var/lib/postgresql/12/main/recovery.signal'
# запускаем базу данных, чтобы она инициировала процесс восстановления
service postgresql start

Барои онҳое, ки мехоҳанд раванди барқароркуниро тафтиш кунанд, дар зер як пораи хурди ҷодуи bash омода карда шудааст, то дар сурати мушкилот дар барқарорсозӣ скрипт бо рамзи баромади ғайри сифр шикаст хӯрад. Дар ин мисол, 120 санҷиш бо муддати 5 сония (ҳамагӣ 10 дақиқа барои барқарорсозӣ) барои муайян кардани нест кардани файли сигнал анҷом дода мешавад (ин маънои онро дорад, ки барқарорсозӣ муваффақ аст):

#!/bin/bash

CHECK_RECOVERY_SIGNAL_ITER=0
while [ ${CHECK_RECOVERY_SIGNAL_ITER} -le 120 ]
do
    if [ ! -f "/var/lib/postgresql/12/main/recovery.signal" ]
    then
        echo "recovery.signal removed"
        break
    fi
    sleep 5
    ((CHECK_RECOVERY_SIGNAL_ITER+1))
done

# если после всех проверок файл всё равно существует, то падаем с ошибкой
if [ -f "/var/lib/postgresql/12/main/recovery.signal" ]
then
    echo "recovery.signal still exists!"
    exit 17
fi

Пас аз барқарорсозии бомуваффақият, фаромӯш накунед, ки ҳамаи равандҳоро дубора оғоз кунед (pgbouncer/monit ва ғайра).

Санҷиши маълумот пас аз барқароршавӣ

Пас аз барқарорсозӣ тамомияти махзани маълумотро тафтиш кардан ҳатмист, то вазъият бо нусхаи шикаста/каҷшуда ба вуҷуд наояд. Ва беҳтар аст, ки ин корро бо ҳар як бойгонии сохташуда анҷом диҳед, аммо дар куҷо ва чӣ гуна танҳо аз тасаввуроти шумо вобаста аст (шумо метавонед серверҳои инфиродӣ дар як соат афзоиш диҳед ё дар CI тафтиш кунед). Аммо ҳадди аққал маълумот ва индексҳоро дар базаи маълумот тафтиш кардан лозим аст.

Барои санҷидани маълумот, онро тавассути партов иҷро кардан кифоя аст, аммо беҳтар аст, ки ҳангоми эҷоди пойгоҳи додаҳо шумо ҳисобҳои санҷишро фаъол созед (маблағи санҷиши маълумот):

#!/bin/bash

if ! su - postgres -c 'pg_dumpall > /dev/null'
then
    echo 'pg_dumpall failed'
    exit 125
fi

Барои санҷидани индексҳо - вуҷуд дорад модули amcheck, биёед дархости sql-ро барои он гирем Санҷишҳои WAL-G ва дар атрофи он каме мантиқ бунёд кунед:

#!/bin/bash

# добавляем sql-запрос для проверки в файл во временной директории
cat > /tmp/amcheck.sql << EOF
CREATE EXTENSION IF NOT EXISTS amcheck;
SELECT bt_index_check(c.oid), c.relname, c.relpages
FROM pg_index i
JOIN pg_opclass op ON i.indclass[0] = op.oid
JOIN pg_am am ON op.opcmethod = am.oid
JOIN pg_class c ON i.indexrelid = c.oid
JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE am.amname = 'btree'
AND c.relpersistence != 't'
AND i.indisready AND i.indisvalid;
EOF
chown postgres: /tmp/amcheck.sql

# добавляем скрипт для запуска проверок всех доступных баз в кластере
# (обратите внимание что переменные и запуск команд – экранированы)
cat > /tmp/run_amcheck.sh << EOF
for DBNAME in $(su - postgres -c 'psql -q -A -t -c "SELECT datname FROM pg_database WHERE datistemplate = false;" ')
do
    echo "Database: ${DBNAME}"
    su - postgres -c "psql -f /tmp/amcheck.sql -v 'ON_ERROR_STOP=1' ${DBNAME}" && EXIT_STATUS=$? || EXIT_STATUS=$?
    if [ "${EXIT_STATUS}" -ne 0 ]
    then
        echo "amcheck failed on DB: ${DBNAME}"
        exit 125
    fi
done
EOF
chmod +x /tmp/run_amcheck.sh

# запускаем скрипт
/tmp/run_amcheck.sh > /tmp/amcheck.log

# для проверки что всё прошло успешно можно проверить exit code или grep’нуть ошибку
if grep 'amcheck failed' "/tmp/amcheck.log"
then
    echo 'amcheck failed: '
    cat /tmp/amcheck.log
    exit 125
fi

Барои чамъбаст кардан

Ман мехоҳам ба Андрей Бородин барои кӯмакаш дар омода кардани нашрия изҳори сипос кунам ва барои саҳмаш дар рушди WAL-G!

Ин ёддоштро ба охир мерасонад. Ман умедворам, ки ман тавонистам осонии насбкунӣ ва потенсиали бузурги истифодаи ин асбобро дар ширкати шумо расонам. Ман дар бораи WAL-G бисёр шунидам, аммо ҳеҷ гоҳ барои нишастан ва фаҳмидани он вақт надоштам. Ва пас аз он ки ман онро дар хона амалӣ кардам, ин мақола аз ман берун омад.

Алоҳида, бояд қайд кард, ки WAL-G инчунин метавонад бо DBMS зерин кор кунад:

Манбаъ: will.com

Илова Эзоҳ