Doordash.pdf
984.9 KB
شرکت DoorDash چگونه پلتفرم پردازش بلادرنگ خود را با Iceberg متحول کرد؟
شرکت DoorDash برای پردازش رویدادهای بلادرنگ خودش، یک پلتفرم استریم داخلی توسعه داده که امکان تصمیمگیری سریع و هوشمند را برای تیمهای تجاری فراهم میکند.
در ساعات اوج فعالیت، این پلتفرم با حجم بالایی از داده روبهرو میشود — بیش از ۳۰ میلیون پیام در هر ثانیه، معادل حدود ۵ گیگابایت داده در ثانیه که از سمت مشتریان، رانندگان (Dashers)، فروشندگان و اپلیکیشنهای داخلی DoorDash ارسال میشود.
ساختار اولیه به این صورت بود:
🧱دریافت و بافر دادهها با Kafka
🧱پردازش با Apache Flink
🧱ذخیره در Amazon S3
🧱 در نهایت، انتقال دادهها به Snowflake از طریق یک پایپلاین به نام Snowpie
اما این معماری در عمل با چند مشکل جدی مواجه شد:
⛔️هزینههای بالای Snowflake
⛔️دوبار نوشتن دادهها (هم در S3 و هم در Snowflake)
⛔️وابستگی به یک فروشنده خاص ( Snowflake)
برای حل این چالشها، DoorDash تصمیم گرفت به سراغ Apache Iceberg برود تا زیرساخت دادهای بلادرنگ خود را بازطراحی کند؛ راهحلی متنباز، مقیاسپذیر و مستقل از فروشنده.
خلاصه آنرا در PDF الصاق شده مشاهده کنید👆
شرکت DoorDash برای پردازش رویدادهای بلادرنگ خودش، یک پلتفرم استریم داخلی توسعه داده که امکان تصمیمگیری سریع و هوشمند را برای تیمهای تجاری فراهم میکند.
در ساعات اوج فعالیت، این پلتفرم با حجم بالایی از داده روبهرو میشود — بیش از ۳۰ میلیون پیام در هر ثانیه، معادل حدود ۵ گیگابایت داده در ثانیه که از سمت مشتریان، رانندگان (Dashers)، فروشندگان و اپلیکیشنهای داخلی DoorDash ارسال میشود.
ساختار اولیه به این صورت بود:
🧱دریافت و بافر دادهها با Kafka
🧱پردازش با Apache Flink
🧱ذخیره در Amazon S3
🧱 در نهایت، انتقال دادهها به Snowflake از طریق یک پایپلاین به نام Snowpie
اما این معماری در عمل با چند مشکل جدی مواجه شد:
⛔️هزینههای بالای Snowflake
⛔️دوبار نوشتن دادهها (هم در S3 و هم در Snowflake)
⛔️وابستگی به یک فروشنده خاص ( Snowflake)
برای حل این چالشها، DoorDash تصمیم گرفت به سراغ Apache Iceberg برود تا زیرساخت دادهای بلادرنگ خود را بازطراحی کند؛ راهحلی متنباز، مقیاسپذیر و مستقل از فروشنده.
خلاصه آنرا در PDF الصاق شده مشاهده کنید👆
اوج بلوغ تیمهای مهندسی داده: محیط Staging و چکلیست تغییرات دیتابیس 🔴
وقتی یه دستور ساده میتونه کل سیستم رو بخوابونه!
چند روز پیش یکی از دوستان تماس گرفت و گفت روی یک جدول بزرگ در ClickHouse دستور OPTIMIZE FINAL زده. جدول مربوط به دیتای اصلی سیستمشون بوده و چند میلیارد رکورد داشته. نتیجه؟ تمام CPUها پر شدن، کوئریهای عادی از کار افتادن و سیستم عملاً فلج شده. 🧨
اتفاقی که شاید برای خیلی از ما آشنا باشه. ولی پشت این اتفاق، یک نکته خیلی مهم هست:
🧑💻 ما باید عادت کنیم مثل مهندسان نرمافزار، محیطهای جدا برای تست و اجرا داشته باشیم.
🚫 دادههای حساس و عملیاتی هیچوقت نباید محل آزمایش باشن.
اینا چند تا نکته کلیدی هستن که هر مهندس داده باید رعایت کنه:
🔹 محیط staging جداگانه داشته باشیم که شبیه production باشه (نه لزوماً با همون حجم دیتا)
🔹 دیتا رو نمونهگیری (sample) کنیم و روی کپیها تست کنیم، نه روی دیتای اصلی
🔹 دستورات سنگین مثل OPTIMIZE, VACUUM, یا REINDEX رو اول روی محیط تست اجرا کنیم
🔹 حتماً از ابزارهای مانیتورینگ، لاگگیری و EXPLAIN استفاده کنیم قبل از اجرای کوئریهای پرهزینه 📊
✨ جادوی چکلیست 📝
قبل از اجرای هر عملیات دیتابیسی سنگین، باید یه چکلیست ساده ولی جدی داشته باشیم:
✅ تست انجام شده؟
✅ دیتای درگیر چقدره؟
✅ منابع مورد نیاز؟
✅ توقف اضطراری یا rollback چطوریه؟
✅ مانیتور فعال هست؟
✅ روی staging امتحان شده؟
چکلیستها نه فقط جلوی اشتباهات انسانی رو میگیرن، بلکه فرهنگ مسئولیتپذیری، نظم و آرامش به تیم میدن. 🧠
حتی برای بدترین سناریوها، اگر از قبل فکر شده باشه، میشه از فاجعه جلوگیری کرد. 🚨
چکلیستها تو مهندسی داده جادو میکنن.
#مهندسی_داده #DataEngineering #ClickHouse #StagingMatters #ChecklistMagic #DatabaseOps #ProductionReady
وقتی یه دستور ساده میتونه کل سیستم رو بخوابونه!
چند روز پیش یکی از دوستان تماس گرفت و گفت روی یک جدول بزرگ در ClickHouse دستور OPTIMIZE FINAL زده. جدول مربوط به دیتای اصلی سیستمشون بوده و چند میلیارد رکورد داشته. نتیجه؟ تمام CPUها پر شدن، کوئریهای عادی از کار افتادن و سیستم عملاً فلج شده. 🧨
اتفاقی که شاید برای خیلی از ما آشنا باشه. ولی پشت این اتفاق، یک نکته خیلی مهم هست:
🧑💻 ما باید عادت کنیم مثل مهندسان نرمافزار، محیطهای جدا برای تست و اجرا داشته باشیم.
🚫 دادههای حساس و عملیاتی هیچوقت نباید محل آزمایش باشن.
اینا چند تا نکته کلیدی هستن که هر مهندس داده باید رعایت کنه:
🔹 محیط staging جداگانه داشته باشیم که شبیه production باشه (نه لزوماً با همون حجم دیتا)
🔹 دیتا رو نمونهگیری (sample) کنیم و روی کپیها تست کنیم، نه روی دیتای اصلی
🔹 دستورات سنگین مثل OPTIMIZE, VACUUM, یا REINDEX رو اول روی محیط تست اجرا کنیم
🔹 حتماً از ابزارهای مانیتورینگ، لاگگیری و EXPLAIN استفاده کنیم قبل از اجرای کوئریهای پرهزینه 📊
✨ جادوی چکلیست 📝
قبل از اجرای هر عملیات دیتابیسی سنگین، باید یه چکلیست ساده ولی جدی داشته باشیم:
✅ تست انجام شده؟
✅ دیتای درگیر چقدره؟
✅ منابع مورد نیاز؟
✅ توقف اضطراری یا rollback چطوریه؟
✅ مانیتور فعال هست؟
✅ روی staging امتحان شده؟
چکلیستها نه فقط جلوی اشتباهات انسانی رو میگیرن، بلکه فرهنگ مسئولیتپذیری، نظم و آرامش به تیم میدن. 🧠
حتی برای بدترین سناریوها، اگر از قبل فکر شده باشه، میشه از فاجعه جلوگیری کرد. 🚨
چکلیستها تو مهندسی داده جادو میکنن.
#مهندسی_داده #DataEngineering #ClickHouse #StagingMatters #ChecklistMagic #DatabaseOps #ProductionReady
شرکت OpenAI چگونه کلاستر های کافکای خود را پایدار کرد و توان عملیاتی خود را ۲۰ برابر کرد؟ 🚀
در یک سال گذشته، OpenAI توان عملیاتی Kafka را در بیش از ۳۰ خوشه، بیست برابر افزایش داد و به پایداری خیرهکننده ۹۹.۹۹۹٪ (پنج ۹) دست یافت. در ادامه، به سه بخش کلیدی این تحول میپردازیم:
🟩 ۱. گروهبندی خوشهها (Cluster Groups)
چالش: با بیش از ۳۰ خوشه Kafka در محیطهای متفاوت (هر کدام با تنظیمات مخصوص، احراز هویتهای پراکنده و قوانین فایروال خاص خود)، استفاده از سیستم بسیار پیچیده شده بود. کاربران نمیدانستند برای ذخیره یا خواندن داده باید به کدام خوشه متصل شوند و سؤالات مکرری مثل «تاپیک X کجاست؟» زمان توسعه را تلف میکرد. اگر یکی از خوشهها از کار میافتاد، کاربران باید بهصورت دستی به خوشه دیگری مهاجرت میکردند، که هم وقتگیر بود و هم مستعد خطا.
راهحل: OpenAI خوشهها را به شکل گروههای خوشهای درآورد؛ یعنی مجموعهای از خوشهها که در یک منطقه جغرافیایی قرار دارند (مثلاً آمریکا یا اروپا) و با هم یک گروه منطقی را تشکیل میدهند. کاربران حالا با «تاپیکهای منطقی» کار میکنند که بهصورت خودکار به تاپیکهای فیزیکی در خوشههای مختلف همان گروه متصل میشوند. این ساختار، زیرساخت پیچیده را از دید کاربران پنهان میکند و در صورت خرابی یک خوشه، خوشههای دیگر گروه جایگزین میشوند.
🟨 ۲. پراکسی تولیدکننده : Prism
چالش: پیش از این، هر اپلیکیشنی که داده تولید میکرد، مستقیماً به Kafka متصل میشد. این مدل باعث ایجاد تا ۵۰ هزار اتصال همزمان به هر بروکر میشد که منجر به مصرف شدید حافظه و کاهش پایداری میگردید. همچنین، توسعهدهندگان باید تنظیمات پیچیدهای مانند لیست بروکرها، پورتها، و احراز هویت را بهصورت دستی انجام میدادند. اگر یک خوشه از دسترس خارج میشد، برنامهها باید دستی به خوشه دیگری متصل میشدند، که منجر به خطا و قطعی میشد.
راهحل: OpenAI یک پراکسی به نام Prism ایجاد کرد که با استفاده از gRPC بهعنوان واسط ارتباطی، پیچیدگی Kafka را از کاربران پنهان میسازد. برنامهها فقط داده را به Prism میفرستند و Prism مسئول هدایت آن به بروکرهای مناسب است. در صورت خرابی یک خوشه، دادهها بهطور خودکار به خوشههای دیگر گروه ارسال میشود.
🟧 ۳. پراکسی مصرفکننده : uForwarder
چالش: مصرفکنندگان Kafka هم با مشکلاتی مشابه روبهرو بودند. برنامهها باید بهصورت دستی تنظیمات Kafka، انتخاب خوشه، مدیریت offset و احراز هویت را انجام میدادند. این فرآیند زمانبر و مستعد خطا بود. از طرف دیگر، مدل pull سنتی Kafka برای خواندن دادهها، موجب تأخیر و محدودیت در مصرف همزمان میشد. در صورت خرابی خوشهها، اتصال مجدد مصرفکنندگان به صورت دستی نیاز بود، که کارآمد نبود.
راهحل: OpenAI از uForwarder (یک پروژه متنباز از Uber) بهره گرفت که مدل مصرف را از pull به push تغییر میدهد. در این مدل، uForwarder خودش دادهها را از Kafka دریافت کرده و به اپلیکیشنها تحویل میدهد. این پراکسی ویژگیهای پیشرفتهای دارد مثل: بازارسال خودکار، صف پیامهای ناموفق (DLQ)، مصرف همزمان از چند خوشه، و موازیسازی پیشرفته. همچنین از مشکلاتی مثل Head-of-Line Blocking جلوگیری میکند.
نتیجه: مصرفکنندگان میتوانند بدون دانش خاصی از Kafka دادهها را دریافت کنند؛ توسعه آسانتر، پایداری بالاتر و عملکرد مقیاسپذیرتر حاصل شد.
منبع:
https://lnkd.in/dVpS5ZaD
در یک سال گذشته، OpenAI توان عملیاتی Kafka را در بیش از ۳۰ خوشه، بیست برابر افزایش داد و به پایداری خیرهکننده ۹۹.۹۹۹٪ (پنج ۹) دست یافت. در ادامه، به سه بخش کلیدی این تحول میپردازیم:
🟩 ۱. گروهبندی خوشهها (Cluster Groups)
چالش: با بیش از ۳۰ خوشه Kafka در محیطهای متفاوت (هر کدام با تنظیمات مخصوص، احراز هویتهای پراکنده و قوانین فایروال خاص خود)، استفاده از سیستم بسیار پیچیده شده بود. کاربران نمیدانستند برای ذخیره یا خواندن داده باید به کدام خوشه متصل شوند و سؤالات مکرری مثل «تاپیک X کجاست؟» زمان توسعه را تلف میکرد. اگر یکی از خوشهها از کار میافتاد، کاربران باید بهصورت دستی به خوشه دیگری مهاجرت میکردند، که هم وقتگیر بود و هم مستعد خطا.
راهحل: OpenAI خوشهها را به شکل گروههای خوشهای درآورد؛ یعنی مجموعهای از خوشهها که در یک منطقه جغرافیایی قرار دارند (مثلاً آمریکا یا اروپا) و با هم یک گروه منطقی را تشکیل میدهند. کاربران حالا با «تاپیکهای منطقی» کار میکنند که بهصورت خودکار به تاپیکهای فیزیکی در خوشههای مختلف همان گروه متصل میشوند. این ساختار، زیرساخت پیچیده را از دید کاربران پنهان میکند و در صورت خرابی یک خوشه، خوشههای دیگر گروه جایگزین میشوند.
🟨 ۲. پراکسی تولیدکننده : Prism
چالش: پیش از این، هر اپلیکیشنی که داده تولید میکرد، مستقیماً به Kafka متصل میشد. این مدل باعث ایجاد تا ۵۰ هزار اتصال همزمان به هر بروکر میشد که منجر به مصرف شدید حافظه و کاهش پایداری میگردید. همچنین، توسعهدهندگان باید تنظیمات پیچیدهای مانند لیست بروکرها، پورتها، و احراز هویت را بهصورت دستی انجام میدادند. اگر یک خوشه از دسترس خارج میشد، برنامهها باید دستی به خوشه دیگری متصل میشدند، که منجر به خطا و قطعی میشد.
راهحل: OpenAI یک پراکسی به نام Prism ایجاد کرد که با استفاده از gRPC بهعنوان واسط ارتباطی، پیچیدگی Kafka را از کاربران پنهان میسازد. برنامهها فقط داده را به Prism میفرستند و Prism مسئول هدایت آن به بروکرهای مناسب است. در صورت خرابی یک خوشه، دادهها بهطور خودکار به خوشههای دیگر گروه ارسال میشود.
🟧 ۳. پراکسی مصرفکننده : uForwarder
چالش: مصرفکنندگان Kafka هم با مشکلاتی مشابه روبهرو بودند. برنامهها باید بهصورت دستی تنظیمات Kafka، انتخاب خوشه، مدیریت offset و احراز هویت را انجام میدادند. این فرآیند زمانبر و مستعد خطا بود. از طرف دیگر، مدل pull سنتی Kafka برای خواندن دادهها، موجب تأخیر و محدودیت در مصرف همزمان میشد. در صورت خرابی خوشهها، اتصال مجدد مصرفکنندگان به صورت دستی نیاز بود، که کارآمد نبود.
راهحل: OpenAI از uForwarder (یک پروژه متنباز از Uber) بهره گرفت که مدل مصرف را از pull به push تغییر میدهد. در این مدل، uForwarder خودش دادهها را از Kafka دریافت کرده و به اپلیکیشنها تحویل میدهد. این پراکسی ویژگیهای پیشرفتهای دارد مثل: بازارسال خودکار، صف پیامهای ناموفق (DLQ)، مصرف همزمان از چند خوشه، و موازیسازی پیشرفته. همچنین از مشکلاتی مثل Head-of-Line Blocking جلوگیری میکند.
نتیجه: مصرفکنندگان میتوانند بدون دانش خاصی از Kafka دادهها را دریافت کنند؛ توسعه آسانتر، پایداری بالاتر و عملکرد مقیاسپذیرتر حاصل شد.
منبع:
https://lnkd.in/dVpS5ZaD
Linkedin
OpenAI’s Kafka throughput grew 20x in the last year across 30+ clusters. | Stanislav Kozlovski
OpenAI’s Kafka throughput grew 20x in the last year across 30+ clusters.
Their setup achieves five 9s (99.999%).
Here’s how they did it 👇
〰️〰️〰️〰️
🟩 𝗖𝗹𝘂𝘀𝘁𝗲𝗿 𝗚𝗿𝗼𝘂𝗽𝘀
They group clusters into groups. Each cluster lives in a separate region.
Through an…
Their setup achieves five 9s (99.999%).
Here’s how they did it 👇
〰️〰️〰️〰️
🟩 𝗖𝗹𝘂𝘀𝘁𝗲𝗿 𝗚𝗿𝗼𝘂𝗽𝘀
They group clusters into groups. Each cluster lives in a separate region.
Through an…
https://virgool.io/divarengineering/-bhwoaodprld6
سفر تکامل نقشهی دیوار: داستان مهندسی پشت نمایش هوشمند میلیونها آگهی
وقتی به دنبال خانه یا ملک میگردید، «کجا بودن» آن شاید اولین و مهمترین سؤالی باشد که به ذهنتان میرسد. در پلتفرمی مثل دیوار که روزانه هزاران آگهی املاک در آن ثبت میشود، نمایش این حجم از اطلاعات مکانی به شکلی کارآمد و قابل فهم، یک چالش بزرگ است. ما در دیوار مسیری پر فراز و نشیب را برای بهبود نمایش آگهیها روی نقشه طی کردهایم؛ از نمایش سادهی نقطهای تا سیستمهای هوشمند کلاستربندی داینامیک. این مقاله داستان این تکامل فنی و تصمیمهایی است که در این راه گرفتهایم. هدف ما نه تنها ارائهی یک تجربهی کاربری روان، بلکه ساخت زیرساختی پایدار و مقیاسپذیر برای آیندهی نقشهی دیوار بوده است.
——-
این مقاله خواندنی را از آدرس بالا مطالعه کنید .
سفر تکامل نقشهی دیوار: داستان مهندسی پشت نمایش هوشمند میلیونها آگهی
وقتی به دنبال خانه یا ملک میگردید، «کجا بودن» آن شاید اولین و مهمترین سؤالی باشد که به ذهنتان میرسد. در پلتفرمی مثل دیوار که روزانه هزاران آگهی املاک در آن ثبت میشود، نمایش این حجم از اطلاعات مکانی به شکلی کارآمد و قابل فهم، یک چالش بزرگ است. ما در دیوار مسیری پر فراز و نشیب را برای بهبود نمایش آگهیها روی نقشه طی کردهایم؛ از نمایش سادهی نقطهای تا سیستمهای هوشمند کلاستربندی داینامیک. این مقاله داستان این تکامل فنی و تصمیمهایی است که در این راه گرفتهایم. هدف ما نه تنها ارائهی یک تجربهی کاربری روان، بلکه ساخت زیرساختی پایدار و مقیاسپذیر برای آیندهی نقشهی دیوار بوده است.
——-
این مقاله خواندنی را از آدرس بالا مطالعه کنید .
ویرگول
سفر تکامل نقشهی دیوار: داستان مهندسی پشت نمایش هوشمند میلیونها آگهی
وقتی به دنبال خانه یا ملک میگردید، «کجا بودن» آن شاید اولین و مهمترین سؤالی باشد که به ذهنتان میرسد. در پلتفرمی مثل دیوار که روزانه هزار…
چگونه با ClickHouse زیرساخت کمپین بازاریابی شخصیسازیشده اسنپ! مارکت را طراحی کردیم؟ 🎯
این مقاله ترجمه ای است از :
https://medium.com/@prmbas/clickhouse-in-the-wild-an-odyssey-through-our-data-driven-marketing-campaign-in-q-commerce-93c2a2404a39
در جریان طراحی و اجرای کمپین «سوپرسنج» در اسنپ! مارکت، هدف ما خلق تجربهای متفاوت و هوشمندانه برای میلیونها کاربر بود؛ تجربهای که با تحلیل رفتار خرید واقعی مشتریان و بهرهگیری از الگوریتمهای یادگیری ماشین و هوش مصنوعی، بهشکل شخصی و سرگرمکننده ارائه میشد.
برای رسیدن به این هدف، طراحی یک زیرساخت دادهای مقیاسپذیر و تحلیلی ضروری بود؛ زیرساختی که بتواند حجم بالایی از دادههای سفارش، محصول، رفتار مشتری و تعاملات کمپین را در زمان محدود پردازش کند. ما تصمیم گرفتیم از #ClickHouse بهعنوان موتور پردازش تحلیلی اصلی استفاده کنیم.
📦 کمپین سوپرسنج: شخصیت خرید شما چیست؟
سوپرسنج یک کمپین خلاقانه و دادهمحور بود که با الهام از تستهای #MBTI، پرترهای طنز و شخصیسازیشده از کاربران اسنپ! مارکت ارائه میداد. این پرتره با تحلیل واقعی رفتار خرید مشتریان و بهکمک هوش مصنوعی تولید میشد.
اجزای اصلی کمپین:
🧑💼 پروفایل شخصی: آمارهایی مثل تاریخ اولین سفارش، مجموع کوپنهای استفادهشده و مسافت طیشده توسط پیکها
🧠 تست شخصیت خرید: تخصیص تیپهای شخصیتی بر اساس رفتار خرید (مثلاً «تنقلاتی راحتطلب» یا «قهوهدوست اقتصادی»)
🤖 محتوای طنز با هوش مصنوعی: تولید دیالوگ و داستان کوتاه بر اساس دادههای مشتری، با استفاده از LLMها
🔧 ساختار فنی: معماری چندلایه پردازش داده
برای پشتیبانی از چنین تجربهای، ما لایههای مختلفی از پردازش داده را در نظر گرفتیم:
🟫 لایه برنز : دادههای خام شامل سفارشها، اطلاعات کاربران، و متادیتاهای مربوط به محصولات در بازهای چهارساله
🟪 لایه نقره: پردازشهای تحلیلی میانی با استفاده از SQL و Python، ذخیرهشده بهشکل فایلهای Parquet
🟨 لایه طلا : خروجی نهایی شامل برچسبهای شخصیتی، آمار اختصاصی، و JSONهایی که به مدلهای زبانی برای تولید متن تزریق میشد
⚠️ چالش فنی: جوینهای سنگین و مصرف بالای حافظه
در مراحل اولیه، از الگوریتم پیشفرض Join در ClickHouse استفاده کردیم. اما با رشد دادهها و افزایش پیچیدگی کوئریها، مصرف حافظه سر به فلک کشید و در مواردی منجر به کرش شد.
برای حل این مشکل، با بررسی دقیق مستندات ClickHouse و رفتارهای کوئری، به الگوریتم partial_merge مهاجرت کردیم.
✅ نتیجه:
💥پایداری بیشتر در کوئریهای سنگین
💥کاهش چشمگیر استفاده از RAM
💥حذف نیاز به ایجاد جداول staging برای ترکیب دادهها
🚀 قابلیتهای ویژه ClickHouse که بهرهبرداری کردیم:
🌱 خواندن مستقیم فایلهای Parquet از مسیرهای محلی و شبکهای
🌱 توابع تحلیلی سطح بالا مانند argMax, groupArray, corr, toStartOfInterval
🌱 پشتیبانی بومی از JSON و آرایهها برای ذخیره دادههای ساختیافته در فرمت نیمهساختیافته
🌱 اتصال Real-time به داشبورد Grafana برای مشاهده نتایج و رفتار کمپین در زمان اجرا
📈 نتیجه نهایی
کمپین سوپرسنج با مشارکت بیش از ۱۰۰ هزار کاربر در مدتی کوتاه، بهعنوان یکی از موفقترین کمپینهای دادهمحور در صنعت تجارت الکترونیک ایران شناخته شد. این موفقیت تنها به دلیل طراحی خلاقانه و محتوای طنز نبود؛ بلکه به لطف یک زیرساخت دادهای دقیق، سریع، و بومیسازیشده به دست آمد — زیرساختی که علیرغم نبود زیرساختهای ابری بینالمللی، بر پایه ابزارهای متنباز مانند ClickHouse توسعه یافت و در مقیاس وسیع بهکار گرفته شد.
این مقاله ترجمه ای است از :
https://medium.com/@prmbas/clickhouse-in-the-wild-an-odyssey-through-our-data-driven-marketing-campaign-in-q-commerce-93c2a2404a39
در جریان طراحی و اجرای کمپین «سوپرسنج» در اسنپ! مارکت، هدف ما خلق تجربهای متفاوت و هوشمندانه برای میلیونها کاربر بود؛ تجربهای که با تحلیل رفتار خرید واقعی مشتریان و بهرهگیری از الگوریتمهای یادگیری ماشین و هوش مصنوعی، بهشکل شخصی و سرگرمکننده ارائه میشد.
برای رسیدن به این هدف، طراحی یک زیرساخت دادهای مقیاسپذیر و تحلیلی ضروری بود؛ زیرساختی که بتواند حجم بالایی از دادههای سفارش، محصول، رفتار مشتری و تعاملات کمپین را در زمان محدود پردازش کند. ما تصمیم گرفتیم از #ClickHouse بهعنوان موتور پردازش تحلیلی اصلی استفاده کنیم.
📦 کمپین سوپرسنج: شخصیت خرید شما چیست؟
سوپرسنج یک کمپین خلاقانه و دادهمحور بود که با الهام از تستهای #MBTI، پرترهای طنز و شخصیسازیشده از کاربران اسنپ! مارکت ارائه میداد. این پرتره با تحلیل واقعی رفتار خرید مشتریان و بهکمک هوش مصنوعی تولید میشد.
اجزای اصلی کمپین:
🧑💼 پروفایل شخصی: آمارهایی مثل تاریخ اولین سفارش، مجموع کوپنهای استفادهشده و مسافت طیشده توسط پیکها
🧠 تست شخصیت خرید: تخصیص تیپهای شخصیتی بر اساس رفتار خرید (مثلاً «تنقلاتی راحتطلب» یا «قهوهدوست اقتصادی»)
🤖 محتوای طنز با هوش مصنوعی: تولید دیالوگ و داستان کوتاه بر اساس دادههای مشتری، با استفاده از LLMها
🔧 ساختار فنی: معماری چندلایه پردازش داده
برای پشتیبانی از چنین تجربهای، ما لایههای مختلفی از پردازش داده را در نظر گرفتیم:
🟫 لایه برنز : دادههای خام شامل سفارشها، اطلاعات کاربران، و متادیتاهای مربوط به محصولات در بازهای چهارساله
🟪 لایه نقره: پردازشهای تحلیلی میانی با استفاده از SQL و Python، ذخیرهشده بهشکل فایلهای Parquet
🟨 لایه طلا : خروجی نهایی شامل برچسبهای شخصیتی، آمار اختصاصی، و JSONهایی که به مدلهای زبانی برای تولید متن تزریق میشد
⚠️ چالش فنی: جوینهای سنگین و مصرف بالای حافظه
در مراحل اولیه، از الگوریتم پیشفرض Join در ClickHouse استفاده کردیم. اما با رشد دادهها و افزایش پیچیدگی کوئریها، مصرف حافظه سر به فلک کشید و در مواردی منجر به کرش شد.
برای حل این مشکل، با بررسی دقیق مستندات ClickHouse و رفتارهای کوئری، به الگوریتم partial_merge مهاجرت کردیم.
-- changing join algorithm in the current CLI session
SET join_algortim = 'partial_merge';
-- data easlity stored in a parquet file
-- default path: /var/lib/clickhouse/user_files
INSERT INTO FUNCTION file('temp_data.parquet', Parquet)
SELECT *
FROM [db1].[table1] AS t1
LEFT JOIN [db2].[table2] AS t2 ON t1.[column1] = t2.[column2];
✅ نتیجه:
💥پایداری بیشتر در کوئریهای سنگین
💥کاهش چشمگیر استفاده از RAM
💥حذف نیاز به ایجاد جداول staging برای ترکیب دادهها
🚀 قابلیتهای ویژه ClickHouse که بهرهبرداری کردیم:
🌱 خواندن مستقیم فایلهای Parquet از مسیرهای محلی و شبکهای
🌱 توابع تحلیلی سطح بالا مانند argMax, groupArray, corr, toStartOfInterval
🌱 پشتیبانی بومی از JSON و آرایهها برای ذخیره دادههای ساختیافته در فرمت نیمهساختیافته
🌱 اتصال Real-time به داشبورد Grafana برای مشاهده نتایج و رفتار کمپین در زمان اجرا
📈 نتیجه نهایی
کمپین سوپرسنج با مشارکت بیش از ۱۰۰ هزار کاربر در مدتی کوتاه، بهعنوان یکی از موفقترین کمپینهای دادهمحور در صنعت تجارت الکترونیک ایران شناخته شد. این موفقیت تنها به دلیل طراحی خلاقانه و محتوای طنز نبود؛ بلکه به لطف یک زیرساخت دادهای دقیق، سریع، و بومیسازیشده به دست آمد — زیرساختی که علیرغم نبود زیرساختهای ابری بینالمللی، بر پایه ابزارهای متنباز مانند ClickHouse توسعه یافت و در مقیاس وسیع بهکار گرفته شد.
Medium
ClickHouse in the Wild: An Odyssey Through Our Data-Driven Marketing Campaign in Q-Commerce
Key visual of “SuperSanj” campaign, ran by Snapp! Market
ساخت ETL با SQL؛ ساده، سریع و بدون وابستگی به زیرساخت سنگین
در دنیای مهندسی داده، ساخت یک فرآیند ETL معمولاً نیازمند زیرساختهایی پیچیده، ابزارهایی سنگین و دانش فنی نسبتاً بالا بود. اما اکنون، با ظهور ابزارهای سبک و ماژولار مانند DuckDB، میتوان همین فرآیند را با چند خط SQL ساده انجام داد؛ بدون نیاز به نصب پلتفرمهای حجیم یا نوشتن کدهای پیچیده.
🎬 فرض کنیم با دادههای جریانی سروکار دارید
کافکا یکی از متداولترین ابزارها برای مدیریت دادههای جریانی (streaming data) است. معمولاً برای خواندن این دادهها و انجام پردازش، به ابزارهایی مانند Apache Flink، Spark Streaming یا سیستمهای مدیریت جریان نیاز داریم.
اما حالا با افزونهای به نام Tributary برای DuckDB، میتوان مستقیماً از Kafka دادهها را خواند، پردازش کرد و به مقصد موردنظر نوشت – تماماً با SQL.
🧩 افزونه Tributary چه کاری انجام میدهد؟
افزونه Tributary یک افزونه رسمی برای DuckDB است که امکان اتصال مستقیم به Kafka را فراهم میکند. این افزونه با تابع tributary_scan_topic پیامهای Kafka را بهصورت یک جدول قابل خواندن در اختیار شما میگذارد:
در اینجا، دادههای Kafka بهصورت real-time به DuckDB وارد میشوند و آماده تحلیل، فیلتر یا انتقال به سیستمهای دیگر هستند.
🧩 اما خود DuckDB چیست؟
در دنیای مهندسی داده و تحلیل، ابزارهای سبک و مستقل نقش پررنگتری پیدا کردهاند. یکی از مهمترین این ابزارها، DuckDB است٫ یک پایگاه داده تحلیلی درونفرایندی (in-process analytical database) که میتوان آن را مشابه SQLite اما مخصوص تحلیلهای ستونی و پیچیده دانست.
در حالیکه SQLite برای تراکنشهای کوچک در موبایل و نرمافزارهای تعبیهشده طراحی شده، DuckDB برای تحلیلهای ستونی، پردازش سریع فایلهای Parquet و اجرای کوئریهای تحلیلی سنگین ساخته شده است — آن هم بدون نیاز به سرور یا نصب پیچیده..
💡 کاربردهای عملی این رویکرد چیست؟
✅ تحلیل سریع روی پیامهای Kafka بدون نیاز به سیستمهای تحلیلی سنگین.
✅ ساخت pipelineهای سبک ETL با استفاده از SQL.
✅ انتقال دادهها از Kafka به فایلهای Parquet، PostgreSQL، یا حتی ارسال مجدد به Kafka (با افزونههای مکمل مانند duckdb_kafka_sink).
⚙️ نحوه استفاده و راهاندازی
نصب و راهاندازی Tributary در DuckDB بسیار ساده است:
سپس تنها با چند خط SQL، به Kafka متصل میشوید و دادههای جریانی را پردازش میکنید.
🚀 یک گام به سوی آیندهی سادهتر در مهندسی داده
ابزارهایی مانند DuckDB به همراه افزونههایی مانند Tributary، نمایانگر جهتی هستند که دنیای داده به آن حرکت میکند: سادگی، ماژولار بودن، و استفاده حداکثری از زبان استاندارد SQL.
دیگر لازم نیست برای پیادهسازی یک ETL ساده، سیستمهای بزرگ و پیچیده مستقر شود. گاهی یک فایل SQL کافیست.
در صورتی که علاقهمند به ساخت ETL سبکوزن با SQL هستید یا به دنبال راهحلی ساده برای تحلیل جریان دادهها در Kafka میگردید، پیشنهاد میکنم حتماً نگاهی به افزونه Tributary بیندازید.
https://query.farm/duckdb_extension_tributary.html
پ.ن. عکس و ایده اصلی پست از مطلب زیر در لینکدین گرفته شده است:
https://www.linkedin.com/posts/rusty-conover_kafka-duckdb-streamingdata-activity-7339109125852676096-3QWs
در دنیای مهندسی داده، ساخت یک فرآیند ETL معمولاً نیازمند زیرساختهایی پیچیده، ابزارهایی سنگین و دانش فنی نسبتاً بالا بود. اما اکنون، با ظهور ابزارهای سبک و ماژولار مانند DuckDB، میتوان همین فرآیند را با چند خط SQL ساده انجام داد؛ بدون نیاز به نصب پلتفرمهای حجیم یا نوشتن کدهای پیچیده.
🎬 فرض کنیم با دادههای جریانی سروکار دارید
کافکا یکی از متداولترین ابزارها برای مدیریت دادههای جریانی (streaming data) است. معمولاً برای خواندن این دادهها و انجام پردازش، به ابزارهایی مانند Apache Flink، Spark Streaming یا سیستمهای مدیریت جریان نیاز داریم.
اما حالا با افزونهای به نام Tributary برای DuckDB، میتوان مستقیماً از Kafka دادهها را خواند، پردازش کرد و به مقصد موردنظر نوشت – تماماً با SQL.
🧩 افزونه Tributary چه کاری انجام میدهد؟
افزونه Tributary یک افزونه رسمی برای DuckDB است که امکان اتصال مستقیم به Kafka را فراهم میکند. این افزونه با تابع tributary_scan_topic پیامهای Kafka را بهصورت یک جدول قابل خواندن در اختیار شما میگذارد:
SELECT * FROM tributary_scan_topic('clicks_topic', "bootstrap.servers" := 'localhost:9092');
در اینجا، دادههای Kafka بهصورت real-time به DuckDB وارد میشوند و آماده تحلیل، فیلتر یا انتقال به سیستمهای دیگر هستند.
🧩 اما خود DuckDB چیست؟
در دنیای مهندسی داده و تحلیل، ابزارهای سبک و مستقل نقش پررنگتری پیدا کردهاند. یکی از مهمترین این ابزارها، DuckDB است٫ یک پایگاه داده تحلیلی درونفرایندی (in-process analytical database) که میتوان آن را مشابه SQLite اما مخصوص تحلیلهای ستونی و پیچیده دانست.
در حالیکه SQLite برای تراکنشهای کوچک در موبایل و نرمافزارهای تعبیهشده طراحی شده، DuckDB برای تحلیلهای ستونی، پردازش سریع فایلهای Parquet و اجرای کوئریهای تحلیلی سنگین ساخته شده است — آن هم بدون نیاز به سرور یا نصب پیچیده..
💡 کاربردهای عملی این رویکرد چیست؟
✅ تحلیل سریع روی پیامهای Kafka بدون نیاز به سیستمهای تحلیلی سنگین.
✅ ساخت pipelineهای سبک ETL با استفاده از SQL.
✅ انتقال دادهها از Kafka به فایلهای Parquet، PostgreSQL، یا حتی ارسال مجدد به Kafka (با افزونههای مکمل مانند duckdb_kafka_sink).
⚙️ نحوه استفاده و راهاندازی
نصب و راهاندازی Tributary در DuckDB بسیار ساده است:
INSTALL tributary FROM community;
LOAD tributary;
سپس تنها با چند خط SQL، به Kafka متصل میشوید و دادههای جریانی را پردازش میکنید.
🚀 یک گام به سوی آیندهی سادهتر در مهندسی داده
ابزارهایی مانند DuckDB به همراه افزونههایی مانند Tributary، نمایانگر جهتی هستند که دنیای داده به آن حرکت میکند: سادگی، ماژولار بودن، و استفاده حداکثری از زبان استاندارد SQL.
دیگر لازم نیست برای پیادهسازی یک ETL ساده، سیستمهای بزرگ و پیچیده مستقر شود. گاهی یک فایل SQL کافیست.
در صورتی که علاقهمند به ساخت ETL سبکوزن با SQL هستید یا به دنبال راهحلی ساده برای تحلیل جریان دادهها در Kafka میگردید، پیشنهاد میکنم حتماً نگاهی به افزونه Tributary بیندازید.
https://query.farm/duckdb_extension_tributary.html
پ.ن. عکس و ایده اصلی پست از مطلب زیر در لینکدین گرفته شده است:
https://www.linkedin.com/posts/rusty-conover_kafka-duckdb-streamingdata-activity-7339109125852676096-3QWs