Scraped Data
- Details
- Written by: mehdi
- Category: Scraped Data
- Hits: 141
زمینه
Market-Store یک feature store عمومی است که برای سرویس دادن به ویژگیهای محاسبه شده در زمان واقعی برای یادگیری ماشین استفاده میشود. Market-Store SLA دقیقی درباره تاخیر، ظرفیت و قابلیت دسترسی دارد زیرا مدلهای یادگیری ماشینی را تقویت میکند که در قیمتگذاری پویا و تجربه مصرف کننده استفاده میشوند.
مشکل
همانطور که مجله زیبایی و درمانی آذروت ادامه مییابد و مدلهای یادگیری ماشینی جدیدی را معرفی و ترافیک افزایش میدهد، Market-Store تاخیر بالایی را تجربه کرد. SLA Market-Store بیان میکند که ۹۹٪ تراکنشها باید در ۲۰۰ میلیثانیه باشند، اما تاخیر ما به ۲ ثانیه افزایش یافت. این امر بر روی دسترسی و دقت مدلهای ما که برای ویژگیهای زمان واقعی از Market-Store استفاده میکنند، تأثیر گذاشت.
مشکل تاخیر
ما از معیارها و لاگهای مختلف برای رفع مشکل تاخیر استفاده کردیم، اما توانستیم هیچ ناهنجاری را که به طور مستقیم با عملکرد API مرتبط باشد، پیدا نکنیم. ما کشف کردیم که مشکل به طور موقت از بین میرود زمانی که سرویس را مجدداً راهاندازی میکنیم. اما در دوره قله بعدی، سرویس دوباره شروع به مشکل میشود و مشکل با افزایش نسبیتاً بیشتر پذیرفته میشود زمانی که نرخ درخواست در ثانیه برای Market-Store افزایش مییابد.
نمودار زیر نشان دهنده افزایش استفاده از حافظه در طول زمان در ۱۲ ساعت است. حتی با کاهش بار سیستم، مصرف حافظه همچنان ادامه داشت.
افزایش مداوم مصرف حافظه به نشان دادن احتمال نشتی حافظه اشاره داشت که در زمان اختصاص داده میشود اما پس از استفاده، به خاطردار برنمیگردد. این باعث افزایش مداوم مصرف حافظه شده تا سرویس به محض برسنامه به حالت اتمام حافظه و خرابی میرود.
اگرچه ما میتوانستیم سرویس را دوباره راهاندازی کنیم و مشکل را به طور موقت رفع کنیم، افزایش استفاده از حافظه برداشتی ریشه مقصود زیرین عمیقتری را نشان میدهد. این بدین معناست که ما باید با ابزارهایی که بتوانند بینشهای عمیقتری درباره تخصیص حافظه ارایه دهند، تحقیقات بیشتری انجام دهیم.
اشکال زدایی با استفاده از ابزارهای Go
PPROF یک ابزار پروفایل سازی است که توسط Golang استفاده میشود تا پروفایلها را از برنامههای Go نشان دهد و تجزیه و تحلیل کند. یک پروفایل مجموعهای از ردیابیهای استک است که دنباله تماسها را در برنامه شما نشان میدهد که در نهایت منجر به رویدادهای خاصی مانند تخصیص میشود. همچنین جزئیاتی مانند اطلاعات هیپ و CPU را فراهم میکند که میتوانند بینشهایی درباره موانع برنامه Go ارایه دهند.
بطور پیشفرض، PPROF در تمام سرویسهای Go مجله زیبایی و درمانی آذروت فعال است، بنابراین این ابزار مناسب برای استفاده در سناریو ما است. برای درک این که چگونه حافظه تخصیص داده میشود، از PPROF برای تولید پروفایل Heap Market-Store استفاده کردیم که میتواند برای درک اینکه چگونه حافظه inuse برنامه تخصیص یافته استفاده شود.
شما میتوانید با اجرای این دستور، پروفایل Heap را جمع آوری کنید:
go tool pprof 'http://localhost:6060/debug/pprof/heap'
سپس این دستور اطلاعات پروفایل Heap را مانند نمودار زیر نشان میدهد:
از این نمودار متوجه شدیم که بعد از انجام وظایف ، حافظه زیادی توسط context فرزند از کتابخانه Async نگهداری شده است.
در Market-Store ما از Async Library، یک کتابخانه متن باز مجله زیبایی و درمانی آذروت، استفاده میکنیم که به طور معمول برای اجرای وظایف همزمان استفاده میشود. هر context ایجاد شده توسط Async Library باید پس از اتمام وظایف زمینه تمیز شود. به این ترتیب، حافظه به سرویس برگشت داده خواهد شد.
هرچند، همانطور که در نمودار مشاهده میشود، حافظه بازگشت داده نشده است، که منجر به نشت حافظه میشود و به تبع آن استفاده از حافظه افزایش مییابد حتی در صورت کاهش بار سیستم Market-Store.
شناسایی واقعیت مشکل
بنابراین ما میدانستیم که تاخیر Market-Store تحت تأثیر قرار گرفته است، اما نمیدانستیم چرا. از گراف اول، میبینیم که مصرف حافظه حتی با کاهش بار سیستم Market-Store ادامه دارد. سپس، PPROF به ما نشان میدهد که حافظه نگهداری شده توسط context ها پاک نمیشود، که منجر به نشت حافظه میشود.
در طی بررسیهای ما، ما رابطهای بین افزایش مصرف حافظه و تضعیف تاخیر API سرور تشخیص دادیم. به عبارت دیگر، نشت حافظه منجر به مصرف حافظه بالا میشود و در نهایت منجر به مشکل تاخیر میشود.
با این حال، هیچ تغییری در سرویس ما اتفاق نیفتاده بود که باعث تأثیری بر روی نحوه ایجاد و تمیز شدن context ها شود. پس چه علتی باعث نشت حافظه شد؟
اشکال زدایی نشت حافظه
باید مطالعهای درباره کتابخانه Async و نحوه عملکرد آن انجام میدادیم. برای Market-Store، ما کش را به صورت همزمان برای مکانیزم نوشتن کشینگ write-around بهروز میکنیم. ما از کتابخانه Async برای اجرای وظایف به طور پسزمینه استفاده میکنیم.
قطعه کد زیر راهکار کارکرد کتابخانه Async را توضیح میدهد:
async.Consume(context.Background(),runtime.NumCPU()*4,buffer)// Consume runs the tasks with a specific max concurrencyfuncConsume(ctxcontext.Context,concurrencyint,taskschanTask)Task{// code...returnInvoke(ctx,func(context.Context)(interface{},error){workers:=make(chanint,concurrency)concurrentTasks:=make([]Task,concurrency)// code ...t.Run(ctx).ContinueWith(ctx,func(interface{},error)(interface{},error){// code...})}}funcInvoke(ctxcontext.Context,actionWork)Task{returnNewTask(action).Run(ctx)}func(t*task)Run(ctxcontext.Context)Task{ctx,t.cancel=context.WithCancel(ctx)got.run(ctx)returnt}
ملاحظه: کدی که در این مقاله مربوط نمیشود با کد جایگزین شده است.
همانطور که در قطعه کد بالا مشاهده میشود، کتابخانه Async متد Consumero بگونهای مقداردهی اولیه کرده است تا یک context زمینه را ایجاد کند و سپس آن را به تمام اجراکنندههایی که دارد، منتقل میکند. context های زمینه خالی هستند و شناسه یا ارتباطی با context های زیرین که از آن ایجاد شدهاند ندارند.
در Market-Store، ما از context های زمینه استفاده میکنیم زیرا آنها به زنجیره context ثابت نیستند و حتی بعد از تمیز شدن یک context درخواست ادامه خواهد یافت. این بدین معناست که پس از اتمام وظیفه مصرفی، حافظه مصرف شده توسط context فرزند آزاد شده و جلوگیری از بروز نشت حافظه به طور کامل.
شناسایی علت نشت حافظه
با تحقیقات بیشتر، یک MR که در کتابخانه اعمال شده بود وجود داشت که مشکل لغو وظیفه را حل میکند. همانطور که در قطعه کد زیر نشان داده میشود، متد Consume تغییر داده شده بود به گونهای که context وظیفه به اجراکنندهها منتقل میشد، به جای context های خالی زمینه.
funcConsume(ctxcontext.Context,concurrencyint,taskschanTask)Task{// code...returnInvoke(ctx,func(taskCtxcontext.Context)(interface{},error){workers:=make(chanint,concurrency)concurrentTasks:=make([]Task,concurrency)// code ...t.Run(taskCtx).ContinueWith(ctx,func(interface{},error)(interface{},error){// code...})}}
قبل از اینکه تکه کد را توضیح دهیم، کوتاهی توضیح میدهیم که context های Golang چیستند. context یک بسته استاندارد Golang است که حد زمانها، اعلانهای لغو و سایر مقادیر محدوده درخواست را از مرزهای وب سرویس به ارث میبرد و بین فرآیندها گسترش مییابد. همیشه باید به خاطر داشته باشیم که context ها را پس از استفاده از آنها لغو کنیم.
اهمیت لغو کردن context
وقتی یک context لغو میشود، همه context هایی که از آن ایجاد شدهاند نیز لغو میشوند. این بدین معناست که هیچ context یا ارتباط ناشناسی وجود ندارد و میتواند توسط ابزار CancelFunc کتابخانه Async به دست آید.
متد CancelFunc کتابخانه Async:
- لغو context فرزند ایجاد شده را و لغو وظیفه های زمینه آن حذف میکندحذف ارجاع والدین از context فرزندتوقف هر تایمر مرتبط
همیشه باید مطمئن شویم که پس از استفاده از context ها، متد CancelFunc را فراخوانی کنیم تا اطمینان حاصل کنیم که context ها و حافظه نشت نمیشوند.
توضیح تأثیر MR
در قطعه کد قبلی، مشاهده میشود که context های وظیفه به اجراکننده ها منتقل میشوند و لغو نمیشوند. کتابخانه Async context های وظیفه را از context هایی که خالی هستند ایجاد میکند، به این معنی که context های وظیفه توسط context های والدین پیگیری میشوند. بنابراین، حتی اگر کار مرتبط با این context های وظیفه تمام شود، توسط سیستم پاک نخواهند شد (گنجایش زباله را ندارند).
همانطوری که با استفاده از context های وظیفه به جای context های زمینه شروع کردیم و آنها را لغو نکردیم، حافظه مصرف شده توسط این context ها هرگز بازگشت داده نشد و در نتیجه نشت حافظه ایجاد شد.
تلاشهای ما برای اشکال زدایی و بررسی علت اصلی مشکل تاخیر بالای Market-Store زمان بربر و از این رو در این حادثه چندین مورد مهم یاد گرفتیم که به جلوگیری از نشت حافظه در آینده کمک میکند.
- همیشه context هایی که ایجاد کرده اید را لغو کنید. رها کردن آنها برای تمیز کردن (پاک کردن سیستم) ممکن است باعث نشت حافظه غیرمنتظره شود.Profiling های Go میتوانند بسیاری از بینشها درباره برنامه شما ارایه کنند، به خصوص زمانی که مطمئن نیستید کجا رفتار کاری برنامه را اشکال زدایی کنید.همیشه در هنگام یکپارچه کردن وابستگی های خود ، بنچمارک کنید.
- Details
- Written by: mehdi
- Category: Scraped Data
- Hits: 143
بررسی کلی و تجزیه و تحلیل اولیه
مدیریت دانش اغلب یکی از بزرگترین چالشهایی است که بیشتر شرکتها درونی با آن روبرو میشوند. تیمها ساعتهای زیادی را صرف تلاش برای به دست آوردن اطلاعات به طریق ناکارآمد یا استفاده نامناسب میکنند و یا به طور مداوم از همکاران خود درخواست اطلاعاتی که در جایی قبلاً ثبت شده است میکنند. زمان زیادی بر روی کانالهای ارتباطی داخلی کارمندان (در موارد ما، Slack) صرف سعی در یافتن پاسخ به سوالات تکراری میشود. در سفر ما برای اتوماسیون پاسخ به این سوالات تکراری، نیاز داشتیم ابتدا بفهمیم دقیقاً میزان زمان و تلاشی که توسط مهندسان در دستیابی به این سوالات تکراری صرف میشود چقدر است.
به زودی شناختیم که فعالیتهای بسیاری از ابزارهای داخلی مهندسی مربوط به وظایف مربوط به خدمتگزاری عبارتند از پاسخ به سوالات کاربران (کاربران داخلی) در کانالهای مختلف Slack. بسیاری از این سوالات قبلاً پرسیده شده و یا در ویکی ثبت شده است. این پرس و جوها به بهرهوری مهندسین خدمتگزاری زمینه میدهد و بر کارایی آنها در انجام وظایف عملیاتی تأثیر میگذارد. پس از اینکه پی به این برداشت زدیم که کارکنان خدمتگزاری بسیار وقت خود را برای پاسخ به درخواستهای Slack میگذارند، تصمیم گرفتیم در یک سفر به تعیین بالاترین سوالات بپردازیم.
برای این مطالعهبا گروههای کوچکی از تیمها مشورت کردیم و متوجه شدیم که:
- پرسشهای پرتکرار کاربران “چگونه ABC را انجام دهم؟” یا “آیا XYZ خراب است؟” هستند. پرسشهای دوم عمدهای که پرسیده میشوند مربوط به درخواستها و تأییدها یا سایر مجوزها است. پاسخ به اینگونه سوالات بیشتر به آدرسهای اینترنتی مستندات موجود است.
این نتایج ما را آگاه ساخت که ما نه فقط به یک پاسخگوی خودکاری مبتنی بر هوش مصنوعی برای سوالات تکراری نیاز داریم. در واقع، ما باید از تاریخچه چت این کانالها برای تشخیص الگوها استفاده کنیم.
جمع آوری نظرات کاربران برای فروشندگان مختصر لیست شده
با توجه به صرفهجویی در هزینه و زمان و در نظر گرفتن کیفیت راهحلهای موجود در بازار، تصمیم گرفتیم که به جای ابداع چرخ دوباره، یک محصول موجود را خریداری کنیم. و برای مشخص کردن کدام محصول را بخریم، نیاز به تحلیل مقایسهای داشتیم. و بنابراین سفر مقایسه فروشندگان ما آغاز شد!
هنگام مقایسه مجموعه ویژگیهای ارائه شده توسط فروشندگان مختلف، متوجه شدیم که کاربران ما نیاز به مشارکت در این روند تصمیمگیری دارند. با این حال، به اشتراک گذاشتن تحلیل فروشنده با کاربران و اجازه دادن به آنها برای انتخاب ربات مورد علاقه خود چندین چالش را به وجود آورد:
- کاربران ممکن است به رباتهای شناخته شده (از تجربیات قبلی) تمایل پیدا کنند.کاربران ممکن است به برندهای بزرگ با عقیده پیشفرضی و مفهومی که برندها بزرگ بهترین ویژگیها و پشتیبانی کاربر را به همراه دارند تمایل داشته باشند.کاربران احتمالاً فروشنده گرانقیمتتر را انتخاب کنند و فرض کنند هزینه بالاتر به معنای کارایی بالاتر است.
برای اطمینان حاصل کردن از ارائه بازخورد بدون تبعیض، در اینجا نحوه آغاز رأیگیری کاربران را برای شما توضیح میدهیم. ویژگیهای برتر هر ربات را نسبت به سایر رباتهای مختصرلیست شده برجسته کردیم. نام رباتها را برای جلب توجه بهتر پنهان کردیم. به طور کلی، دستهبندی به این شکل بود:
اگرچه هیچ یک از گزینهها تمام ویژگیهایی را که کاربران ما میخواستند نداشتند، حدود 60 درصد افراد فروشنده 1 (OneBar) را انتخاب کردند. از این نتیجه، ویژگیهای اصلی مورد نیاز کاربران ما را کشف کردیم همچنین آنها را در روند تصمیمگیری مشارکت کردیم.
انطباق نیازهای ما با مجموعه ویژگیهای فروشندگان موجود
اگرچه کاربران ما ترجیحات خود را روشن کردند، ما هنوز نیاز داشتیم اطمینان حاصل کنیم که مجموعه ویژگیهای موجود در بازار با نیازهای داخلی ما تطبیق دارد، به خصوص در مورد تنظیمات و ویژگیهای موجود در پرتالهایی که ما قصد داریم جایگزین کنیم. به عنوان قسمتی از فرآیند جمع آوری نیازهای ما، در ادامه برخی از شرایط بحرانی که بیشتر و بیشتر به چشم میخوردند را توضیح میدهیم:
بررسی اثبات کننده مفهوم
ما چندین ابزار را (از جمله برخی از ابزارهای استفاده شده توسط تیم منابع انسانی ما برای پاسخگویی خودکار به سوالات کارمندان) در نظر گرفتیم. سپس تصمیم گرفتیم که یک طرح کامل از مفهوم را با OneBar انجام دهیم تا بررسی کنیم که آیا نیازهای داخلی ما را برآورده میکند یا خیر.
این مراحلی هستند که ما در آنها POC را برای فروشنده مختصرلیست شده (OneBar) انجام دادیم:
مرحله 1: مطالعه ترافیک، دیدن چه بینشهایی OneBar نشان میدهد و چه چیزهایی که باید به طور بالقوه نشان داده میشد، را تفکر کنید. سپس درباره اینکه یک پشتیبان یا پشتیبانی ایدهآل در چنین محیطی چگونه باید عمل کند، فکر کنید. یعنی ما میتوانستیم پیامهای خاصی را در تاریخچه شناسایی کنیم و برای هر یک از آنها بیان کنیم که چه باید اتفاق میافتاد.
مرحله 2: از رکوردهای مورد نیاز در OneBar ایجاد کنید و آن را به طور حداکثر در نزدیکی به رفتار مطلوب پیکربندی کنید.
مرحله 3: بگذارید ابزار برای چند هفته اجرا شود و سپس ارزیابی کنید که چقدر به سوالات پاسخ میدهد، چه قدر افراد به صورت مستقیم جستجو میکنند، چه مقدار اطلاعات اضافه میکنند، و غیره. OneBar همه این معیارها را در برنامه اضافه میکند که فعالیت را آسانتر میکند.
علاوه بر POC OneBar، ما سایر راهکارها را بررسی کردیم و یک مقایسه و تجزیه و تحلیل جامع انجام دادیم. پس از انجام POC و بررسی سایر فروشندگان، تصمیم گرفتیم از OneBar استفاده کنیم زیرا ویژگیهای آن بهترین نیازهای ما را برآورده میکند.
اولویتبندی کانالهای Slack
اگرچه ما چندین کانال Slack داشتیم که دوست داشتیم ربات مختصرلیست شده را در آنها فعال کنیم، قرارداد اولیه ما استفاده از ربات OneBar را فقط برای 20 کانال محدود کرد. ما نمیتوانستیم از OneBar برای اسکن خودکار بیش از 20 کانال Slack استفاده کنیم.
کاربران همچنان میتوانند با ربات به صورت مستقیم چت کنند تا پاسخهایشان را براساس آنچه در پایگاه دانش ربات تغذیه شده است دریافت کنند. آنها همچنین میتوانند وارد سیستم وب شوند که پایگاه دانش را، سایر ویژگیهای ارزشمند و ویژگیهای اضافی برای مدیران / کارشناسان نمایش میدهد.
کانالهای Slack که ویژگیهای لایسنس بر روی آنها فعال شده بود اولویت بندی شدند بر اساس:
- بیشترین تعداد پیامهای ارسال شده در کانال در ماه، یعنی کانالهای فعالتر.بیشترین تعداد اعضا تأثیرگذار، یعنی کانالها با تعداد عضو زیاد.
برای این کار، از گزارشهای آماری Slack استفاده کردیم و کانالهایی را که با معیارهای اولویتبندی ما مطابقت داشتند شناسایی کردیم.
تغییر دشوار است، اما اغلب ضروری
با ورود فروشنده، ما شروع به آموزش و آموزش کارمندان در استفاده از این سیستم مدیریت دانش جدید برای تمام سوالات متداولشان کردیم. این چالش بود چون تغییر همیشه پیچیده ولی برای رشد ضروری است.
یک سری سخنرانیهای فنی و آموزش که در سراسر شرکت و به مقیاسهای کوچکتر هم راهنمایی کاربران در مورد ویژگیها و قابلیتهای ربات استفاده کرد.
در ابتدا، ما به عدم دسترسی به دادههای کافی منجر شدیم که باعث پاسخهای غلط از ربات شود. اما با افزایش آگاهی تیم از قابلیتها و یادگیری بیشتر درباره آن...
- Details
- Written by: mehdi
- Category: Scraped Data
- Hits: 133
بطور معمول، برنامههای مدرن از موتورهای مختلف پایگاه داده برای نیازهای سرویس خود استفاده میکنند؛ در Grab ، اینها شامل MySQL ، Aurora و DynamoDB است. اخیراً تیم Caspian نیاز روز افزونی برای مصرف دادههای زمان واقعی در بسیاری از تیمهای سرویس مشاهده کرده است. این تغییرات در زمان واقعی در رکوردهای پایگاه داده به پشتیبانی از تصمیمات تجاری آنلاین و آفلاین برای صدها تیم کمک میکند.
بدلیل این موضوع، ما وقت خود را به هماهنگسازی دادهها از MySQL ، Aurora و Dynamodb تا صف پیام، به عنوان مثال Kafka سپردهایم. در این بلاگ، ما در مورد این که چگونه مصرف دادههای زمان واقعی کمک کرده است، میگوییم.
در چند سال اخیر، تیمهای سرویس باید تمام دادههای معاملاتی را دو بار بنویسند: یک بار در Kafka و یک بار در پایگاه داده. این به حل چالشهای ارتباط بین سرویسها و به دست آوردن لاگهای ردیابی کمک کرده است. با این حال، در صورت عدم موفقیت تراکنشها، اصالت داده مشکلی مهم میشود. علاوه بر این، نگهداری طرح دادههای مورد نوشتن در Kafka یک کار دشوار برای توسعه دهندگان است.
با جذب زمانبندی، تکامل طرح بهتر و قطعیت داده تضمین شده و تیمهای سرویس دیگر نیازی به دو بار نوشتن داده ندارند.
شاید شما در حال تعجب باشید که چرا ما یک تراکنش تکی که بانک اطلاعات سرویسها و Kafka را دربرگیرد برای ارائه داده یکنواخت استفاده نمیکنیم؟ این کار نمیتواند انجام شود زیرا Kafka از ورود به تراکنشهای توزیع شده پشتیبانی نمیکند. در برخی موارد، ممکن است داده جدیدی در پایگاه دادههای سرویسها ثبت شود، اما پیام مربوطه به تاپیکهای Kafka ارسال نشود.
به جای ثبت نام یا اصلاح طرح نگاشتی در نویسنده Golang به Kafka قبل از دست بردن از دست بردن طرح، تیمهای سرویس به طور کلی تمایل دارند از چنین تکالیف نگهداری طرحی اجتناب کنند. در چنین مواردی، میتوان از جذب زمان واقعی استفاده کرد که در آن تبادل داده بین پایگاههای داده متعدد یا تکثیر بین منبع و نمونههای پشتیبانی مورد نیاز است.
هنگام بررسی چالشهای اصلی در مورد جذب داده زمان واقعی، متوجه شدیم که بسیاری از نیازهای کاربر پتانسیلی وجود دارد که باید شامل شود. برای ساخت یک راه حل استاندارد، چندین نکته اولیه که ما احساس کردیم اولویت بالایی دارند، شناسایی کردیم:
- به عنوان مثال گرفتن حق دسترسی به دادههای معاملاتی در زمان واقعی برای اتخاذ تصمیمات تجاری به مقیاس.ثبت لاگ از هر پایگاه داده داده شده.
برای اعطای قدرت برنامههای Grabbers با دادههای زمان واقعی برای اتخاذ تصمیمات تجاری خود، ما تصمیم گرفتیم رویکردی قابل مقیاس را که با مجموعهای از محصولات داخلی تسهیل میشود، انتخاب کنیم و یک راه حل برای جذب دادههای زمان واقعی طراحی کنیم.
ساختگی معماری
راه حل برای جذب دادههای زمان واقعی چندین جزء کلیدی دارد:
- ذخیره دادههای استریمتولید کننده رویدادصف پیامپردازنده استریم
ذخیره استریم
ذخیره استریم عمل میکند که تراکنشهای داده را به ترتیب با تضمین یک بار دقیق ذخیره میکند. با این حال، سطح ترتیب در ذخیره استریم با توجه به پایگاه دادههای مختلف متفاوت است.
برای MySQL یا Aurora، دادههای تراکنش در فایلهای binlog به ترتیب و چرخشی ذخیره میشوند، بدین ترتیب ترتیب کلی را تضمین میکنند. داده با ترتیب کلی تضمین میکند که همه رکوردهای MySQL مرتب شده و واقعیت زندگی واقعی را نشان میدهند. به عنوان مثال، هنگامی که لاگهای تراکنشی بازیشوند یا توسط مصرفکنندگان پایینجریان مصرف شوند، سفارش غذای مشتری A ساعت 12:01 عصر پیش از سفارش مشتری B ساعت 12:01:45 عصر همیشه ظاهر میشود.
با این حال، این موضوع برای ذخیره استریم DynamoDB در حقیقت درست نیست زیرا استریمهای DynamoDB به صورت بخشی شده هستند. گزارشهای حق تملکی از یک رکورد داده میدهد که آنها به ترتیب به همان بخش در همان بخش میروند و ترتیب بخشبندیشده است. بنابراین در هنگام پخش دوباره اتفاق میافتد که سفارش مشتری B ممکن است قبل از سفارش مشتری A ظاهر شود.
علاوه بر این، برای هر دو فرمت binlog و رکوردهای استریم DynamoDB ، چندین فرمت برای انتخاب وجود دارد. در نهایت ما برای فرمتهای binlogROW و NEW_AND_OLD_IMAGESرا تنظیم میکنیم. این نشان میدهد ناهمواره قبل و بعد از اصلاح هر رکورد جدول داده شده اطلاعات تفصیلی را نشان میدهد. فیلدهای اصلی binlog و DynamoDB stream در شکلهای 2 و 3 به ترتیب جدولبندی شده اند.
تولید کننده رویداد
تولید کننده رویدادها پیامهای binlog یا رکوردهای استریم را وارد صف پیام میکنند. ما چندین فناوری را برای مختلف موتورهای پایگاه داده بررسی کردیم.
برای MySQL یا Aurora، سه راهحل مورد ارزیابی قرار گرفته است: Debezium ، Maxwell و Canal. ما انتخاب کردیم تا Debezium را به عنوان یکی از آنها به حاشیه بگذاریم زیرا با چارچوب Kafka Connect یکپارچه شده است. علاوه بر این، ما مشاهده کردیم که پتانسیل گسترش را در میان سایر سیستمهای خارجی هنگام انتقال مجموعههای بزرگی از داده به درون خوشه Kafka دارد.
یکی از مثالهای شبه منبع باز مشابه این است که سعی میکند یک اتصال سفارشی DynamoDB را گسترش دهد که چارچوب Kafka Connect (KC) را گسترش دهد. این تابع حساب میکند که وسیله مدیریت چکپوینت را از طریق جدول اضافی DynamoDB انجام دهد و میتواند به خوبی در KC استقرار یابد.
با این حال، کانکتور DynamoDB نمیتواند از طریق طبیعت اساسی استریمهای DynamoDB استفاده کند: بخشبندی پویا و مقیاسپذیری خودکار بر اساس ترافیک. به جای آن، تنها یک وظیفه نخ تکی را برای پردازش تمام شارههای جدول DynamoDB دارد. نتیجه این است که سرویسهای پایینجریان در مواقعی که ترافیک نوشتن بالا میتابد، بیش از همه از تاخیر داده رنج میبرند.
با توجه به این موضوع، تابع Lambda به عنوان منبع تولید رویداد مناسبترین کاندیدایی است. نه تنها همزمانی توابع لامبدا براساس ترافیک واقعی مقیاس میکند، بلکه فرکانس تریگر قابل تنظیم است و شما میتوانید بر اساس تصمیم خود تعیین کنید.
کافکا
این مخزن داده توزیع شده است که برای جذب و پردازش داده به صورت زمان واقعی بهینه شده است. به دلیل مقیاسپذیری بالا، مقاومت در برابر خطا و پردازش همزمان، به طور گسترده ای پذیرفته شده است. پیامها در Kafka تجری شده و در Protobuf رمزگذاری میشوند.
پردازشگر استریم
پردازنده استریم پیامها را در Kafka مصرف کرده و هر دقیقه به S3 بنویسید. چندین گزینه آماده در بازار وجود دارد؛ Spark و Flink بیشترین گزینههای رایج هستند. در Grab ، ما یک کتابخانه Golang را برای مقابله با ترافیک استفاده میکنیم.
کاربردها
اکنون که راجع به اینکه چگونه جذب دادههای زمان واقعی در Grab انجام میشود، صحبت کردیم، بیایید به برخی از موقعیتهایی که میتوانند از جذب دادههای زمان واقعی بهرهبرداری کنند، نگاه کنیم.
1. خطوط لوله داده
ما در Grab هزاران خط لوله را در هر ساعت اجرا میکنیم. برخی جداول رشد قابل توجهی داشته و بار کاری را فراتر از آنچه که یک پرس و جوی SQL مبتنی بر کوئری میتواند کنترل کند، ایجاد میکنند. خط لوله داده ساعتانه باعث ایجاد افزایش خواندن در پایگاه داده تولیدی که میان خدمات مختلف به اشتراک گذاشته میشود و منابع CPU و حافظه را خالی میکند. این باعث کاهش عملکرد خدمات دیگر و حتی ممکن است آنها را از خواندن محدود کند. با جذب زمان واقعی، پرس و جوی خطوط لوله داده به صورت تدریجی و در یک بازه زمانی پخش میشود.
سناریوی دیگری که به جذب زمان واقعی میپردازیم، زمانی است که بر روی جدول شاخص از دست رفته تشخیص داده میشود. برای سرعت بخشیدن به پرس و جو، جذب پرس و جوی مبتنی بر SQL نیاز به ایجاد شاخص بر روی ستونهای مانند created_at ، updated_at و id دارد. بدون شاخصگذاری، جذب پرس و جو مبتنی بر SQL میتواند منجر به مصرف بالای CPU و حافظه یا حتی شکست شود.
اگرچه اضافه کردن شاخص برای این ستونها میتواند این مشکل را حل کند، اما هزینهای به همراه میآورد، به عبارت دیگر کپی از ستون شاخص گرفته میشود و کلید اصلی در دیسک ایجاد میشود و شاخص در حافظه نگه داشته میشود. ایجاد و نگهداری یک شاخص در یک جدول بزرگ هزینهبرتر از جداول کوچکتر است. با توجه به ملاحظات عملکرد، توصیه نمیشود شاخصها را به یک جدول بزرگ موجود اضافه کنید.
در عوض، جذب زمان واقعی جذب پرس و جوی مبتنی بر SQL را سایه میاندازد. ما میتوانیم یک کانکتور جدید و یک آرشیوکننده (کتابخانه Golang Coban تیم) و یک کار تراکم را برای ایجاد ارتباط از binlog به جدول مقصد در lake داده بیرون کنیم.
2. رساندن تصمیمات تجاری
یکی از موارد استفاده کلیدی از جذب داده زمان واقعی برای اتخاذ تصمیمات تجاری به مقیاس بدون حتی لمس خدمات منبع است. الگوی Saga در دنیای میکروسرویس رایج است. هر سرویس دارای پایگاه داده خود است و یک تراکنش بانکی کلی را به چندین تراکنش پایگاه داده تقسیم میکند. ارتباط بین این سرویسها از طریق صف پیام برقرار میشود یعنی Kafka.
در یک بلاگ تکنولوژیای قبلی که توسط تیم جستجوی مجله زیبایی و درمانی آذروت منتشر شده است، در مورد این صحبت کردیم که چگونه جذب زمان واقعی با Debezium قابلیتها و قابلیتهای جستجو را بهینه و افزایش میدهد. هر جدول MySQL به یک موضوع Kafka نگاشت میشود و یک یا چندین موضوع ساختار جستجو را در Elasticsearch ایجاد میکنند.
با این رویکرد جدید، هیچ داده ای از دست نمیرود، به عبارت دیگر تغییرات از طریق ابزار خط فرمان MySQL یا ابزارهای مدیریت دیگر پایگاه دادهها قابل ضبط است. تکامل طرح نیز به طور طبیعی پشتیبانی میشود؛ طرح جدید که در یک جدول MySQL تعریف شده است، به ارث برده میشود و در Kafka ذخیره میشود. برای هماهنگی طرح با آنچه در MySQL وجود دارد، نیازی به تغییر کد تولید کننده نیست. علاوه بر این، خواندن پایگاه داده با توجه به تلاشهای پلتفرم هماهنگسازی داده 90 درصد کاهش یافته است.
تیم GrabFood بیشترین مزیتهای مشابه در حوزه DynamoDB را نشان میدهد. تنها تفاوتهای آن نسبت به MySQL این است که فرکانس تابع لامبدا قابل تنظیم است و پاراللیسم بر اساس ترافیک اتوماتیک مقیاس میشود. با توجه به مقیاسپذیری خودکار، منظور از بالا و پایین تابع لامبدا این است که مواردی که ناگهان ترافیک بالا را تجربه میکند، تابعهای لامبدا بیشتری برای خدمت رسانی خودکار ایجاد میکند، یا با کاهش ترافیک منسوخ میشود.
3. تکثیر پایگاه داده
یکی از موارد استفاده که در ابتدا در نظر نگرفته بودیم، تکثیر دادههای فزاینده برای بازیابی بحرانی است. در Grab، ما چشماندازهای DynamoDB را برای جداول tier 0 و مهم فعال میکنیم. هر عملیات درج ، حذف ، اصلاح به طور ناگهانی به جلو میروند.