در انتظار راه اندازی یک جریان جدید در نرخ مهندس داده ترجمه ای از مطالب جالب را آماده کرده ایم.
مرور
ما در مورد یک الگوی نسبتاً محبوب صحبت خواهیم کرد که توسط آن برنامهها از چندین فروشگاه داده استفاده میکنند، جایی که هر فروشگاه برای اهداف خاص خود استفاده میشود، به عنوان مثال، برای ذخیره فرم متعارف داده (MySQL و غیره)، ارائه قابلیتهای جستجوی پیشرفته (ElasticSearch، و غیره) .)، کش (Memcached و غیره) و دیگران. به طور معمول، هنگام استفاده از چندین فروشگاه داده، یکی از آنها به عنوان ذخیره اصلی و بقیه به عنوان فروشگاه های مشتق عمل می کنند. تنها مشکل این است که چگونه می توان این ذخیره های داده را همگام کرد.
ما به تعدادی الگوی مختلف نگاه کردیم که سعی در حل مشکل همگام سازی چندین فروشگاه، مانند نوشتن دوبل، تراکنش های توزیع شده و غیره داشتند. با این حال، این رویکردها دارای محدودیت های قابل توجهی از نظر استفاده واقعی، قابلیت اطمینان و نگهداری هستند. علاوه بر همگام سازی داده ها، برخی از برنامه ها نیز نیاز به غنی سازی داده ها از طریق فراخوانی سرویس های خارجی دارند.
دلتا برای حل این مشکلات توسعه داده شد. دلتا در نهایت یک پلتفرم ثابت و رویداد محور برای همگام سازی و غنی سازی داده ها فراهم می کند.
راه حل های موجود
دو ورودی
برای همگام نگه داشتن دو ذخیرهگاه داده، میتوانید از نوشتن دوگانه استفاده کنید، که در یک فروشگاه مینویسد و بلافاصله پس از آن در دیگری مینویسد. ضبط اول را می توان مجدداً امتحان کرد و در صورت شکست اولی پس از اتمام تعداد تلاش ها، ضبط دوم را می توان لغو کرد. با این حال، اگر نوشتن در فروشگاه دوم ناموفق باشد، ممکن است دو ذخیرهگاه داده با هم هماهنگ نباشند. این مشکل معمولاً با ایجاد یک روش بازیابی حل میشود که میتواند بهطور دورهای دادهها را از اولین ذخیرهسازی به ذخیرهسازی دوم مجدداً منتقل کند، یا این کار را تنها در صورت تشخیص تفاوت در دادهها انجام دهد.
مشکلات این است:
انجام یک روش بازیابی یک کار خاص است که قابل استفاده مجدد نیست. علاوه بر این، دادههای بین مکانهای ذخیرهسازی تا زمانی که فرآیند بازیابی انجام نشود، هماهنگ نیستند. اگر بیش از دو ذخیرهگاه داده استفاده شود، راهحل پیچیدهتر میشود. در نهایت، روش بازیابی می تواند بار را به منبع داده اصلی اضافه کند.
جدول گزارش را تغییر دهید
هنگامی که تغییراتی در مجموعه ای از جداول رخ می دهد (مانند درج، به روز رسانی و حذف یک رکورد)، رکوردهای تغییر به عنوان بخشی از همان تراکنش به جدول گزارش اضافه می شوند. رشته یا فرآیند دیگری دائماً رویدادها را از جدول گزارش درخواست می کند و آنها را در یک یا چند فروشگاه داده می نویسد، در صورت لزوم، پس از تأیید رکورد توسط همه فروشگاه ها، رویدادها را از جدول گزارش حذف می کند.
مشکلات این است:
این الگو باید به صورت کتابخانه ای و در حالت ایده آل بدون تغییر کد برنامه ای که از آن استفاده می کند، پیاده سازی شود. در یک محیط چند زبانه، اجرای چنین کتابخانه ای باید به هر زبان ضروری وجود داشته باشد، اما اطمینان از سازگاری عملکرد و رفتار در بین زبان ها بسیار دشوار است.
مشکل دیگر در به دست آوردن تغییرات طرحواره در سیستم هایی است که از تغییرات طرحواره تراکنش پشتیبانی نمی کنند [1][2]، مانند MySQL. بنابراین، الگوی ایجاد یک تغییر (مثلاً تغییر طرحواره) و ثبت تراکنش آن در جدول ثبت تغییرات همیشه کارساز نخواهد بود.
معاملات توزیع شده
تراکنشهای توزیعشده را میتوان برای تقسیم یک تراکنش در چندین فروشگاه داده ناهمگن استفاده کرد، به طوری که عملیات یا به همه ذخیرههای دادهای که استفاده میشوند متعهد باشد یا به هیچ یک از آنها متعهد نباشد.
مشکلات این است:
تراکنش های توزیع شده یک مشکل بسیار بزرگ برای ذخیره سازی داده های ناهمگن است. آنها بنا به ماهیت خود تنها می توانند به کمترین مخرج مشترک سیستم های درگیر تکیه کنند. برای مثال، تراکنشهای XA اجرا را مسدود میکنند اگر فرآیند برنامه در مرحله آمادهسازی با شکست مواجه شود. علاوه بر این، XA تشخیص بن بست را ارائه نمی دهد یا از طرح های کنترل همزمان خوش بینانه پشتیبانی نمی کند. علاوه بر این، برخی از سیستمها مانند ElasticSearch از XA یا هر مدل تراکنش ناهمگن دیگری پشتیبانی نمیکنند. بنابراین، اطمینان از اتمی نوشتن در فنآوریهای مختلف ذخیرهسازی داده، یک کار بسیار چالش برانگیز برای برنامهها است [3].
دلتا
دلتا برای رفع محدودیتهای راهحلهای همگامسازی دادههای موجود طراحی شده است و همچنین غنیسازی دادهها را در لحظه امکانپذیر میسازد. هدف ما این بود که همه این پیچیدگی ها را از توسعه دهندگان برنامه انتزاعی کنیم تا بتوانند به طور کامل روی اجرای عملکردهای تجاری تمرکز کنند. در ادامه «جستجوی فیلم» را توضیح خواهیم داد، مورد استفاده واقعی برای دلتای نتفلیکس.
نتفلیکس به طور گسترده از معماری میکروسرویس استفاده می کند و هر میکروسرویس معمولاً یک نوع داده را ارائه می دهد. اطلاعات اولیه درباره فیلم در میکروسرویسی به نام Movie Service موجود است و دادههای مرتبط مانند اطلاعات مربوط به تولیدکنندگان، بازیگران، فروشندگان و غیره توسط چندین میکروسرویس دیگر (یعنی Deal Service، Talent Service و Vendor Service) مدیریت میشوند.
کاربران تجاری در استودیو نتفلیکس اغلب نیاز به جستجو در معیارهای مختلف فیلم دارند، به همین دلیل است که برای آنها بسیار مهم است که بتوانند در تمام داده های مربوط به فیلم جستجو کنند.
قبل از دلتا، تیم جستجوی فیلم باید قبل از فهرست کردن دادههای فیلم، دادهها را از چندین میکروسرویس استخراج میکرد. علاوه بر این، تیم باید سیستمی را توسعه می داد که به طور دوره ای فهرست جستجو را با درخواست تغییرات از سایر میکروسرویس ها به روز می کرد، حتی اگر اصلاً تغییری وجود نداشت. این سیستم به سرعت پیچیده و نگهداری آن دشوار شد.
شکل 1. سیستم نظرسنجی به دلتا
پس از استفاده از دلتا، سیستم به یک سیستم مبتنی بر رویداد مانند شکل زیر ساده شد. رویدادهای CDC (Change-Data-Capture) با استفاده از Delta-Connector به موضوعات Keystone Kafka ارسال می شوند. یک برنامه دلتا که با استفاده از چارچوب پردازش دلتا استریم (بر اساس Flink) ساخته شده است، رویدادهای CDC را از یک موضوع دریافت می کند، آنها را با فراخوانی سایر ریزسرویس ها غنی می کند و در نهایت داده های غنی شده را به فهرست جستجو در Elasticsearch ارسال می کند. کل فرآیند تقریباً در زمان واقعی انجام می شود، یعنی به محض اینکه تغییرات در انبار داده انجام شود، فهرست های جستجو به روز می شوند.
شکل 2. خط لوله داده با استفاده از دلتا
در بخشهای بعدی، عملکرد Delta-Connector را شرح میدهیم که به ذخیرهسازی متصل میشود و رویدادهای CDC را در لایه انتقال منتشر میکند، که یک زیرساخت انتقال داده در زمان واقعی است که رویدادهای CDC را به موضوعات کافکا هدایت میکند. و در پایان، ما در مورد چارچوب پردازش جریان دلتا صحبت خواهیم کرد، که توسعه دهندگان برنامه می توانند از آن برای پردازش داده ها و منطق غنی سازی استفاده کنند.
CDC (Change-Data-Capture)
ما یک سرویس CDC به نام Delta-Connector توسعه دادهایم که میتواند تغییرات متعهد شده را از ذخیرهگاه داده در زمان واقعی ضبط کرده و آنها را در یک جریان بنویسد. تغییرات بلادرنگ از لاگ تراکنش و انبارهای ذخیره سازی گرفته شده است. Dump ها استفاده می شوند زیرا گزارش های تراکنش معمولاً کل تاریخچه تغییرات را ذخیره نمی کنند. تغییرات معمولاً به صورت سریال دلتا میشوند، بنابراین گیرنده نگران نیست که تغییر از کجا آمده است.
Delta-Connector از چندین ویژگی اضافی مانند:
امکان نوشتن داده های خروجی سفارشی از کافکا.
امکان فعال کردن dump های دستی در هر زمان برای همه جداول، یک جدول خاص یا برای کلیدهای اولیه خاص.
Dump ها را می توان به صورت تکه ای بازیابی کرد، بنابراین در صورت خرابی نیازی به شروع دوباره نیست.
نیازی به قرار دادن قفل روی جداول نیست، که برای اطمینان از اینکه ترافیک نوشتن پایگاه داده هرگز توسط سرویس ما مسدود نمی شود بسیار مهم است.
در دسترس بودن بالا به دلیل موارد اضافی در مناطق در دسترس بودن AWS.
ما در حال حاضر از MySQL و Postgres، از جمله استقرار در AWS RDS و Aurora پشتیبانی می کنیم. ما همچنین از Cassandra (مولتی مستر) پشتیبانی می کنیم. شما می توانید جزئیات بیشتر در مورد دلتا-کانکتور را در اینجا بیابید پست وبلاگ.
کافکا و لایه انتقال
لایه انتقال رویداد دلتا بر روی سرویس پیام رسانی این پلتفرم ساخته شده است سنگ سراطاق.
از لحاظ تاریخی، ارسال در Netflix برای دسترسی بهجای طول عمر بهینهسازی شده است (به زیر مراجعه کنید). مقاله قبلی). مبادله، ناهماهنگی بالقوه داده های کارگزار در سناریوهای مختلف لبه بود. مثلا، انتخابات ناپاک رهبر مسئول این است که گیرنده به طور بالقوه دارای رویدادهای تکراری یا گم شده است.
با دلتا، ما ضمانتهای دوام قویتری برای اطمینان از تحویل رویدادهای CDC به فروشگاههای مشتق شده میخواستیم. برای این منظور، ما یک خوشه کافکا با طراحی ویژه را به عنوان یک شی درجه یک پیشنهاد کردیم. در جدول زیر می توانید به برخی از تنظیمات کارگزار نگاه کنید:
در خوشه های کیستون کافکا، انتخابات ناپاک رهبر معمولاً برای اطمینان از دسترسی ناشر گنجانده شده است. این ممکن است منجر به از دست رفتن پیامها در صورت انتخاب یک نسخه غیرهمگامسازی شده به عنوان رهبر شود. برای خوشه جدید کافکا با در دسترس بودن بالا، گزینه انتخابات ناپاک رهبر برای جلوگیری از از دست رفتن پیام خاموش است.
افزایش هم داشتیم فاکتور تکرار از 2 تا 3 و حداقل کپی های insync 1 تا 2. ناشرینی که در این خوشه می نویسند، از همه سایرین نیاز دارند و اطمینان حاصل می کنند که 2 مورد از 3 نسخه جدیدترین پیام های ارسال شده توسط ناشر را دارند.
هنگامی که یک نمونه کارگزار خاتمه می یابد، یک نمونه جدید جایگزین نمونه قبلی می شود. با این حال، کارگزار جدید باید با کپیهای غیرهمگامسازی شده، که ممکن است چندین ساعت طول بکشد، برسد. برای کاهش زمان بازیابی برای این سناریو، ما شروع به استفاده از ذخیره سازی بلوک داده (Amazon Elastic Block Store) به جای دیسک های کارگزار محلی کردیم. هنگامی که یک نمونه جدید جایگزین یک نمونه کارگزار پایانیافته میشود، حجم EBS را که نمونه پایانیافته داشت وصل میکند و شروع به دریافت پیامهای جدید میکند. این فرآیند زمان پاکسازی پسماند را از ساعت ها به دقیقه کاهش می دهد زیرا نمونه جدید دیگر نیازی به تکرار از حالت خالی ندارد. به طور کلی، ذخیره سازی جداگانه و چرخه عمر کارگزار به طور قابل توجهی تأثیر تغییر کارگزار را کاهش می دهد.
برای افزایش بیشتر ضمانت تحویل داده ها، استفاده کردیم سیستم ردیابی پیام برای شناسایی هرگونه از دست دادن پیام در شرایط شدید (مثلاً همگامسازی ساعت در رهبر پارتیشن).
چارچوب پردازش جریان
لایه پردازش دلتا بر روی پلت فرم Netflix SPaaS ساخته شده است که Apache Flink را با اکوسیستم Netflix یکپارچه می کند. این پلتفرم یک رابط کاربری ارائه میکند که استقرار کارهای Flink و هماهنگسازی خوشههای Flink را در بالای پلتفرم مدیریت کانتینر Titus ما مدیریت میکند. این رابط همچنین پیکربندی های کار را مدیریت می کند و به کاربران اجازه می دهد تا تغییرات پیکربندی را به صورت پویا بدون نیاز به کامپایل مجدد کارهای Flink انجام دهند.
دلتا یک چارچوب پردازش جریانی مبتنی بر Flink و SPaaS ارائه می دهد که از آن استفاده می کند مبتنی بر حاشیه نویسی DSL (زبان خاص دامنه) برای انتزاع جزئیات فنی. به عنوان مثال، برای تعریف مرحله ای که رویدادها با فراخوانی سرویس های خارجی غنی می شوند، کاربران باید DSL زیر را بنویسند و فریم ورک بر اساس آن مدلی ایجاد می کند که توسط Flink اجرا می شود.
شکل 3. نمونه ای از غنی سازی در DSL در دلتا
چارچوب پردازش نه تنها منحنی یادگیری را کاهش میدهد، بلکه ویژگیهای رایج پردازش جریانی مانند تکرار، طرحوارهسازی، و انعطافپذیری و انعطافپذیری را برای حل مشکلات عملیاتی رایج فراهم میکند.
چارچوب پردازش Delta Stream از دو ماژول کلیدی، ماژول DSL & API و ماژول Runtime تشکیل شده است. ماژول DSL & API APIهای DSL و UDF (User-Defined-Function) را فراهم می کند تا کاربران بتوانند منطق پردازش خود را بنویسند (مانند فیلتر کردن یا تبدیل). ماژول Runtime پیاده سازی یک تجزیه کننده DSL را ارائه می دهد که یک نمایش داخلی از مراحل پردازش در مدل های DAG ایجاد می کند. مؤلفه Execution مدل های DAG را برای مقداردهی اولیه عبارات Flink واقعی و در نهایت اجرای برنامه Flink تفسیر می کند. معماری فریمورک در شکل زیر نشان داده شده است.
شکل 4. معماری چارچوب پردازش جریان دلتا
این رویکرد چند مزیت دارد:
کاربران می توانند بدون نیاز به کاوش در ویژگی های Flink یا ساختار SPaaS بر منطق کسب و کار خود تمرکز کنند.
بهینه سازی را می توان به گونه ای انجام داد که برای کاربران شفاف باشد و خطاها بدون نیاز به تغییر در کد کاربر (UDF) برطرف شوند.
تجربه برنامه دلتا برای کاربران ساده شده است، زیرا این پلتفرم انعطاف پذیری و انعطاف پذیری را در اختیار کاربران قرار می دهد و انواع معیارهای دقیق را جمع آوری می کند که می تواند برای هشدارها استفاده شود.
استفاده تولید
دلتا بیش از یک سال است که در حال تولید است و نقش کلیدی در بسیاری از برنامه های استودیو نتفلیکس ایفا می کند. او به تیمها کمک کرد تا موارد استفاده مانند فهرستبندی جستجو، ذخیرهسازی دادهها و گردشهای کاری مبتنی بر رویداد را اجرا کنند. در زیر مروری بر معماری سطح بالای پلت فرم دلتا است.
شکل 5. معماری سطح بالای دلتا.
تقدیر و تشکر
مایلیم از افرادی که در ایجاد و توسعه دلتا در نتفلیکس نقش داشتند تشکر کنیم: آلن وانگ، چارلز ژائو، جبین یون، جاش اسنایدر، کاستوری چاترجی، مارک چو، اولوف جوهانسون، پیوش گویال، پراشانت رامداس، راغورام اونتی. Srinivasan، Sandeep Gupta، Steven Wu، Tharanga Gamaethige، Yun Wang و Zhenzhong Xu.