جریان WALS PostgreSQL با از دست دادن داده های صفر در ذهن

pgrwl
گزارش های نوشتن را از یک سرور postgreSQL پخش کنید
🚀 درباره
-
این پروژه به عنوان یک خدمت می کند بسترهای تحقیق برای کشف جریان بایگانی WAL با هدف RPO = 0 در حین بهبودی
-
این در درجه اول برای استفاده در محیط های کانتینر طراحی شده است.
-
این ابزار تمام ویژگی های کلیدی را تکرار می کند
pg_receivewal
، از جمله اتصال مجدد خودکار در مورد از دست دادن اتصال ، پخش در پرونده های جزئی ، بررسی خطای گسترده و موارد دیگر. -
این ابزار به راحتی به عنوان یک باینری و ساده برای اشکال زدایی نصب می شود – فقط از ویرایشگر دلخواه خود و یک ظرف داکر خود استفاده کنید که PostgreSQL را اجرا می کند.
🔐 ویژگی ها
- ✅ جریان بایگانی WAL با شکاف های تکثیر
- ✅ ایمن
.partial
انتقال پرونده (هر پیام سرور “fsynced” است) - ✅ S3/SFTP Backends با فشرده سازی GZIP/ZSTD اختیاری + رمزگذاری AES-GCM
- ✅ سرور HTTP داخلی برای خدمت به WALS + معیارها و هشدار (برنامه ریزی شده)
- ✅ پیکربندی حداقل و ترکیب
- ✅ کاملاً قابل آزمایش با تست های ادغام مبتنی بر داکر است
🛠 استفاده
Receive
حالت
cat <<EOF >config.yml
main:
listen_port: 7070
directory: wals
receiver:
slot: pgrwl_v5
log:
level: trace
format: text
add_source: true
EOF
export PGHOST=localhost
export PGPORT=5432
export PGUSER=postgres
export PGPASSWORD=postgres
export PGRWL_MODE=receive
pgrwl -c config.yml
Serve
حالت
cat <<EOF >config.yml
main:
listen_port: 7070
directory: wals
log:
level: trace
format: text
add_source: true
EOF
export PGRWL_MODE=serve
pgrwl -c config.yml
⭐ همچنین مشاهده کنید: مثالها (بایگانی مرحله به مرحله و بازیابی) و K8S (تنظیم اساسی)
reference مرجع پیکربندی
پرونده پیکربندی در قالب JSON یا YML است (*.json ترجیح داده می شود).
این از متغیرهای متغیر محیط مانند پشتیبانی می کند ${PGRWL_SECRET_ACCESS_KEY}
بشر
main: # Required for both modes: 'receive"https://dev.to/"serve'
listen_port: 7070 # HTTP server port (used for management)
directory: "/var/lib/pgwal" # Base directory for storing WAL files
receiver: # Required for 'receive' mode
slot: replication_slot # Replication slot to use
no_loop: false # If true, do not loop on connection loss
uploader: # Optional (used in receive mode)
sync_interval: 10s # Interval for the upload worker to check for new files
max_concurrency: 4 # Maximum number of files to upload concurrently
log: # Optional
level: info # One of: trace / debug / info / warn / error
format: text # One of: text / json
add_source: true # Include file:line in log messages (for local development)
storage: # Optional
name: s3 # One of: s3 / sftp
compression: # Optional
algo: gzip # One of: gzip / zstd
encryption: # Optional
algo: aesgcm # One of: aes-256-gcm
pass: "${PGRWL_ENCRYPT_PASSWD}" # Encryption password (from env)
sftp: # Required section for 'sftp' storage
host: sftp.example.com # SFTP server hostname
port: 22 # SFTP server port
user: backupuser # SFTP username
pass: "${PGRWL_VM_PASSWORD}" # SFTP password (from env)
pkey_path: "/home/user/.ssh/id_rsa" # Path to SSH private key (optional)
pkey_pass: "${PGRWL_SSH_PKEY_PASS}" # Required if the private key is password-protected
s3: # Required section for 's3' storage
url: https://s3.example.com # S3-compatible endpoint URL
access_key_id: AKIAEXAMPLE # AWS access key ID
secret_access_key: "${PGRWL_AWS_SK}" # AWS secret access key (from env)
bucket: postgres-backups # Target S3 bucket name
region: us-east-1 # S3 region
use_path_style: true # Use path-style URLs for S3
disable_ssl: false # Disable SSL
🚀 نصب
نصب دستی
- آخرین باینری را برای پلتفرم خود از صفحه انتشار بارگیری کنید.
- باینری را در سیستم خود قرار دهید
PATH
(به عنوان مثال ،/usr/local/bin
).
اسکریپت نصب برای سیستم عامل مبتنی بر یونیکس (نیاز دارد: تار ، حلقه ، JQ):
(
set -euo pipefail
OS="$(uname | tr '[:upper:]' '[:lower:]')"
ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')"
TAG="$(curl -s https://api.github.com/repos/hashmap-kz/pgrwl/releases/latest | jq -r .tag_name)"
curl -L "https://github.com/hashmap-kz/pgrwl/releases/download/${TAG}/pgrwl_${TAG}_${OS}_${ARCH}.tar.gz" |
tar -xzf - -C /usr/local/bin && \
chmod +x /usr/local/bin/pgrwl
)
🗃 استفاده در فرآیند تهیه نسخه پشتیبان
فرآیند کامل ممکن است مانند این باشد (یک مثال معمولی ، خشن و ساده):
- شما یک کار کرون دارید که انجام می دهد پشتیبان گیری از پایه از خوشه شما هر سه روز است.
- شما فرار می کنید
pgrwl
به عنوان یک واحد SystemD یا یک غلاف Kubernetes (بسته به زیرساخت شما). - شما یک کارگر نگهدارنده پیکربندی شده دارید که پرونده های WAL را از سه روز قدیمی تر می کند.
- با این تنظیم ، شما می توانید در سه روز گذشته خوشه خود را – در صورت تصادف – به هر ثانیه بازگردانید.
🧱 معماری
یادداشت های طراحی
pgrwl
برای استفاده از سیستم فایل محلی منحصراً طراحی شده است. این یک انتخاب عمدی است ، زیرا – همانطور که قبلاً ذکر شد – ما باید پس از نوشتن هر پیام به دیسک ، به FSYNC اعتماد کنیم.
این تضمین می کند که *.partial
پرونده ها همیشه حاوی بخش های WAL کاملاً معتبر هستند و باعث می شوند آنها در مرحله بازیابی استفاده کنند (پس از حذف ساده *.partial
پسوند)
pgrwl
از فشرده سازی و رمزگذاری به عنوان ویژگی های اختیاری برای فایلهای تکمیل شده WAL (هنگام بارگذاری در ذخیره سازی از راه دور) پشتیبانی می کند.
با این حال ، جریان *.partial
پرونده ها به هر مکانی غیر از سیستم فایل محلی می توانند موضوعات غیرقابل پیش بینی بی شماری را معرفی کنند.
به طور خلاصه: PostgreSQL منتظر است تا ماکت را تأیید کند ، بنابراین ما نمی توانیم در چنین مسیرهای مهم به سیستم های خارجی وابسته باشیم.
💾 یادداشت ها fsync
(از آنجا که ابزار در حالت همزمان کار می کند تنها):
- پس از نوشتن هر بخش WAL ،
fsync
برای اطمینان از دوام در پرونده WAL در حال حاضر باز انجام می شود. - در
fsync
هنگامی که یک بخش WAL به پایان رسید و*.partial
پرونده به فرم نهایی خود تغییر نام داده می شود. - در
fsync
هنگامی که یک پیام نگهدارنده از سرور دریافت می شود ، شروع می شودreply_requested
مجموعه گزینه - علاوه بر این ،
fsync
هر زمان که خطایی در طول حلقه دریافت کپی رخ دهد ، خوانده می شود.
🔁 یادداشت ها archive_command
وت archive_timeout
تفاوت معنی داری بین استفاده وجود دارد archive_command
و بایگانی پرونده های WAL از طریق تکثیر جریان
پروتکل
در archive_command
فقط پس از اتمام پرونده WAL به طور کامل انجام می شود – معمولاً هنگام رسیدن به 16 MIB (اندازه قطعه پیش فرض). این بدان معنی است که در یک سناریوی تصادف ، می توانید حداکثر 16 MIB داده را از دست دهید.
با تنظیم پایین می توانید این کار را کاهش دهید archive_timeout
(به عنوان مثال ، 1 دقیقه) ، اما حتی در آن زمان ، در یک سناریوی بدترین حالت ،
شما خطر از دست دادن حداکثر 1 دقیقه داده را دارید.
همچنین ، توجه به این نکته حائز اهمیت است که PostgreSQL پرونده های WAL را به پیکربندی می کند wal_segment_size
، بنابراین آنها هستند
ایجاد شده با اندازه کامل بدون در نظر گرفتن میزان داده ها. (نقل قول از مستندات:
بنابراین عاقلانه است که خیلی کوتاه تنظیم شود archive_timeout
– این ذخیره آرشیو شما را نفخ خواهد کرد.).
در مقابل ، جریان بایگانی WAL – هنگامی که با شکاف های تکثیر و synchronous_standby_names
پارامتر – حسادت هایی که سیستم را می توان به آخرین معامله متعهد بازگرداند.
این رویکرد از دست دادن داده های صفر واقعی را فراهم می کند (RPO = 0) ، آن را برای الزامات با دوام بالا ایده آل کنید.
👷 یادداشت های توسعه دهنده
🧪 تست ادغام:
در اینجا و مثال a طلایی اساسی آزمون
این تأیید می کند که ما می توانیم پس از تصادف ناگهانی سیستم ، به آخرین معامله متعهد بازگردیم.
همچنین بررسی می کند که پرونده های WAL تولید شده با بایت برای بایت یکسان با موارد تولید شده توسط pg_receivewal
بشر
مراحل آزمون:
- شروع و راه اندازی یک خوشه postgresql
- گیرنده های WAL را اجرا کنید (
pgrwl
وتpg_receivewal
) - پشتیبان گیری پایه ایجاد کنید
- یک جدول ایجاد کنید و هر ثانیه (در پس زمینه) جدول زمانی فعلی را وارد کنید
- pgbench را اجرا کنید تا پایگاه داده را با 1 میلیون ردیف جمع کنید
- داده های اضافی تولید کنید (512 پوند MIB)
- به طور همزمان 100 جدول با 10000 ردیف ایجاد کنید.
- کار درج اسکریپت را خاتمه دهید
- pg_dumpall را اجرا کنید و خروجی را به عنوان SQL ساده ذخیره کنید
- تمام فرآیندهای postgreSQL را خاتمه داده و حذف کنید
PGDATA
دایرکتوری (خاتمه نیرو و غیر طبیعی است) - بازگرداندن
PGDATA
از پشتیبان گیری پایه ، Recovery.Signal را اضافه کنید و تنظیم کنید Restore_command - تغییر نام همه
*.partial
پرونده های وال در دایرکتوری های بایگانی WAL - خوشه PostgreSQL را شروع کنید (خوشه باید به آخرین معامله متعهد بهبود یابد)
- بعد از آماده شدن خوشه ، pg_dumpall را اجرا کنید
- نتایج pg_dumpall (قبل و بعد) را متفاوت کنید
- سیاهههای مربوط به اسکریپت را بررسی کنید و تأیید کنید که جدول شامل آخرین ردیف درج شده است
- دایرکتوری های WAL را مقایسه کنید (نام های پرونده و محتویات باید 100 ٪ مطابقت داشته باشند)
- دایرکتوری های WAL را پاک کنید و مجدداً بایگانی های WAL را در یک جدول زمانی جدید انجام دهید (پاکسازی ضروری است زیرا ما گیرنده ها را با گزینه-بدون حلقه اجرا می کنیم)
- دوباره دایرکتوری های WAL را مقایسه کنید
برای کمک یا تأیید پروژه به صورت محلی ، موارد زیر make
اهداف باید همه تصویب شوند:
# Compile the project
make build
# Run linter (should pass without errors)
make lint
# Run unit tests (should all pass)
make test
# Run integration tests (slow, but critical)
# Requires Docker and Docker Compose to be installed
make test-integ-scripts
# Run GoReleaser builds locally
make snapshot
✅ همه اهداف باید قبل از ارسال تغییرات یا باز کردن روابط عمومی با موفقیت تکمیل شوند.
ساختار کد منبع
internal/xlog/pg_receivewal.go
→ Entry point for WAL receiving logic.
Based on the logic found in PostgreSQL:
https://github.com/postgres/postgres/blob/master/src/bin/pg_basebackup/pg_receivewal.c
internal/xlog/receivelog.go
→ Core streaming loop and replication logic.
Based on the logic found in PostgreSQL:
https://github.com/postgres/postgres/blob/master/src/bin/pg_basebackup/receivelog.c
internal/xlog/xlog_internal.go
→ Helpers for LSN math, WAL file naming, segment calculations.
Based on the logic found in PostgreSQL:
https://github.com/postgres/postgres/blob/master/src/include/access/xlog_internal.h
internal/xlog/walfile.go
→ Manages WAL file descriptors: open, write, close, sync.
internal/xlog/streamutil.go
→ Utilities for querying server parameters (e.g. wal_segment_size),
replication slot info, and streaming setup.
internal/xlog/fsync/
→ Optimized wrappers for safe and efficient `fsync` system calls.
📐 حلقه اصلی
⏮ پیوندها
✅ tl ؛ دکتر
اگر در حال ساخت خطوط لوله پشتیبان PostgresQL قابل اعتماد هستید و می خواهید جریانبا دواموت کنترل کننده، بده pgrwl
یک امتحان
💬 سوال یا بازخورد؟ یک شماره github را رها کنید یا در اینجا نظر دهید!
👉 منبع را بررسی کنید
🔖 تحت من مجوز