عنوان:

‫مهاجرت reddit از پایتون به Go


نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۹/۱۳ ۱۰:۱۴
آدرس: www.dntips.ir
ردیت زیرساخت backend نظرات خود را مدرن‌سازی کرده‌است و مدل نظرات را از یک مونولیت قدیمی پایتون به یک میکروسرویس جدید مبتنی بر گو (Go) منتقل کرده. این بخشی از تلاش گسترده‌تری برای جایگزینی چهار مدل اصلی (نظرات، حساب‌ها، پست‌ها، subredditها) بوده که قبلاً توسط یک سرویس پایتون قدیمی با مشکلات قابلیت اطمینان و عملکرد ارائه می‌شدند. مدل نظرات به دلیل حجم بالای نوشتاری و نقش حیاتی در تعامل کاربران، اولویت داشت.

چالش‌های کلیدی:
  • مشکلات سیستم قدیمی: مونولیت پایتون سابقه‌ای از مشکلات قابلیت اطمینان و عملکرد داشت و مالکیت آن بین تیم‌ها تقسیم شده بود که نگهداری را دشوار می‌کرد.
  • ریسک‌های مهاجرت endpointهای نوشتاری: برخلاف endpointهای خواندنی، عملیات نوشتاری شامل چندین datastore (پستگرس، مم‌کش، ردیس) و نیاز به تحویل تضمینی رویدادهای CDC (Change Data Capture) است. مهاجرت نادرست می‌توانست داده‌های تولید را خراب کند یا رویدادها را مختل کند.
  • تفاوت‌های زبانی: تفاوت بین پایتون (با استفاده از ORM) و گو (بدون ORM) منجر به فشار غیرمنتظره روی دیتابیس و مشکلات سریال‌سازی شد، جایی که سرویس‌های پایتون نمی‌توانستند داده‌های نوشته‌شده توسط گو را deserialize کنند.
  • شرایط رقابتی (Race Conditions): در تست tap compare، شرایط رقابتی باعث mismatches کاذب در مقایسه داده‌ها می‌شد، زیرا به‌روزرسانی‌های همزمان بین سرویس گو و پایتون قدیمی منجر به وضعیت‌های ناسازگار می‌شد.
  • پیچیدگی متادیتای نظرات: نظرات هزاران ترکیب ممکن از وضعیت‌های داخلی و متادیتا دارند که تست جامع را دشوار می‌کند. موارد حاشیه‌ای تنها در tap compare تولید ظاهر می‌شدند.

راه‌حل‌های پیاده‌شده:
  • Tap Compare برای endpointهای خواندنی: روشی ایمن برای تست endpointهای خواندنی جدید با هدایت درصد کمی از ترافیک به سرویس جدید، مقایسه پاسخ آن با سرویس قدیمی (که از سرویس جدید فراخوانی می‌شود)، و ثبت تفاوت‌ها بدون تأثیر بر کاربران.
  • Datastoreهای خواهری برای endpointهای نوشتاری: برای تست ایمن نوشتاری‌ها، سه datastore ایزوله خواهری (شبیه پستگرس، مم‌کش، ردیس) ایجاد شد. سرویس گو در طول تست به این‌ها می‌نوشت در حالی که نوشتاری‌های تولید را به سرویس پایتون قدیمی واگذار می‌کرد. پس از نوشتاری، محتوای تولید و datastoreهای خواهری مقایسه می‌شدند.
فرآیند:
  • هدایت درصد کمی از ترافیک به میکروسرویس گو.
  • سرویس گو سرویس پایتون قدیمی را برای نوشتاری تولید فرامی‌خواند.
  • سرویس گو به datastoreهای خواهری می‌نوشت.
  • مقایسه محتوای تولید و datastoreهای خواهری.
  • رفع سریال‌سازی: بررسی لاگ‌های tap compare در مصرف‌کنندگان رویداد CDC پایتون قدیمی برای اطمینان از deserialize شدن داده‌های نوشته‌شده توسط گو.
  • مدیریت شرایط رقابتی: تشخیص اینکه mismatches گاهی به دلیل شرایط رقابتی است (مثلاً نظر به‌روزرسانی‌شده چندین بار بین فراخوانی‌های گو و پایتون). برنامه آینده: نسخه‌بندی به‌روزرسانی‌های دیتابیس برای مقایسه تنها تغییرات مرتبط.
  • بهینه‌سازی کوئری‌ها: رفع فشار اولیه دیتابیس از گو با بهینه‌سازی کوئری‌ها، زیرا ORM پایتون بهینه‌سازی‌های پنهانی داشت.

فناوری‌های استفاده‌شده:
  • قدیمی: مونولیت پایتون، پستگرس (datastore backend)، مم‌کش (کشینگ)، ردیس (ذخیره رویداد برای CDC).
  • جدید: میکروسرویس گو، کوبرنتیز (برای میزبانی در UTC)، gRPC/Thrift (برای ارتباط سرویس‌ها).
  • ابزارها: تست tap compare، تجمیع لاگ برای تأیید، کانتینرهای داکرایز شده.

نتایج:
  • مهاجرت موفق: تمام endpointهای نظرات اکنون توسط میکروسرویس گو ارائه می‌شوند بدون اختلال برای کاربران.
  • بهبود عملکرد: تأخیر endpointهای نوشتاری (ایجاد نظر، به‌روزرسانی نظر، افزایش خواص نظر) نصف شده. گراف‌های P99 نشان‌دهنده سرویس پایتون قدیمی (سبز) با پیک تا ۱۵ ثانیه، در حالی که سرویس گو (زرد) به طور مداوم زیر ۱۰۰ میلی‌ثانیه است.
  • اولین مهاجرت مدل اصلی: نظرات اولین مدل اصلی است که کاملاً از مونولیت قدیمی خارج شده.
  • حفظ قابلیت اطمینان: تحویل ۱۰۰% رویدادهای CDC حفظ شده.

برنامه‌های آینده:
  • مهاجرت مدل‌های باقی‌مانده (پست‌ها و subredditها) به میکروسرویس‌های مدرن گو.
  • بهبود تست: سرمایه‌گذاری در تست محلی جامع‌تر با استفاده از داده‌های واقعی تولید برای گرفتن موارد حاشیه‌ای قبل از tap compare.
  • بهبود tap compare: کاهش بررسی دستی لاگ با تشخیص خودکار تفاوت‌ها و مدیریت شرایط رقابتی با نسخه‌بندی دیتابیس.
  • ادامه مدرن‌سازی: حذف تمام مونولیت‌های قدیمی پایتون برای اطمینان از قابلیت اطمینان و عملکرد در سراسر زیرساخت ردیت.


مشاهده مطلب اصلی