برنامه نویسی

جریان 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
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید


🚀 نصب

نصب دستی

  1. آخرین باینری را برای پلتفرم خود از صفحه انتشار بارگیری کنید.
  2. باینری را در سیستم خود قرار دهید 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 را رها کنید یا در اینجا نظر دهید!

👉 منبع را بررسی کنید

🔖 تحت من مجوز

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا