ایربیانبی چطور ترافیک واقعی دیتابیس رو ضبط و دوباره اجرا میکنه
خلاصهٔ کاملتر
ایربیانبی صدها کلاستر دیتابیس سازگار با MySQL داره که میلیونها کوئری در ثانیه جواب میدن. تو این پست، تیم زیرساخت دیتابیسشون توضیح میده چرا بنچمارکهای مصنوعی مثل sysbench براشون کافی نبود و چطور سیستمی ساختن که ترافیک واقعی رو ضبط و دوباره پخش (replay) میکنه. سیستم قبلیشون کوئریها رو سمت کلاینت و جدا برای هر زبان لاگ میکرد، نگهداریش سخت بود و اطلاعات کامل تراکنش رو نداشت، پس نمیشد باهاش دقیق replay کرد.
نقطهٔ ضبط جدید ProxySQL هست، یعنی پراکسیای که پروتکل MySQL رو میفهمه و از قبل بین اپها و دیتابیسها نشسته بود. پس هیچ تغییری تو اپلیکیشنها لازم نیست. قابلیت query logging خود ProxySQL رو فقط برای یه کلاستر خاص و فقط برای مدت تست روشن میکنن. یه sidecar به اسم Log Mover لاگها رو از دیسک لوکال برمیداره و میبره رو object storage ابری. چون این لاگها ممکنه دادهٔ شخصی داشته باشن، دقیقاً مثل دادهٔ production باهاشون رفتار میشه و هیچوقت روی محیطهای پایینتر replay نمیشن.
Log Processor لاگهای باینری رو decode میکنه، کوئریهای هر کلاستر رو جدا میکنه و دستورهای هر تراکنش رو به ترتیب اصلیشون کنار هم میذاره. بعد هم فایلها رو تو بازههای پنجدقیقهای دستهبندی میکنه. یه ترفند جالبش بازنویسی INSERTهاست: چون دیتابیس مقصد ممکنه auto-increment رو جور دیگهای بده، last_insert_id ضبطشده رو صریحاً تو کوئری میذاره. مثلاً INSERT INTO users (name) VALUES ('bob') میشه INSERT INTO users (id, name) VALUES (1, 'bob'). هزینهش اینه که دیگه خود مکانیزم auto-increment مقصد تست نمیشه.
Log Replayer از یه API Server با رابط وب، یه scheduler و هزاران worker تشکیل شده. دو حالت داره: «Replay only» برای تست بار، با سرعت 1x، 2x، 3x یا یه QPS دلخواه؛ و «Replay and compare» که همون کوئریها رو همزمان روی دو دیتابیس اجرا میکنه و نتیجهها رو مقایسه میکنه. scheduler به همهٔ تسکهای یه batch یه «زمان شروع» مشترک میده تا workerها با هم شروع کنن، یعنی همزمانی و ریتم ترافیک اصلی حفظ میشه.
تو ارتقا به MySQL 8.0 این سیستم چند تا مشکل رو زود لو داد. حذف query cache تو 8.0 کوئریهای تکراریای رو رو کرد که cache قبلاً بیصدا جذبشون میکرد. تو بدترین مورد، latency یه الگوی کوئری از 0.03 به 2.6 ثانیه رسید و بهجای 5 مگابایت، 273 مگابایت در هر join میخوند؛ دلیلش تغییر نحوهٔ خوندن ردیفها موقع sort تو MySQL 8.0.20 به بعد بود. حالت compare هم کوئریهایی رو پیدا کرد که ORDER BY نداشتن یا tiebreaker یکتا نداشتن و با LIMIT روی موتور جدید ردیفهای متفاوتی برمیگردوندن.
برای برنامهریزی ظرفیت هم ترافیک رو با سرعت بالاتر پخش میکنن. روی یه کلاستر بزرگ، 80 درصد ترافیک نوشتن بیشتر، میانگین commit latency رو از حدود 6 به 34 میلیثانیه رسوند، یعنی سقف کلاستر خیلی قبل از اینکه ترافیک واقعی بهش برسه پیدا شد. نویسندهها جمعبندی میکنن که بنچمارک مصنوعی بار خیالی رو تست میکنه، ولی replay بار واقعی رو.
نکات کلیدی:
- نقطهٔ ضبط ProxySQL هست، پس هیچ تغییری تو کد اپها لازم نیست
- لاگها تو فایلهای پنجدقیقهای برای هر کلاستر و هر pod دستهبندی میشن
- INSERTها با last_insert_id ضبطشده بازنویسی میشن تا replay روی موتورهای مختلف یکسان رفتار کنه
- دو حالت داره: Replay only برای تست بار و Replay and compare برای مقایسهٔ دو دیتابیس
- تو ارتقا به MySQL 8.0، latency یه کوئری از 0.03 به 2.6 ثانیه رفته بود که قبل از production پیدا شد
- 80 درصد ترافیک نوشتن بیشتر، commit latency رو از 6 به 34 میلیثانیه رسوند




