بلاگ/همگام‌سازی و پشتیبان‌گیری افزایشی فایل بین سرورها با rsync
به‌روز شده

همگام‌سازی و پشتیبان‌گیری افزایشی فایل بین سرورها با rsync

1405/08/063 بازدید
همگام‌سازی و پشتیبان‌گیری افزایشی فایل بین سرورها با rsync

همگام‌سازی و پشتیبان‌گیری افزایشی فایل بین سرورها با rsync

اگر چند گیگ فایل روی یک سرور دارید و هر شب باید نسخه‌ای از آن را جایی دیگر نگه دارید، کپی کامل با scp یا tar هر بار وقت و پهنای باند زیادی می‌گیرد. rsync فقط تفاوت فایل‌ها را منتقل می‌کند، برای همین پشتیبان‌گیری با rsync برای این کار دقیقا ساخته شده است.

rsync چیست و چرا برای بکاپ افزایشی مناسب است

rsync یک ابزار خط فرمان لینوکس برای کپی و همگام‌سازی فایل‌ها است، هم روی یک سرور و هم بین دو سرور از راه SSH. نقطهٔ قوت آن الگوریتم delta است: قبل از انتقال، rsync بلوک‌های فایل مبدا و مقصد را مقایسه می‌کند و فقط بخش‌هایی را می‌فرستد که تغییر کرده‌اند.

این یعنی اگر یک فایل لاگ 2 گیگابایتی فقط چند مگابایت آخرش عوض شده باشد، rsync کل 2 گیگ را دوباره نمی‌فرستد. دفعهٔ دوم که دستور را اجرا می‌کنید، فقط تغییرات منتقل می‌شوند؛ به همین دلیل به آن بکاپ افزایشی می‌گویند، نه این‌که هر بار یک کپی کامل جدید بسازد.

در مقایسه، scp و cp هر بار کل فایل را کپی می‌کنند، حتی اگر یک بایت تغییر کرده باشد. برای چند فایل کوچک فرقی نمی‌کند، اما برای دایرکتوری چند ده گیگابایتی بین دو سرور، همین تفاوت باعث می‌شود بکاپ شبانه چند دقیقه طول بکشد به‌جای چند ساعت.

الگوریتم دلتای rsync: سرور مبدا فقط بلوک‌های تغییرکرده را به سرور مقصد منتقل می‌کند

قبل از شروع: دسترسی SSH بدون رمز بین دو سرور

برای این‌که دستور rsync داخل cron بدون وقفه اجرا شود، سرور مبدا باید بتواند بدون وارد کردن رمز به سرور مقصد وصل شود. کلید SSH برای این کار کافی است.

# روی سرور مبدا (جایی که بکاپ از آن اجرا می‌شود)
ssh-keygen -t ed25519 -f ~/.ssh/rsync_backup -N ""

# کپی کلید عمومی به سرور مقصد
ssh-copy-id -i ~/.ssh/rsync_backup.pub user@backup-server

بعد از این مرحله، اتصال را یک بار تست کنید:

ssh -i ~/.ssh/rsync_backup user@backup-server "echo connected"

اگر پیام connected را بدون پرسیدن رمز دیدید، کلید درست کار می‌کند و می‌توانید به سراغ دستور اصلی rsync بروید.

دستور پایه برای همگام‌سازی فایل بین دو سرور

ساده‌ترین شکل دستور این است:

rsync -avz -e "ssh -i ~/.ssh/rsync_backup" /var/www/mysite/ user@backup-server:/backup/mysite/

فلگ‌هایی که باید بشناسید

  • -a حالت archive است: زیرپوشه‌ها، مجوزها، مالکیت فایل و زمان آخرین تغییر را حفظ می‌کند. بدون این فلگ، rsync فقط محتوای فایل را کپی می‌کند و متادیتا از بین می‌رود.
  • -v خروجی را نمایش می‌دهد تا بفهمید دقیقا چه چیزی منتقل شده.
  • -z داده را قبل از انتقال فشرده می‌کند؛ روی لینک‌های اینترنتی کندتر فرق واقعی ایجاد می‌کند، روی شبکهٔ داخلی دیتاسنتر معمولا لازم نیست.
  • اسلش انتهای مسیر مبدا (mysite/) مهم است: یعنی محتوای پوشه را بریز توی مقصد، نه این‌که خود پوشه mysite را یک پوشه جدید داخل مقصد بسازد.

اگر می‌خواهید مقصد دقیقا مثل مبدا بماند و فایل‌هایی که از مبدا حذف شده‌اند هم از مقصد پاک شوند، فلگ --delete را اضافه کنید:

rsync -avz --delete -e "ssh -i ~/.ssh/rsync_backup" /var/www/mysite/ user@backup-server:/backup/mysite/

این فلگ را با احتیاط استفاده کنید. اگر مسیر مبدا را اشتباه بدهید یا یک مونت‌پوینت موقتا خالی باشد، --delete همان خالی‌بودن را روی مقصد هم اعمال می‌کند و بکاپ شما را پاک می‌کند، نه این‌که آن را به‌روز کند. قبل از اجرای واقعی، یک بار با --dry-run تست بگیرید تا لیست تغییرات را بدون اجرای واقعی ببینید.

بکاپ افزایشی واقعی با اسنپ‌شات و link-dest

دستور بالا همیشه فقط یک نسخه از مقصد را نگه می‌دارد. اگر فایلی امروز خراب شود و فردا همان خرابی همگام‌سازی شود، نسخهٔ سالم دیروز هم از بین رفته. برای داشتن چند نسخهٔ تاریخی، rsync فلگ --link-dest دارد که با hard link کار می‌کند.

ایدهٔ کار این‌طور است: هر اجرای بکاپ یک پوشهٔ جدید با تاریخ آن روز می‌سازد. فایل‌هایی که نسبت به آخرین بکاپ تغییر نکرده‌اند، به‌جای کپی دوباره، فقط با hard link به همان فایل قبلی اشاره می‌کنند. فایل‌هایی که تغییر کرده‌اند، از نو کپی می‌شوند. نتیجه این است که هر پوشهٔ تاریخ یک اسنپ‌شات کامل به نظر می‌رسد، اما فضای دیسک فقط برای تفاوت‌ها مصرف می‌شود.

DATE=$(date +%F)
rsync -avz --delete \
  --link-dest=/backup/mysite/latest \
  -e "ssh -i ~/.ssh/rsync_backup" \
  /var/www/mysite/ \
  user@backup-server:/backup/mysite/$DATE/

ssh -i ~/.ssh/rsync_backup user@backup-server \
  "ln -sfn /backup/mysite/$DATE /backup/mysite/latest"

لینک نمادین latest همیشه به آخرین اسنپ‌شات اشاره می‌کند و بار بعد به --link-dest معرفی می‌شود تا rsync بداند با کدام نسخه مقایسه کند.

مقایسه دو روش

rsync ساده (یک نسخه)rsync + link-dest (چند اسنپ‌شات)
فضای دیسک مصرفیفقط اندازهٔ یک نسخهاندازهٔ یک نسخه + فقط تفاوت هر روز
امکان برگشت به نسخهٔ قدیمی‌ترنداردهر پوشهٔ تاریخ یک نسخهٔ کامل است
ریسک --deleteفایل حذف‌شده برای همیشه از بکاپ هم می‌رودفایل در اسنپ‌شات‌های قبلی باقی می‌ماند
پیچیدگی تنظیمیک خط دستورنیاز به اسکریپت کوچک برای تاریخ و لینک latest
مناسب برایهمگام‌سازی زنده بین دو سرور فعالبکاپ شبانه که باید چند روز قابل بازیابی باشد

برای همگام‌سازی زندهٔ دو سرور (مثل یک سرور اصلی و یک replica) روش ساده کافی است. برای بکاپ شبانه که ممکن است لازم باشد به نسخهٔ سه روز پیش برگردید، link-dest انتخاب درست‌تری است.

زمان‌بندی خودکار با cron

دستور بالا را در یک اسکریپت بریزید، مثلا /usr/local/bin/backup-mysite.sh، و اجرایی‌اش کنید:

chmod +x /usr/local/bin/backup-mysite.sh

بعد با crontab -e یک خط برای اجرای شبانه اضافه کنید:

0 2 * * * /usr/local/bin/backup-mysite.sh >> /var/log/rsync-backup.log 2>&1

این خط هر شب ساعت 2 اسکریپت را اجرا می‌کند و خروجی را در یک فایل لاگ ذخیره می‌کند. بعد از چند شب، آن فایل لاگ را چک کنید؛ اگر خطی با rsync error یا Permission denied دیدید، یعنی کلید SSH یا مجوز پوشهٔ مقصد مشکل دارد، نه این‌که بکاپ درست گرفته شده باشد.

اگر با وجود این پاکسازی هم فضای دیسک تمام شد، اول همین find را چک کنید که درست اجرا شده، نه این‌که مستقیم سراغ بزرگ کردن دیسک بروید. برای پاکسازی اسنپ‌شات‌های قدیمی‌تر از مثلا 14 روز، یک خط دیگر هم می‌توانید به cron اضافه کنید:

30 2 * * * find /backup/mysite -maxdepth 1 -type d -mtime +14 -exec rm -rf {} \;

چند نکتهٔ عملی برای استفادهٔ واقعی

چند فایل یا پوشه را معمولا نباید همگام‌سازی کرد: کش، فایل‌های موقت، و پوشهٔ node_modules یا vendor که دوباره قابل ساخت هستند. با --exclude این مسیرها را کنار بگذارید تا هم زمان و هم فضا صرفه‌جویی شود:

rsync -avz --delete --exclude 'cache/' --exclude '*.tmp' \
  -e "ssh -i ~/.ssh/rsync_backup" \
  /var/www/mysite/ user@backup-server:/backup/mysite/

اگر بکاپ روی یک لینک اینترنتی محدود اجرا می‌شود، فلگ --bwlimit=5000 سرعت انتقال را به 5 مگابایت بر ثانیه محدود می‌کند تا کاربران واقعی سرور در ساعت بکاپ کندی حس نکنند. و برای پوشه‌های خیلی بزرگ با میلیون‌ها فایل کوچک، فلگ --progress به‌جای -v خروجی خواناتری می‌دهد که نشان می‌دهد کار کجاست.

روی یک سرور مجازی که منبع و مقصد بکاپ روی آن هستند، فضای دیسک و پهنای باند شبکه همان چیزی است که سرعت این کار را تعیین می‌کند؛ اگر پلن فعلی‌تان با چند اسنپ‌شات روزانه پر می‌شود، گزینهٔ اول افزایش فضای دیسک بدون قطعی است، و اگر آن هم کافی نبود، وقت بالا بردن پلن یا گرفتن یک سرور مجازی جدید برای همان بکاپ است.

سؤالات متداول

آیا rsync برای بکاپ بین دو سرور ویندوز و لینوکس هم کار می‌کند؟ نسخهٔ اصلی rsync برای لینوکس و مک است. روی ویندوز باید از WSL یا نسخه‌هایی مثل cwRsync استفاده کنید؛ بین دو سرور لینوکس مستقیم و بدون نرم‌افزار اضافه کار می‌کند.

تفاوت rsync با rclone چیست؟ rsync برای سرورهایی با دسترسی SSH طراحی شده. rclone بیشتر برای فضاهای ابری مثل S3 یا Google Drive ساخته شده و از پروتکل‌های متفاوتی پشتیبانی می‌کند؛ برای همگام‌سازی دو سرور لینوکس، rsync انتخاب ساده‌تری است.

آیا rsync می‌تواند جایگزین کامل یک راهکار بکاپ حرفه‌ای شود؟ برای یک یا چند سرور با نیاز ساده، بله کافی است. برای محیط‌هایی با چند ده سرور یا نیاز به رمزنگاری و مانیتورینگ مرکزی، ابزارهایی مثل Borg یا Restic روی همان کلیدهای SSH مزایای بیشتری دارند.

چرا اجرای دوم rsync سریع‌تر از اولی است؟ چون در اجرای اول همهٔ فایل‌ها تازه هستند و کامل منتقل می‌شوند. از اجرای دوم به بعد، rsync فقط فایل‌های تغییریافته را پیدا و منتقل می‌کند، برای همین زمان اجرا معمولا چند برابر کوتاه‌تر می‌شود.

اگر همین امروز می‌خواهید این را تست کنید، یک سرور مقصد کوچک کافی است تا ببینید اسکریپت و cron درست کار می‌کنند، قبل از این‌که آن را روی سرور اصلی اجرا کنید.