پرش به محتوای اصلی
پرش به محتوای مقاله

JuiceFS ۱.۴: افزایش ۹۳ برابری سرعت حذف فایل در مجموعه‌داده‌های AI

·۲۸ خرداد ۱۴۰۵۹ دقیقه مطالعه
JuiceFS ۱.۴: عملیات سریع‌تر متادیتا با حذف دسته‌ای، شبیه‌سازی دسته‌ای و کش سمت کاربر Redis
JuiceFS ۱.۴: عملیات سریع‌تر متادیتا با حذف دسته‌ای، شبیه‌سازی دسته‌ای و کش سمت کاربر Redis
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

جایگزینی تراکنش‌های تک‌نفره متادیتا با عملیات دسته‌ای (Batching) که منجر به جهش ۹۳ برابری در سرعت حذف فایل شد؛ تغییری که مستقیماً روی لایه عملیاتی اثر می‌گذارد نه فقط تئوری.

اگر میلیون‌ها فایل کوچک را برای آموزش مدل‌های هوش مصنوعی مدیریت می‌کنید، بزرگ‌ترین مانع شما معمولاً پهنای باند داده نیست، بلکه تأخیر در پاسخگویی به متادیتا (Metadata Latency) است. JuiceFS Community Edition 1.4 دقیقاً همین نقطه ضعف را هدف گرفته تا زمان حذف و کپی مجموعه‌داده‌های عظیم را به شدت کاهش دهد.

در سناریوهای دسترسی گسترده به فایل‌ها، مانند آموزش مدل‌های هوش مصنوعی و مدیریت مجموعه‌داده‌ها، متادیتا اغلب اولین گلوگاه عملکردی است؛ به‌ویژه زمانی که تعداد فایل‌ها و میزان دسترسی‌های هم‌زمان (Concurrency) افزایش می‌یابد. چه در حال حذف میلیون‌ها فایل کوچک باشید، چه در حال کپی مجموعه‌داده‌های بزرگ یا پیمایش دایرکتوری‌ها تحت فشار ترافیکی بالا، عملکرد متادیتا مستقیماً بر کارایی کل اپلیکیشن اثر می‌گذارد. در این محیط‌ها، هر درخواست تک‌فایل معمولاً یک رفت‌وبرگشت شبکه‌ای (Network Round Trip) مجزا ایجاد می‌کند. این امر منجر به ایجاد سربار عظیمی از فراخوانی‌های سیستم (System Calls) و تعویض‌های زمینه (Context Switches) می‌شود که در نهایت کل خط لوله آموزش مدل را کند می‌کند.

برای حل این مشکل، JuiceFS سه بهینه‌سازی اصلی در لایه متادیتا معرفی کرده است: حذف دسته‌ای (Batch Unlink) برای پاکسازی فایل‌ها در مقیاس بزرگ، کپی دسته‌ای (Batch Clone) برای تکثیر متادیتا، و کشینگ سمت کلاینت Redis برای خواندن متادیتای «داغ» (Hot Metadata). این بهبودها باعث کاهش تعداد تایید تراکنش‌ها (Transaction Commits)، کاهش رفت‌وبرگشت‌های شبکه‌ای و حذف جست‌وجوهای تکراری متادیتا می‌شوند. این رویکرد برای پژوهشگران هوش مصنوعی که به‌طور مکرر مجموعه‌داده‌ها را می‌چرخانند یا نسخه‌بندی (Version-control) بزرگی روی پیکره‌های متنی و تصویری انجام می‌دهند، حیاتی است.

گلوگاه حذف: Batch Unlink

حذف یک فایل در معماری‌هایی که متادیتا از داده تفکیک شده است، فرآیند پیچیده‌ای است و بسیار فراتر از حذف یک ورودی ساده در دایرکتوری است. سیستم باید مراحل زیر را طی کند:

  • به‌روزرسانی شمارنده ارجاعات اینود (Inode Reference Counts)
  • بازپس‌گیری منابع اینود و فضای ذخیره‌سازی
  • پردازش ورودی‌های سطل زباله (Trash Entries)
  • به‌روزرسانی آمارهای سهمیه (Quota Statistics)

این عملیات‌ها معمولاً باید در قالب یک تراکنش واحد تکمیل شوند. در حالت سنتی، استفاده از دستور rm -rf برای هر تک‌فایل یک تراکنش متادیتای مجزا را تحریک می‌کند. هر درخواست unlink از پروتکل FUSE عبور کرده، بین فضای هسته (Kernel) و فضای کاربر (User Space) سوئیچ می‌کند و یک تراکنش جداگانه را فعال می‌سازد. با رشد تعداد فایل‌ها، سربار ناشی از فراخوانی‌های سیستم و رفت‌وبرگشت‌های شبکه به‌سرعت انباشته می‌شود.

JuiceFS پیش از این تلاش کرده بود با دستور juicefs rmr این مشکل را حل کند. برخلاف rm -rf ، دستور rmr لایه FUSE را دور می‌زند و درخواست‌های حذف را مستقیماً به کلاینت می‌فرستد. همچنین از حذف چندرشته‌ای (به‌طور پیش‌فرض ۵۰ رشته) پشتیبانی می‌کند. با این حال، موتور متادیتا همچنان مجبور بود برای هر فایل یک تراکنش اجرا کند. به این معنا که حذف ۱۰۰,۰۰۰ فایل، همچنان به ۱۰۰,۰۰۰ تراکنش نیاز داشت.

قابلیت Batch Unlink این روند را تغییر می‌دهد. این سیستم چندین عملیات حذف در یک دایرکتوری واحد را در قالب یک تراکنش دسته‌ای (Batch Transaction) ادغام می‌کند. فایل‌های معمولی و لینک‌های نمادین (Symbolic Links) را گروه‌بندی کرده و در یک فراخوانی واحد به موتور متادیتا ارسال می‌کند. این کار باعث تبدیل تعداد زیادی تراکنش کوچک به تعداد کمی تراکنش بزرگ می‌شود.

پیاده‌سازی Batch Unlink

JuiceFS یک رابط (Interface) برای حذف دسته‌ای در لایه موتور متادیتا اضافه کرده است. هنگام پاکسازی بازگشتی (Recursive) یک دایرکتوری، سربار به دو روش کاهش می‌یابد:
۱. دایرکتوری‌های مختلف به‌صورت هم‌زمان و با استفاده از حذف چندرشته‌ای مدیریت می‌شوند.
۲. در داخل هر دایرکتوری، فایل‌های عادی و symlinkها در دسته‌هایی گروه‌بندی شده و به تابع BatchUnlink ارسال می‌شوند.

نکته مهم این است که BatchUnlink به‌طور مستقیم دایرکتوری‌ها را حذف نمی‌کند. حذف دایرکتوری‌ها از همان گردش کار بازگشتی استاندارد پیروی می‌کند: ابتدا محتویات زیر-دایرکتوری خالی می‌شود و سپس خودِ زیر-دایرکتوری حذف می‌گردد. این روش باعث حفظ معناشناسی صحیح حذف بازگشتی و جلوگیری از ریسک‌های مربوط به سازگاری در ساختار درخت دایرکتوری می‌شود.

JuiceFS 1.4: عملیات سریع‌تر متادیتا با حذف دسته‌ای، شبیه‌سازی دسته‌ای و کش سمت کاربر Redis

بهره‌وری حاصل از این روش بسته به بک‌اند (Backend) متفاوت است، زیرا سیستم از استراتژی‌های دسته‌بندی متفاوتی برای به حداقل رساندن تایید تراکنش‌ها استفاده می‌کند:

  • بک‌اندهای SQL (مانند MySQL، PostgreSQL و غیره): پیش از این، هر فایل به توالی مجزایی از دستورات INSERT، DELETE و UPDATE نیاز داشت. اکنون سیستم تمام رکوردهای لبه (Edge Records) برای ورودی‌های هدف را در یک پرس‌وجوی دسته‌ای دریافت کرده و ویژگی‌های اینود مربوطه را در یک پرس‌وجوی دسته‌ای قفل‌شده می‌گیرد. سپس حذف لبه‌ها، به‌روزرسانی وضعیت اینود (کاهش nlink یا علامت‌گذاری برای پاکسازی) و درج ورودی‌های delfile را همگی در یک تراکنش واحد اجرا می‌کند.
  • بک‌اند Redis: از خط لوله (Pipeline) و تراکنش‌های MULTI/EXEC استفاده می‌کند. تمام دستورات HDEL (حذف dentry)، ZADD (صف برای پاکسازی)، SET (به‌روزرسانی ویژگی اینود) و INCRBY (به‌روزرسانی شمارنده) برای چندین فایل در یک خط لوله جمع‌آوری می‌شوند. برای جلوگیری از مسدود کردن حلقه رویداد تک‌رشته‌ای Redis برای مدت طولانی، اندازه هر دسته به ۲۵۰ ورودی محدود شده است.
  • بک‌اند TiKV: از قابلیت بومی نوشتن دسته‌ای (Batch Write) در TiKV برای تجمیع چندین حذف در یک تراکنش واحد بهره می‌برد. این امر اجازه می‌دهد ظرفیت نوشتن هم‌زمان بک‌اند به‌طور کامل مورد استفاده قرار گیرد.

در بنچمارک‌های انجام شده روی یک دایرکتوری تخت (Flat) شامل ۱۰۰,۰۰۰ فایل با دستور juicefs rmr --threads 16 ، قابلیت Batch Unlink عملکرد را تا ۹۳ برابر نسبت به روش‌های سنتی بهبود بخشید؛ بیشترین سود در TiKV و Redis مشاهده شد.

سرعت بخشیدن به نسخه‌بندی مجموعه‌داده: Batch Clone

در آموزش هوش مصنوعی، ایجاد Snapshot از مجموعه‌داده‌ها بسیار رایج است. دستور juicefs clone امکان کپی سریع را با استفاده مجدد از ارجاعات بلوک‌های موجود (به‌جای کپی واقعی داده‌ها) فراهم می‌کند. بلوک‌های داده جدید تنها زمانی تخصیص می‌یابند که روی نسخه کپی شده نوشته شود، که این کار از سربار زمانی و فضای ذخیره‌سازی کپی کامل جلوگیری می‌کند.

با این حال، کپی کردن یک دایرکتوری بزرگ همچنان از مشکل تراکنش‌های «تک‌به‌تک» رنج می‌برد. قابلیت Batch Clone این مشکل را با خواندن ورودی‌های دایرکتوری به‌صورت جریانی (Stream) حل می‌کند. برای هر دسته، تمام ورودی‌های غیر-دایرکتوری جمع‌آوری شده و در یک عملیات واحد کپی می‌شوند.

مکانیسم Batch Clone

یک جزئیات فنی کلیدی در اینجا، «پیش‌تخصیص اینود» (Inode Pre-allocation) است. پیش از ورود به تراکنش، سیستم از nextInode برای تخصیص پیش‌دستانه اینودهای هدف برای تمام ورودی‌هایی که قرار است کپی شوند، استفاده می‌کند. این کار باعث جلوگیری از تداخل قفل‌ها (Lock Contention) می‌شود که در صورت درخواست مکرر اینود در داخل تراکنش رخ می‌داد.

پس از ورود به تراکنش، فرآیند مراحل زیر را طی می‌کند:

  • پرس‌وجوی دسته‌ای تمام ویژگی‌های فایل منبع با استفاده از قفل‌های ردیفی (Row Locks).
  • ساخت تمام داده‌های درج برای نودهای هدف، لبه‌ها، چانک‌ها، symlinkها و xattrها.
  • درج تمام داده‌ها در یک دسته واحد.

JuiceFS 1.4: عملیات سریع‌تر متادیتا با حذف دسته‌ای، شبیه‌سازی دسته‌ای و کش سمت-کلاینت Redis

کپی دسته‌ای (Batch Clone) مشابه حذف دسته‌ای، از قابلیت‌های بومی نوشتن دسته‌ای هر بک‌اند استفاده می‌کند. بهبود عملکرد به مدل تراکنش، سربار ارتباطات شبکه و کارایی درج دسته‌ای برای رکوردهای متادیتا بستگی دارد. نتایج روی یک دایرکتوری تخت با ۱۰۰,۰۰۰ فایل نشان می‌دهد:

  • MySQL: تقریباً ۲۴ برابر سرعت بیشتر.
  • Redis: تقریباً ۵ برابر سرعت بیشتر.
  • TiKV: تقریباً ۲ برابر سرعت بیشتر.

حذف تأخیر شبکه: کشینگ سمت کلاینت Redis

حتی با وجود دسته‌بندی، جست‌وجوهای مکرر برای متادیتای «داغ» می‌تواند موتور Redis را تحت فشار قرار دهد. عملیات open("/mnt/jfs/dataset/images/cat.jpg") را در نظر بگیرید. سیستم فایل مجازی لینوکس (VFS) باید هر جزء را تفکیک کند: جست‌وجوی dataset ، سپس images و در نهایت cat.jpg.

اگر دایرکتوری images شامل صدها هزار فایل باشد و کارهای آموزشی دسترسی تصادفی (Random Access) داشته باشند، هر جست‌وجو نیاز به یک درخواست GET به Redis دارد. حتی اگر یک پرس‌وجو تنها چند ده میکروثانیه زمان ببرد، تأخیر شبکه هر جست‌وجو را به صدها میکروثانیه یا میلی‌ثانیه می‌رساند. تحت فشار هم‌زمانی بالا، این منجر به رفت‌وبرگشت‌های شبکه‌ای عظیم و افزایش شدید بهره‌برداری از CPU در Redis می‌شود.

نحوه عملکرد کشینگ سمت کلاینت Redis

JuiceFS قابلیت کشینگ سمت کلاینت Redis 6.0 را پیاده‌سازی کرده است که به کلاینت‌ها اجازه می‌دهد کلیدهای داغ را به‌صورت محلی کش کرده و در صورت تغییر، اعلان‌های ابطال (Invalidation Notifications) را دریافت کنند. JuiceFS دو دسته از متادیتا را کش می‌کند:

  • کش ویژگی‌های اینود (Inode Attribute Cache): این کش با کلید شماره اینود کار می‌کند و داده‌های کامل ویژگی‌ها (نوع، اندازه، مجوزها، برچسب‌های زمانی) را ذخیره می‌کند. این قابلیت از طریق مکانیسم‌های Hook در لایه درایور Redis پیاده شده است. هنگام پرس‌وجو، ابتدا کش محلی بررسی می‌شود و در صورت یافتن (Hit)، پاسخ فوراً بازگردانده می‌شود. در صورت تغییر متادیتا، کش به‌طور خودکار ابطال می‌گردد.
  • کش ورودی دایرکتوری (Directory Entry Cache): این کش با کلید «اینود والد + جداکننده مسیر + نام فایل» کار می‌کند و نتایج جست‌وجوی دایرکتوری را ذخیره می‌کند. منطق جست‌وجو مستقیماً در مسیر جست‌وجوی دایرکتوری تعبیه شده است. وقتی ورودی‌های یک دایرکتوری ابطال شوند، تمام ورودی‌های کش مرتبط با آن دایرکتوری با استفاده از تطبیق پیشوندی (Prefix Matching) پاک می‌شوند.

JuiceFS 1.4: عملیات سریع‌تر متادیتا با حذف دسته‌ای، شبیه‌سازی دسته‌ای و کش سمت کاربر Redis

سازگاری و مدل BCAST

کشینگ سمت کلاینت در سناریوهای چند-کلاینتی (Multi-mount) یک چالش سازگاری ایجاد می‌کند. اگر یک کلاینت فایلی را ایجاد، حذف یا تغییر نام دهد، سایر کلاینت‌ها ممکن است متادیتای قدیمی (Stale) را ببینند. برای حل این مشکل، JuiceFS مدل «ردیابی و ابطال پخش گسترده» یا BCAST را معرفی کرده است.

پس از اتصال به Redis، هر کلاینت پیشوندهای کلید متادیتایی را که می‌خواهد ردیابی کند، اعلام می‌کند. هرگاه آن کلیدها تغییر کنند، Redis اعلان‌های ابطال را برای کلاینت‌های مربوطه می‌فرستد. کلاینت پس از دریافت اعلان، کش ویژگی اینود یا ورودی دایرکتوری مربوطه را پاک می‌کند تا دسترسی‌های بعدی داده‌های تازه را دریافت کنند.

JuiceFS ۱.۴: عملیات سریع‌تر متادیتا با حذف دسته‌ای، شبیه‌سازی دسته‌ای و کش سمت کاربر Redis

علاوه بر این، JuiceFS در هنگام مقداردهی اولیه کلاینت، متادیتای دایرکتوری ریشه (Root) نقطه اتصال را «گرم» (Warm-up) می‌کند. از آنجایی که این فایل‌ها بیشترین دسترسی را دارند، این گرم‌کردن باعث بهبود چشمگیر عملکرد کلی می‌شود.

کاربردها و محدودیت‌ها

کشینگ سمت کلاینت Redis برای سناریوهایی که خواندن بسیار زیاد و نوشتن کم است (Read-heavy, Write-light) ایده‌آل است؛ مانند آموزش هوش مصنوعی که مجموعه‌داده‌ها معمولاً فقط-خواندنی (Read-only) هستند. این قابلیت به‌ویژه در استقرار بین مناطق دسترسی (Cross-AZ) که تأخیر شبکه بالاست، مفید است.

نیازمندی‌ها و تنظیمات کلیدی عبارتند از:

  • نسخه: Redis نسخه ۶.۰ یا بالاتر مورد نیاز است.
  • انقضا: زمان انقضای پیش‌فرض کش ۱ دقیقه است. این یک شبکه ایمنی برای مواردی است که اعلان‌های ابطال به دلیل اختلالات شبکه نمی‌رسند.
  • سازگاری: برای حجم کارهایی با نیاز به سازگاری سخت‌گیرانه، کاربران می‌توانند زمان انقضا را کوتاه‌تر کرده یا کشینگ سمت کلاینت را به‌طور کامل غیرفعال کنند.

تحلیل تحریریه

این به‌روزرسانی نشان‌دهنده تغییری در نحوه برخورد سیستم‌های فایل توزیع‌شده با «مشکل فایل‌های کوچک» در هوش مصنوعی است. با انتقال منطق از عملیات تک‌فایل به تراکنش‌های دسته‌ای، JuiceFS اذعان می‌کند که در عصر AI، موتور متادیتا گلوگاه واقعی است، نه I/O دیسک.

برای متخصصان، این بدان معناست که انتخاب بک‌اند متادیتا اکنون اهمیت بیشتری دارد. جهش ۹۳ برابری در سرعت حذف برای برخی بک‌اندها نشان می‌دهد که سربار هرگز سخت‌افزار نبوده، بلکه مدل تراکنش بوده است. معرفی BCAST برای کشینگ Redis نیز JuiceFS را به عملکرد سیستم‌های فایل محلی نزدیک‌تر می‌کند در حالی که مقیاس‌پذیری ابری را حفظ می‌کند.

خلاصه و گام‌های بعدی

این سه بهینه‌سازی مسیرهای مختلفی را هدف قرار داده‌اند: Batch Unlink و Batch Clone عملیات‌های مستقل در یک دایرکتوری را در تراکنش‌های دسته‌ای ادغام می‌کنند، در حالی که کشینگ سمت کلاینت Redis تأخیر خواندن را از سطح شبکه به سطح حافظه می‌آورد.

کاربران باید توجه کنند که BatchUnlink و BatchClone رابط‌های داخلی هستند و هنگام استفاده از juicefs rmr و juicefs clone به‌طور خودکار اعمال می‌شوند. چون این عملیات‌ها فایل‌های معمولی را در یک دایرکتوری ادغام کرده و زیر-دایرکتوری‌ها را به‌صورت بازگشتی از طریق Goroutineهای هم‌زمان مدیریت می‌کنند، هرچه دایرکتوری بزرگ‌تر باشد، سود حاصل از آن بیشتر است.

تمام این بهینه‌سازی‌ها در JuiceFS Community Edition 1.4 در دسترس هستند. کلاینت خود را ارتقا دهید تا این بهبودهای عملکردی را دریافت کنید. برای سوالات بیشتر، به بحث‌های JuiceFS در GitHub یا جامعه Discord بپیوندید.

چرا این موضوع مهم است؟

این به‌روزرسانی با تکیه بر اعتبار معماری توزیع‌شده، هزینه‌ی زمانی مدیریت داده‌ها در مقیاس پتا‌بایت را حذف می‌کند. این موضوع برای تیم‌های زیرساختی AI که با میلیون‌ها فایل کوچک سرور می‌چرخانند، یک تغییر بنیادین در بهره‌وری است.

تأثیر برای ایران

برای توسعه‌دهندگانی در ایران که با محدودیت منابع سخت‌افزاری در خوشه‌های محاسباتی روبرو هستند، استفاده از این ابزار متن‌باز می‌تواند فشار روی CPU و شبکه سرورها را به‌طور چشمگیری کاهش دهد.

·نگاه ما
تحریریه دات‌هوش

تمرکز JuiceFS بر کاهش تأخیر متادیتا نشان می‌دهد که در عصر مدل‌های غول‌پیکر، دیگر پهنای باند گلوگاه نیست، بلکه مدیریت «تعداد» درخواست‌هاست. این رویکرد، معماری سیستم‌های فایل را از مدل‌های سنتی به سمت ساختارهای بهینه برای یادگیری ماشین می‌برد که در آن دسته‌بندی داده‌ها اولویت دارد تا تک‌درخواست‌ها.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.