مقالات میهمان

یک میلیارد رکورد در ساعت

نگاهی به فرآیند مهاجرت داده‌های تحلیلی از MySQL به کلیک‌‌هوس

مقاله میهمان

این مقاله به قلم مسیح یگانه در رسانه ویرگول منتشر شده است و سایت مهندسی داده، با هدف به اشتراک گذاشتن مطالب مفید در حوزه پردازش داده آنرا بازنشر نموده است. تصویر ابتدای مقاله نیز از این منبع اخذ شده است.

در این پست بلاگ قصد داریم به بهانه مهاجرت (Migration) پایگاه داده (Database) زمان پخش کاربران یک استارت‌آپ پادکست کانادایی به سرور جدید، مرور کوتاهی بر راه حل انتخابی‌مان برای ذخیره این داده‌ها داشته باشیم و در کنار آن به معرفی اجمالی پایگاه داده ClickHouse و روش اعمال مهاجرت‌مان بپردازیم.

مقدمه

پس از تشکیل تیم هوشمندسازی و تلاش برای ارائه راه‌حل‌هایی برای هوشمندسازی سرویس با استفاده از مدل‌های یادگیری عمیق (Deep Learning)، مهم ترین نیازمندی، حجم عظیمی از داده بود که این مدل‌ها بتوانند بر اساس‌شان آموزش ببینند. داده‌های مختلفی از بخش‌های مختلف سایت/اپ می‌توان استخراج کرد که بتوان برای هوشمندسازی از آنها استفاده کرد؛ از نظرات کاربران برای پادکست‌ها گرفته تا جریان کلیک‌های کاربر در صفحه (که در پست دیگری در آینده به آن پرداخته خواهد شد). اما یکی از حیاتی‌ترین این داده‌ها، زمان پخش کاربران است که می‌توان با تخمین خوبی، به میزان رضایت کاربر از پادکست ترجمه شود و برای ارائه پادکست‌ها بر اساس سلیقه کاربر مورد استفاده قرار گیرد.

زمان پخش چند صد هزار نفر کاربر همزمان (Concurrent) سرویس، هر دقیقه به صورت متناوب از گوشی‌ها، کامپیوترها و تلویزیون‌ها و … به سمت سرورهای ما ارسال می‌شود که دریافت و ذخیره‌سازی آن به صورتی که حجم عظیم و سرعت بالای تولید آن، مشکلی برای ذخیره‌سازی و کوئری کردن بهینه داده‌ها ایجاد نکند، یکی از چالش‌های این پروژه بود که انتخاب یک پایگاه داده مناسب بخش مهمی از راه حل بود.

ما معتقدیم که یک راهکار نهایی (Silver Bullet) برای ذخیره و بازیابی همه انواع داده‌ها وجود ندارد و بر اساس شرایط مختلف مانند مورد استفاده (Use Case)، نوع داده، سرعت تولید داده، حجم داده، نسبت نوشتن به خواندن داده، زمان کوئری و … باید راهکار ذخیره‌سازی خاصی را انتخاب کرد. ما بر اساس شرایط از تکنولوژی‌های مختلفی استفاده می‌کنیم، از ذخیره‌سازی ساده به عنوان فایل‌های CSV برای آموزش (Training) برخی از مدل‌های هوش مصنوعی گرفته تا Redis برای داده‌های کوچک و Cache کردن داده‌ها، MySQL برای اطلاعات رابطه‌ای، MongoDB برای داده‌های بدون ساختار خاص، ElasticSearch برای داده‌هایی که نیاز به جستجوی تمام‌متن (Full-Text Search) دارند، Graylog برای ذخیره و مدیریت لاگ‌ها، Prometheus و Grafana برای ذخیره و نمایش اطلاعات پایش (Monitoring) سرویس‌ها، Kafka و KSQL برای ذخیره و پردازش جریان رخداد‌های سمت کاربر و …

فهرست برخی از ابزارها و سرویس‌های داده حجیم (Big Data) در سال ۲۰۲۰
فهرست برخی از ابزارها و سرویس‌های داده حجیم (Big Data) در سال ۲۰۲۰

معرفی پایگاه داده ClickHouse

پایگاه داده ClickHouse یک پایگاه داده ساختارمند (Structured) ستونی (Column-oriented) سریع برای پردازش تحلیلی آنلاین (OLAP) است که با دستورات SQL کار می‌کند و توسط Yandex ساخته و متن‌باز شده است.

برخی از ویژگی‌های ClickHouse:

  • ذخیره‌سازی ستونی: این شیوه ذخیره‌سازی با ایجاد ستون‌هایی با طول داده ثابت امکان دسترسی سریع مانند آرایه را ایجاد می‌کنند که در صورت اندیس‌گذاری (Indexing)، دسترسی را بسیار سریع می‌کنند. در این شیوه فقط ستون‌هایی که در کوئری موجود هستند بررسی می‌شوند. از مزایای دیگر این روش می‌توان به محلی بودن داده‌ها (Locality of data) و امکان موازی سازی اشاره کرد، به این صورت که هر ستون را یک پروسس بررسی کند.
  • استفاده بهینه از انواع دیسک: ClickHouse طوری طراحی شده که به راحتی روی Hard Disk های معمولی کار کند ولی اگر SSD یا Ram اضافی در اختیارش قرار گیرد، بیشترین بهره را از آنها می‌برد. همچنین می‌توان قابلیت آرشیو کردن در آن تعریف کرد که داده‌های تازه‌تر و پرکاربردتر را در SSD ذخیره کند و در صورت قدیمی شدن داده‌ها، آنها را به HDD منتقل کند.
  • فشرده‌سازی داده‌ها: علاوه بر کدک (Codec) های ذخیره‌سازی عام‌منظور (مثل LZ4, LZHC و ZSTD)، برای داده‌هایی با نوع خاص از کدک‌های خاص منظور دیگر همچون Delta, DoubleDelta, Gorilla و T64 پشتیبانی می‌کند.
  • پردازش برداری: در صورت پشتیبانی CPU از دستورات SIMD یا Single Instruction Multiple Data همچون SSE4.2 از آن بهره می‌گیرد تا پردازش را با سرعت بیشتری انجام دهد.
  • پردازش موازی: از تمام هسته (Core) های CPU بهره می‌برد.
  • پردازش توزیع‌شده: در صورت اختصاص بیش از یک سرور، از قابلیت پردازش توزیع‌شده روی همه سرورها بهره می‌برد.
  • پشتیبانی از SQL: به دلیل آشنایی دراز مدت افراد تیم با SQL و موجود بودن ابزارهای فراوان برای کار کردن با آن، این قابلیت باعث تطبیق سریعتر تیم با این پایگاه داده می‌شود.
  • قابلیت یکپارچه‌سازی (Integrity) بالا: قابلیت اتصال و یکپارچه‌سازی به پایگاه داده‌های دیگر مثل MySQL، سیستم‌های پردازش جریان (Stream Processing) مثل Kafka و … به طوری که این اتصالات در پایگاه داده به عنوان یک جدول دیده می‌شوند و می‌توان با آن عملیات‌های فراوانی از جمله Join انجام داد.
  • داده‌های تغییر ناپذیر (Immutable Data): قابلیت ویرایش داده‌ها در ClickHouse به صورت ساده وجود ندارد و این ویژگی امکان استفاده از پایگاه داده بدون قفل (Locking) را ایجاد می‌کند.
  • ذخیره‌سازی فیزیکی داده‌ها روی دیسک به صورت مرتب شده بر اساس کلید اصلی
  • پشتیبانی از تکثیر داده‌ها (Replication) در عین حفظ یکپارچگی (Integrity) آن

این تصاویر برای درک بهتر تفاوت پردازش کوئری پایگاه داده ستونی در مقابل ردیفی گویا هستند:

پردازش کوئری در پایگاه داده ردیفی
پردازش کوئری در پایگاه داده ردیفی
پردازش کوئری در پایگاه داده ستونی
پردازش کوئری در پایگاه داده ستونی

این پایگاه داده تفاوت‌هایی با پایگاه داده‌های سنتی دارد که در ابتدا می‌تواند گیج کننده باشد. به طور مثال:

  • قابلیت تعریف قید (Constraint) یکتا (Unique) وجود ندارد.
  • کلید اصلی وجود ندارد و در شرایطی Sorting Key نقش آن را ایفا می‌کند.
  • قابلیت ویرایش به راحتی وجود ندارد (وجود دارد ولی به دلیل پرهزینه بودن این عملیات، ترجیحاً استفاده نمی‌شوند) و برای بروز نگه داشتن داده‌های ویرایش شده باید از موتور (Engine) خاصی از جداول استفاده شود.
  • داده‌ها در تمام مدت نهایی نیستند و در مورد زمان نهایی شدن آن نمی‌توان با قاطعیت صحبت کرد.

دو مورد آخر نیاز به توضیح دارند چون مفاهیم جدیدی نسبت به پایگاه داده‌های سنتی هستند. ClickHouse برای ذخیره‌سازی جداول، موتورهای مخلفی را معرفی کرده که از خانواده MergeTree هستند که ایده پشت آن، همانند LSM است و به این صورت کار می‌کند که داده‌های جدید در دسته‌هایی (Batch) به پایگاه داده وارد می‌شوند و در هنگام ورود در Log هایی نگه داشته می‌شوند. در این مرحله داده‌ها مرتب شده نیستند ولی ترتیب آنها را زمان ورود داده‌ها مشخص می‌کند.

ورود داده‌ها به ClickHouse
ورود داده‌ها به ClickHouse

سپس این بخش از داده‌های جدید با Sorting Key مرتب می‌شوند و منتظر ادغام شدن (Merge) می‌شود.

داده‌های جدید در انتظار ادغام
داده‌های جدید در انتظار ادغام

سپس در زمان نامعلومی* در پس‌زمینه، این بخش‌های با هم ادغام می‌شوند و تغییرات لازم روی داده‌ها اعمال می‌شود و بر اساس Sorting Key مرتب و نهایی می‌شوند.

داده‌هایی که در پس‌زمینه ادغام می‌شوند
داده‌هایی که در پس‌زمینه ادغام می‌شوند

در این مرحله داده‌ها در شکل نهایی ثبت شدند و این عملیات برای دسته‌های بعدی تکرار می‌شود.

داده‌های نهایی شده در ClickHouse
داده‌های نهایی شده در ClickHouse

توسط این مکانیزم، ClickHouse می‌تواند بدون نیاز به قفل کردن، داده‌ها را بروز نگه دارد و در هر لحظه به سریعترین حالت ممکن به کوئری‌ها پاسخ دهد. اما برای روشن‌تر شدن شیوه بروز رسانی داده‌های تغییر یافته، باید با سایر اعضای خانواده MergeTree آشنا شویم:

  • موتور ReplaceingMergeTree: این نوع جدول، در هنگام عملیات ادغام، آخرین نسخه داده‌هایی که Sorting Key یکسان دارند را نگه می‌دارد و بقیه را حذف می‌کند. در زمان تعریف جدول باید یک Field را مشخص کرد که از روی آن بتوان نسخه جدیدتر را تشخیص داد (به طور مثال Field زمان ورود داده).
  • موتور SummingMergeTree: این نوع جدول، در هنگام عملیات ادغام، Field های مشخص شده داده‌های مختلف که Sorting Key یکسان دارند را با یکدیگر جمع می‌کند. در زمان تعریف جدول باید این Field ها را مشخص کرد. اگر مشخص نشود، تمام فیلد‌های عددی جمع می‌شوند.
  • موتور CollapsingMergeTree: در این نوع جدول باید یک فیلد علامت (Sign) تعریف شود که فقط مقدار ۱ و ۱- می‌گیرد و در هنگام عملیات ادغام، داده‌هایی که Sorting Key یکسان دارند و یک بار با علامت ۱ و یک بار با علامت ۱- موجود باشند را حذف می‌کند.
  • موتور VersionedCollapsingMergeTree: این نوع جدول، دقیقاً مشابه CollapsingMergeTree است با این تفاوت که یک Field نسخه (Version) نیز به آن اضافه می‌شود و فقط داده‌های هم‌نسخه با هم مقایسه می‌شوند.
  • موتور AggregatingMergeTree: در این نوع جدول بیشترین قابلیت‌ها وجود دارد و می‌توان مشخص کرد داده‌هایی که Sorting Key یکسان دارند را با چه فرمولی ادغام نماید. به طور مثال می‌توان مشخص کرد که مقدار یک فیلد را با مقدار‌های قبلی جمع کند، یکی را تفریق کند، در یکی بیشینه (Maximum) حساب کند، در یکی آخرین مقدار* دیده شده را نگه دارد و …

توسط این موتورها، ClickHouse می‌تواند بدون نیاز به قفل یا ارائه عملیات Update، داده‌ها را فقط با عملیات Insert بروز نگه دارد.

برای آشنایی بیشتر با پایگاه داده ClickHouse به وب‌سایت رسمی یا مستندات آن مراجعه کنید.

دلایل انتخاب ClickHouse و تجربیات ما از آن

ما در تیم جوان هوشمندسازی، در اولین روزهای کاری سال ۱۳۹۹ (حدود ۹ ماه پیش از نگارش این پست) پایگاه داده ClickHouse را در سرورهای شرکت راه‌اندازی کردیم و تا زمان نگارش این پست، بیش از یک میلیارد ردیف ادغام شده از داده‌های پخش روزانه کاربران جمع‌آوری کردیم. این داده‌ها علاوه بر خوراک رسانی به مدل‌های هوش مصنوعی، مصارف آماری دیگری هم برای ما داشتند. به طور مثال برای تست‌های A/B، تحلیل‌های BI و …

برخی از دلایلی که ما این پایگاه داده را انتخاب کردیم:

  • ویژگی‌هایی که ClickHouse ارائه می‌کند نه تنها برای مدل‌های هوش مصنوعی ما مناسب است، بلکه نیازهای دیگر ما از جمله مصارف آماری را برطرف می‌کند.
  • سرعت، سرعت و سرعت. هم کوئری‌هایی که برای مدل‌های هوش مصنوعی خوراک آماده می‌کنند، هم کوئری‌های آماری ما بسیار کوئری‌های پیچیده‌ای هستند که در RDBMS های سنتی چندین دقیقه زمان نیاز دارند اما در ClickHouse با وجود نرخ ورود اطلاعات پخش که در روز به ۳ هزار ردیف در ثانیه می‌رسد، این کوئری‌ها در چند میلی‌ثانیه اجرا می‌شوند. به عنوان نمونه اگر این یک میلیارد ردیف اطلاعات پخش را با اطلاعات پادکست‌ها Join کنیم و با کاربر و پادکست Group کنیم و با Having آنهایی که بیشتر از درصد خاصی از پادکست را دیده اند جدا کنیم و لیستی Comma Separate شده از آن بسازیم، در ClickHouse حدود ۲۰ ثانیه طول می‌کشد. این عدد در MySQL بالای یک ساعت است.
  • با استفاده از خانواده MergeTree بسیاری از پیچیدگی‌های مرسوم برای زمان‌بندی ویرایش داده‌ها و قفل کردن ردیف‌ها عملاً از بین رفته و تنها با عملیات درج (Insert) می‌توانیم به همان نتیجه برسیم.
  • برخی از اطلاعات مورد نیاز در کوئری‌های ما (مانند اطلاعات پادکست‌ها) در پایگاه داده‌های دیگری مثل MySQL ذخیره شدند و ClickHouse قابلیت اتصال و حتی اجرای عملیات Join با MySQL را داراست و به عنوان نمونه با استفاده از این قابلیت بدون نیاز به همگام سازی (Synchronization) داده‌های MySQL و ClickHouse می‌توانیم درصد پخش و درصد پخش مفید را حساب کنیم.
  • فشرده‌سازی داده‌ها دلیل مهم دیگر انتخاب ما بود. به طوری که پس از مهاجرت از MySQL به ClickHouse حجم اشغال شده دیسک به یک دهم کاهش پیدا کرد.
  • این پایگاه داده از انواع خوشه بندی (Clustering) و پردازش توزیع شده پشتیبانی می‌کند و به راحتی تکثیر (Replicate) می‌شود و می‌توان قابلیت دسترسی بالا (High Availability) را از آن انتظار داشت.
  • با پشتیبانی از دستورات MySQL، سرعت تطبیق بالایی به تیم می‌دهد.
  • این پایگاه داده قبلاً امتحان خود را در Yandex Metrica پس داده است و این گزینه بسیاری از پایگاه داده‌های مشابه را به راحتی از دور خارج می‌کند زیرا هیچگاه زیر بار واقعی تست نشده‌اند (Battle Tested).

اما در کنار نقاط قوت فراوان، هم نقاط ضعفی وجود دارد، هم نکاتی که باید به آنها توجه شود:

  • ترجیح درج داده‌ها به صورت دسته‌ای و تا حد ممکن تجمیع نشده: در صورت درج داده‌ها به صورت تکی، کارایی ClickHouse به شدت پایین می‌آید و ترجیح می‌دهد داده‌ها را به صورت دسته‌ای دریافت کند. اما بهتر است در صورت امکان داده‌ها تجمیع نشده باشند و کاملاً خام وارد سیستم شوند و با استفاده از توابع فراوان موجود، در جدول دیگری تجمیع شوند تا اصل داده‌ها به صورت دست نخورده باقی بماند تا در صورت تغییر نیازمندی‌های کسب و کار، بتوان تجمیع جدیدی با قواعد دیگری روی آن اعمال شود.
  • انجام عملیات ادغام در زمان نامعلوم و عدم امکان برنامه‌ریزی برای آن: به نقل از مستندات رسمی:

Data deduplication occurs only during a merge. Merging occurs in the background at an unknown time, so you can’t plan for it. Some of the data may remain unprocessed. Although you can run an unscheduled merge using the OPTIMIZE query, don’t count on using it, because the OPTIMIZE query will read and write a large amount of data.

  • عدم وجود تضمین برای پردازش تمام ردیف‌ها: در نقل قول قبل، به این موضوع نیز اشاره شده که ممکن است بعضی از ردیف‌ها بعد از ادغام حذف نشوند و برای درست کردن آن نمی‌توان روی final یا optimize هم حساب کرد چون کل سیستم را به شدت کند می‌کنند. البته با توجه به روابط منطقی داده‌ها می‌توان با استفاده از عملگرهایی مانند max یا sum داده‌های تجمیع نشده را عملاً بی اثر کرد.
  • پردازش بدون ترتیب ردیف‌ها: به دلیل پردازش موازی، داده‌ها به هیچ ترتیب خاصی پردازش نمی‌شوند و در نتیجه توابعی مثل «اولین»، «آخرین» و … نادقیق می‌شوند. بنابراین توابع first و last با نام‌های anyFirst و anyLast تعریف شده اند که مشخص کننده این مشکل باشند.
  • عدم پشتیبانی از تراکنش (Transaction): بنابر ذات OLAP بودن پایگاه داده، انتظار داشتن این قابلیت هم نمی‌رود.
  • مستندات ضعیف: برخی از مستندات رسمی ClickHouse نهایت یک پاراگراف متن هستند و هیچ اطلاعات خاصی ندارند. البته که همه مستندات به این شکل نیستند.

معماری سیستم استخراج و ذخیره‌سازی اطلاعات زمان پخش

معماری ساده شده سیستم ذخیره‌سازی اطلاعات زمان پخش
معماری ساده شده سیستم ذخیره‌سازی اطلاعات زمان پخش

معماری سیستم ذخیره سازی اطلاعات زمان پخش در حقیقت بسیار ساده است. پخش‌کننده (Player) هایی که در دستگاه‌های مختلف داریم به صورت متناوب هر دقیقه مجموع دقایق پخش و ثانیه فعلی پادکستی که کاربران در حال گوش کردن به آن هستند را به سرورهای ما ارسال می‌کنند که به واسطه یک HA Proxy به دست خوشه ای از یک کد نوشته شده به زبان Go می‌رسد که وظیفه اعتبارسنجی درخواست را دارد و در صورت معتبر تشخیص دادن، اطلاعات زمان پخش را به یک Redis منتقل می‌کند و در آن تجمیع می‌کند. سپس یک خوشه دیگر از کدهای به زبان Go به نام WALL·E دسته دسته اطلاعات پخش‌های کاربران را به ClickHouse ارسال می‌کنند. این اطلاعات در پایگاه داده ClickHouse در یک جدول از نوع SummingMergeTree جمع آوری می‌شدند که Field مربوط به دقیقه پخش را به صورت روزانه جمع می‌کرد. بنابراین در این مدت یک میلیارد ردیف داده کاربر-پادکست-روز داشتیم. این ساختار که تمام بخش‌های آن به دقت پایش می‌شود، به خوبی پاسخگوی نیازهای ما بود اما به دلایلی نیاز دیدیم که ساختار بهتری داشته باشیم و داده‌ها را مهاجرت دهیم.

یکی از دلایل مهاجرت این بود که این پایگاه داده برای ما در فاز تحقیقات و امکان‌سنجی و آشنایی بود و به همین دلیل روی یک ماشین مجازی (Virtual Machine) بالا آمده بود و حالا که حجم دیتای خوبی دارد و از پس تست‌های ما بر آمده، نیاز بود سرور اختصاصی خود را با دیسک قابل انبساط (Expansion) داشته باشد تا بنابر نیاز، افزایش یابد.

از دلایل دیگر، تغییر در Field های داده بود که بعضی دیگر کاربرد نداشتند، بعضی جدید اضافه شده بودند و بعضی نیاز به بهینه‌سازی بیشتری داشتند. به طور مثال Field هایی که مشخص شد مقدارهای نسبتاً ثابتی دارند را از نوع LowCardinality تعریف کردیم.

همچنین احساس نیاز به جدولی کردیم که تجمیع بیشتری از روی این جدول فعلی انجام دهد و به جای اطلاعات روزانه، اطلاعات پخش کلی کاربر را ثبت کند و Field هایی همچون درصد پخش داشته باشد. برای این مورد از Materialized View استفاده کردیم که به هنگام درج داده‌ها در جدول اصلی، تجمیع شده آن را در این جدول ثانویه اضافه می‌کند.

دلیل دیگر، بروزرسانی خود ClickHouse بود که در این مدت امکانات جدیدی اضافه کرده بود و بسیاری از مشکلات آن برطرف شده بود.

سناریوی مهاجرت

حالا که مطمئن بودیم مهاجرتی با این تعداد تغییر داریم، نیاز به سناریویی دقیق برای اجرای آن حس می‌شد که شامل چند بخش اساسی باشد:

  • بروزرسانی ClickHouse
  • انتقال داده‌های موجود به سرور جدید
  • انتقال داده‌های جداول با ساختار قدیم به جداول با ساختار جدید
  • حفظ یکپارچگی کل سیستم‌ها با نسخه جدید، انتقال نرم به سیستم جدید و وجود امکان بازگشت (Revert) در صورت بروز خطا
  • تغییر سرویس‌های استفاده کننده از ClickHouse برای اتصال به سرور جدید

ابتدا جدیدترین نسخه ای از ClickHouse که به اندازه کافی پایدار (Stable) باشد را انتخاب کردیم و تمام سیاهه تغییرات (Changelog) بین نسخه نصب شده قدیمی و نسخه جدید را به دقت مطالعه کردیم تا هر نوع ناسازگاری با داده‌های قدیمی را کشف کنیم که خوشبختانه مشکلی وجود نداشت.

در این مرحله در یک ماشین مجازی نسخه جدید را نصب و تنظیم و راه‌اندازی کردیم و سپس همه راه‌های موجود را امتحان کردیم تا بهترین را پیدا کنیم. به عنوان نمونه فایل‌های داده ClickHouse قدیمی را به ماشین مجازی جدید منتقل کردیم و جای فایل‌های قدیم قرار دادیم (با تمام عجیب بودن این روش، در مستندات ClickHouse تقریباً چنین روشی مطرح شده) و همه چیز به درستی کار کرد ولی راه درستی به نظر نمی‌رسید زیرا باید پایگاه داده سیستمی را هم منتقل می‌کردیم که انتقال آن بین دو نسخه از نظر ما درست نبود. روش‌های دیگر را هم امتحان کردیم ولی در نهایت ClickHouse-Copier را انتخاب کردیم. این کد نوشته شده به زبان Go در کنار مسیر داده‌های ClickHouse یک پوشه با نام backup ایجاد میکند و نسخه پشتیبان از داده‌های فعلی را به صورت Hard Link به داده‌های اصلی در آن ذخیره می‌کند که هم فضای اضافه نمی‌گیرد، هم به راحتی می‌توان فایل‌ها را به مسیر جدید منتقل کرد که در مورد استفاده ما با rsync انجام شد. اما در تمام مستندات پشتیبان‌گیری این پایگاه داده اشاره شده که نباید در زمان پشتیبان‌گیری، داده جدیدی در سیستم درج شود.

To get a consistent copy, the data in the source tables and partitions should not change during the entire process.

در معماری سیستم، سرویس WALL·E می‌تواند برای مدتی از کار بی‌افتد و مشکلی برای سیستم پیش نیاید، زیرا داده‌های در Redis تجمیع می‌شوند. اما این زمان نمی‌تواند زیاد باشد زیرا این Redis گنجایش نگهداری داده‌های زیاد را ندارد. پس زمان اجرای مهاجرت باید ساعتی انتخاب شود که سیستم کمترین ترافیک را دارد و از روی نمودار ترافیک، این بازه بین ساعت ۶ تا ۸ صبح است که می‌توان در آن سرویس WALL·E را متوقف کرد، مهاجرت را انجام داد و سپس آن را به کار انداخت.

توزیع زمانی تعداد کاربران آنلاین
توزیع زمانی تعداد کاربران آنلاین

برای انتقال داده‌ها از جداول با ساختار قدیم به جدید، نیاز بود یک کوئری دقیق INSERT INTO SELECT نوشته شود که تمام ملاحظات ساختار جدید را در نظر بگیرد و Field های اضافی را حذف کند، مقدار معقولی برای Field های جدید در نظر بگیرد و همزمان با اجرای Join روی جداول دیگر، داده‌هایی که موجود نبودند را پر کند.

اینها تغییرات مربوط به خود ClickHouse بود اما نیاز بود دو سرویس دیگر که با Go نوشته شده بودند هم تغییر کنند که ضمن حفظ سازگاری با حالت قبلی (Backward Compatibility)، بتوانند از پس درخواست‌ها از نوع جدید نیز برآیند تا بتوان مهاجرت نرمی را انجام داد و در صورت بروز هر نوع خطا بتوان به حالت قبل برگشت. اولین بخش واقعی مهاجرت، همین بخش بود که از مدت‌ها قبل از شروع مهاجرت، این دو سرویس به طوری تغییر کردند که از پس هر دو نوع درخواست برآیند و مشکلی برای آنها پیش نیاید.

مرحله آخر هم تغییر آدرس اتصال پایگاه داده سرویس‌هایی بود که از ClickHouse استفاده می‌کنند .

این عملیات دو بار به صورت صفر تا صد روی ماشین مجازی انجام شد و زمان بندی‌ها بدست آمد و تمام مشکلات دیده شد و تقریباً برای تمام مراحل راه حل ثانویه (Plan B) و راهکار برگشت به حالت قبل نوشته شد تا در زمان مهاجرت اصلی مشکلی بوجود نیاید که برای آن آمادگی وجود ندارد. همچنین در تمام مراحل باید پایش سیستم‌ها و خواندن دقیق Log ها انجام شود.

زمانبندی مراحل مهاجرت اصلی

ساعت ۰۷:۰۰ – سرویس WALL·E متوقف شد

ساعت ۰۷:۰۱ – ایجاد جداول جدید در ClickHouse جدید

ساعت ۰۷:۰۳ – شروع عملیات پشیبان‌گیری توسط ClickHouse-Copier

ساعت ۰۷:۰۵ – پایان پشتیبان‌گیری و شروع کپی داده‌های پشتیبان‌گیری شده به سرور جدید توسط rsync

ساعت ۰۷:۰۷ – پایان کپی گیری

ساعت ۰۷:۰۸ – برگرداندن (Restore) داده‌های پشتیبان‌گیری شده

ساعت ۰۷:۰۹ – شروع انتقال داده‌ها از جدول قدیم به جدید توسط کوئری INSERT INTO SELECT

ساعت ۰۷:۴۵ – پایان انتقال داده‌ها

Elapsed: 2194.532 sec. Processed 1.01 billion rows, 101.02 GB (461,970 rows/s., 46.03 MB/s.)

ساعت ۰۷:۴۶ – راه‌اندازی مجدد سرویس WALL·E و شروع تست‌ها (در Redis هیچ تجمع خاصی رخ نداد)

ساعت ۰۷:۵۰ – پایان تست‌های از قبل مشخص شده

ساعت ۰۷:۵۲ – خوشه سرویس Stats Gateway جدید بارگذاری شد و به ساختار جدید انتقال پیدا کرد

ساعت ۰۷:۵۳ – پایان موفقیت آمیز تمام تست‌های مشخص شده سیستم از صفر تا صد

ساعت ۰۷:۵۴ – پایش و رصد Log ها برای مشکلات غیر منتظره

ساعت ۰۷:۵۹ – پایان

منابع

http://mattturck.com/wp-content/uploads/2020/09/2020-Data-and-AI-Landscape-Matt-Turck-at-FirstMark-v1.pdf

https://clickhouse.tech/docs/en/

https://altinity.com/blog/clickhouse-materialized-views-illuminated-part-1

https://altinity.com/blog/2018/8/22/clickhouse-copier-in-practice

امتیاز کاربران: ۴٫۵۵ ( ۲ رای)

مجتبی بنائی

دانشجوی دکترای نرم‌افزار دانشگاه تهران (yun.ir/smbanaie)، مدرس دانشگاه و فعال در حوزه توسعه نرم‌افزار و مهندسی داده که تمرکز کاری خود را در چند سال اخیر بر روی مطالعه و تحقیق در حوزه کلان‌داده و زیرساخت‌های پردازش داده و تولید محتوای تخصصی و کاربردی به زبان فارسی و انتشار آنها در سایت مهندسی داده گذاشته است. مدیریت پروژه‌های نرم‌افزاری و طراحی سامانه‌های مقیاس‌پذیر اطلاعاتی از دیگر فعالیتهای صورت گرفته ایشان در چند سال گذشته است.

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

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

این سایت از اکیسمت برای کاهش هرزنامه استفاده می کند. بیاموزید که چگونه اطلاعات دیدگاه های شما پردازش می‌شوند.

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