1 TB/s tezlikda qidirish

TL; DR: To'rt yil oldin men yangi server monitoringi vositasi g'oyasi bilan Googleni tark etdim. G'oya odatda ajratilgan funktsiyalarni bitta xizmatga birlashtirish edi yig'ish va jurnallarni tahlil qilish, ko'rsatkichlarni yig'ish, ogohlantirishlar va asboblar paneli. Printsiplardan biri shundaki, xizmat haqiqatan ham bo'lishi kerak tez, devoplarga oson, interaktiv va yoqimli tajribani taqdim etish. Buning uchun ko'p gigabaytli ma'lumotlar to'plamini bir soniya ichida qayta ishlash va byudjet doirasida qolishi kerak. Mavjud jurnallarni boshqarish vositalari ko'pincha sekin va noqulay, shuning uchun biz yaxshi muammoga duch keldik: foydalanuvchilarga yangi tajriba berish uchun vositani oqilona loyihalash.

Ushbu maqolada biz Skalyrda eski maktab usullari, qo'pol kuch yondashuvini qo'llash, keraksiz qatlamlarni yo'q qilish va murakkab ma'lumotlar tuzilmalaridan qochish orqali bu muammoni qanday hal qilganimiz tasvirlangan. Siz ushbu darslarni o'zingizning muhandislik muammolaringizga qo'llashingiz mumkin.

Eski maktab kuchi

Jurnalni tahlil qilish odatda qidiruvdan boshlanadi: ma'lum bir naqshga mos keladigan barcha xabarlarni toping. Scalyr-da bu ko'plab serverlardan o'nlab yoki yuzlab gigabaytlik jurnallar. Zamonaviy yondashuvlar, qoida tariqasida, qidiruv uchun optimallashtirilgan ba'zi murakkab ma'lumotlar strukturasini qurishni o'z ichiga oladi. Men buni Googleda ko'rganman, bu erda ular bu kabi narsalarni juda yaxshi bilishadi. Ammo biz ancha qo'polroq yondashuvga qaror qildik: jurnallarni chiziqli skanerlash. Va u ishladi - biz raqobatchilarimizga qaraganda tezroq qidirish mumkin bo'lgan interfeysni taqdim etamiz (oxirida animatsiyaga qarang).

Asosiy tushuncha shundaki, zamonaviy protsessorlar haqiqatan ham oddiy, sodda operatsiyalarda juda tezdir. Kirish-chiqarish tezligi va tarmoq operatsiyalariga tayanadigan murakkab, ko'p qatlamli tizimlarda buni o'tkazib yuborish oson va bunday tizimlar bugungi kunda juda keng tarqalgan. Shunday qilib, biz qatlamlar va ortiqcha qoldiqlarni minimallashtiradigan dizaynni ishlab chiqdik. Parallel ravishda bir nechta protsessor va serverlar bilan qidiruv tezligi sekundiga 1 TB ga etadi.

Ushbu maqoladan asosiy xulosalar:

  • Shafqatsiz qidiruv - bu haqiqiy, keng ko'lamli muammolarni hal qilish uchun qulay yondashuv.
  • Qo'pol kuch - bu ishsiz yechim emas, balki dizayn texnikasi. Har qanday texnika singari, u ba'zi muammolarga boshqalarga qaraganda yaxshiroq mos keladi va yomon yoki yaxshi amalga oshirilishi mumkin.
  • Qo'pol kuch, ayniqsa, erishish uchun yaxshi barqaror hosildorlik.
  • Shafqatsiz kuchdan samarali foydalanish kodni optimallashtirish va kerakli vaqtda etarli resurslarni qo'llashni talab qiladi. Agar sizning serverlaringiz foydalanuvchi bo'lmagan og'ir yuk ostida bo'lsa va foydalanuvchi operatsiyalari ustuvor bo'lib qolsa, mos keladi.
  • Ishlash faqat ichki halqa algoritmiga emas, balki butun tizimning dizayniga bog'liq.

(Ushbu maqolada xotiradagi maʼlumotlarni qidirish tasvirlangan. Koʻp hollarda foydalanuvchi jurnalda qidiruvni amalga oshirganda, Scalyr serverlari uni allaqachon keshlab qoʻygan. Keyingi maqolada keshlanmagan jurnallarni qidirish muhokama qilinadi. Xuddi shu tamoyillar amal qiladi: samarali kod, shafqatsiz kuch katta hisoblash resurslari bilan).

Qo'pol kuch usuli

An'anaga ko'ra, katta ma'lumotlar to'plami kalit so'z indeksi yordamida qidiriladi. Server jurnallariga qo'llanilganda, bu jurnaldagi har bir noyob so'zni qidirishni anglatadi. Har bir so'z uchun siz barcha qo'shimchalar ro'yxatini tuzishingiz kerak. Bu ushbu so'z bilan barcha xabarlarni topishni osonlashtiradi, masalan, "xato", "firefox" yoki "transaction_16851951" - shunchaki indeksga qarang.

Men ushbu yondashuvni Google'da ishlatganman va u yaxshi ishladi. Lekin Scalyr-da biz bayt-bayt loglarni qidiramiz.

Nega? Mavhum algoritmik nuqtai nazardan, kalit so'z indekslari qo'pol qidiruvga qaraganda ancha samarali. Biroq, biz algoritmlarni sotmaymiz, biz ishlashni sotamiz. Va ishlash nafaqat algoritmlar, balki tizim muhandisligi bilan ham bog'liq. Biz hamma narsani hisobga olishimiz kerak: ma'lumotlar hajmi, qidiruv turi, mavjud apparat va dasturiy ta'minot konteksti. Muayyan muammomiz uchun "grep" kabi narsa indeksdan ko'ra ko'proq mos keladi, deb qaror qildik.

Indekslar juda yaxshi, lekin ularda cheklovlar mavjud. Bitta so'zni topish oson. Ammo "googlebot" va "404" kabi bir nechta so'zli xabarlarni qidirish ancha qiyinroq. "Ushlab olinmagan istisno" kabi iborani qidirish nafaqat ushbu so'z bilan barcha xabarlarni, balki so'zning o'ziga xos joylashuvini ham qayd etadigan yanada og'irroq indeksni talab qiladi.

Haqiqiy qiyinchilik siz so'z izlamaganingizda keladi. Aytaylik, siz botlardan qancha trafik kelayotganini ko'rmoqchisiz. Birinchi fikr "bot" so'zini jurnallardan qidirishdir. Shunday qilib, ba'zi botlarni topasiz: Googlebot, Bingbot va boshqalar. Ammo bu erda "bot" so'z emas, balki uning bir qismidir. Agar biz indeksda "bot" ni qidirsak, "Googlebot" so'zi bilan hech qanday post topa olmaymiz. Agar siz indeksdagi har bir so'zni tekshirib ko'rsangiz va keyin topilgan kalit so'zlar uchun indeksni skanerlasangiz, qidiruv juda sekinlashadi. Natijada, ba'zi jurnal dasturlari qisman so'zlarni qidirishga ruxsat bermaydi yoki (eng yaxshi holatda) pastroq ishlashga ega maxsus sintaksisga ruxsat beradi. Biz buni oldini olishni xohlaymiz.

Yana bir muammo - tinish belgilari. dan barcha so'rovlarni topmoqchimisiz 50.168.29.7? O'z ichiga olgan disk raskadrovka jurnallari haqida nima deyish mumkin [error]? Subscripts odatda tinish belgilarini o'tkazib yuboradi.

Nihoyat, muhandislar kuchli vositalarni yaxshi ko'radilar va ba'zida muammoni faqat muntazam ifoda bilan hal qilish mumkin. Kalit so'z indeksi bunga juda mos kelmaydi.

Bundan tashqari, indekslar murakkab. Har bir xabar bir nechta kalit so'zlar ro'yxatiga qo'shilishi kerak. Ushbu ro'yxatlar har doim osongina qidiriladigan formatda saqlanishi kerak. So'rovlar, so'z bo'laklari yoki oddiy iboralar bilan ko'p ro'yxat operatsiyalariga tarjima qilinishi va natijalar to'plamini yaratish uchun natijalarni skanerlash va birlashtirish kerak. Keng ko'lamli, ko'p ijarachili xizmat kontekstida bu murakkablik algoritmlarni tahlil qilishda ko'rinmaydigan ishlash muammolarini keltirib chiqaradi.

Kalit so'z indekslari ham juda ko'p joy egallaydi va saqlash jurnallarni boshqarish tizimida asosiy xarajat hisoblanadi.

Boshqa tomondan, har bir qidiruv juda ko'p hisoblash quvvatini iste'mol qilishi mumkin. Bizning foydalanuvchilarimiz noyob so'rovlar uchun yuqori tezlikdagi qidiruvlarni qadrlashadi, ammo bunday so'rovlar nisbatan kamdan-kam hollarda amalga oshiriladi. Oddiy qidiruv so'rovlari uchun, masalan, asboblar paneli uchun, biz maxsus usullardan foydalanamiz (biz ularni keyingi maqolada tasvirlab beramiz). Boshqa so'rovlar juda kam uchraydi, shuning uchun siz kamdan-kam hollarda bir vaqtning o'zida bir nechtasini qayta ishlashingiz kerak bo'ladi. Lekin bu bizning serverlarimiz band emas degani emas: ular yangi xabarlarni qabul qilish, tahlil qilish va siqish, ogohlantirishlarni baholash, eski ma’lumotlarni siqish va hokazolar bilan band. Shunday qilib, bizda so'rovlarni bajarish uchun ishlatilishi mumkin bo'lgan protsessorlarning etarlicha katta ta'minoti mavjud.

Agar sizda qo'pol muammo bo'lsa (va juda ko'p kuch) qo'pol kuch ishlaydi

Shafqatsiz kuch kichik ichki halqalar bilan oddiy muammolarda eng yaxshi ishlaydi. Ko'pincha siz juda yuqori tezlikda ishlash uchun ichki pastadirni optimallashtirishingiz mumkin. Agar kod murakkab bo'lsa, uni optimallashtirish ancha qiyin.

Bizning qidiruv kodimiz dastlab juda katta ichki halqaga ega edi. Biz xabarlarni sahifalarda 4K da saqlaymiz; har bir sahifada ba'zi xabarlar (UTF-8 da) va har bir xabar uchun metama'lumotlar mavjud. Metadata - bu qiymat uzunligini, ichki xabar identifikatorini va boshqa maydonlarni kodlaydigan tuzilma. Qidiruv tsikli quyidagicha ko'rinadi:

1 TB/s tezlikda qidirish

Bu haqiqiy kodning soddalashtirilgan versiyasi. Ammo bu erda ham bir nechta ob'ektni joylashtirish, ma'lumotlar nusxalari va funksiya chaqiruvlari ko'rinadi. JVM funktsiya chaqiruvlarini optimallashtirish va efemer ob'ektlarni taqsimlashda juda yaxshi, shuning uchun bu kod biz loyiq bo'lganimizdan ham yaxshiroq ishladi. Sinov paytida mijozlar undan juda muvaffaqiyatli foydalanishdi. Ammo oxir-oqibat biz uni keyingi bosqichga olib chiqdik.

(Siz nima uchun biz xabarlarni to'g'ridan-to'g'ri jurnallar bilan ishlashdan ko'ra, 4K sahifalar, matn va metama'lumotlar bilan ushbu formatda saqlaymiz, deb so'rashingiz mumkin. Ko'p sabablar bor, ular ichida Scalyr dvigateli tarqatilgan ma'lumotlar bazasiga o'xshaydi. fayl tizimi.Matn qidiruvi koʻpincha jurnalni tahlil qilgandan soʻng chekkalarda DBMS uslubidagi filtrlar bilan birlashtiriladi.Biz bir vaqtning oʻzida bir vaqtning oʻzida minglab jurnallarni qidirishimiz mumkin va oddiy matnli fayllar tranzaksiya, takrorlanadigan, taqsimlangan maʼlumotlarni boshqarishimiz uchun mos emas).

Dastlab, bunday kod qo'pol kuchlarni optimallashtirish uchun unchalik mos emasdek tuyuldi. "Haqiqiy ish" ichida String.indexOf() hatto protsessor profilida ham ustunlik qilmadi. Ya'ni, bu usulni optimallashtirishning o'zi sezilarli samara keltirmaydi.

Shunday bo'ladiki, biz metama'lumotlarni har bir sahifaning boshida saqlaymiz va UTF-8-dagi barcha xabarlarning matni boshqa uchida joylashgan. Bundan foydalanib, biz bir vaqtning o'zida butun sahifani qidirish uchun tsiklni qayta yozdik:

1 TB/s tezlikda qidirish

Ushbu versiya to'g'ridan-to'g'ri ko'rinishda ishlaydi raw byte[] va butun 4K sahifasida bir vaqtning o'zida barcha xabarlarni qidiradi.

Bu qo'pol kuch usuli uchun optimallashtirish ancha oson. Ichki qidiruv tizimi har bir postda alohida emas, balki butun 4K sahifasi uchun bir vaqtda chaqiriladi. Ma'lumotlardan nusxa ko'chirish, ob'ektlarni ajratish yo'q. Va yanada murakkab metadata operatsiyalari har bir xabarda emas, balki ijobiy natija bo'lganda chaqiriladi. Shunday qilib, biz bir tonna yukni yo'q qildik va yukning qolgan qismi keyingi optimallashtirish uchun juda mos bo'lgan kichik ichki qidiruv tizimida to'plangan.

Bizning haqiqiy qidiruv algoritmimiz asoslanadi Leonid Volnitskiyning ajoyib g'oyasi. Bu Boyer-Mur algoritmiga o'xshaydi, har bir qadamda qidiruv satrining taxminan uzunligini o'tkazib yuboradi. Asosiy farq shundaki, u noto'g'ri mosliklarni kamaytirish uchun bir vaqtning o'zida ikkita baytni tekshiradi.

Bizning amalga oshirishimiz har bir qidiruv uchun 64K qidiruv jadvalini yaratishni talab qiladi, ammo bu biz qidirayotgan gigabayt maʼlumotlarga nisbatan hech narsa emas. Ichki halqa bir yadroda soniyasiga bir necha gigabaytni qayta ishlaydi. Amalda, barqaror ishlash har bir yadroda sekundiga 1,25 Gb ni tashkil qiladi va yaxshilash uchun joy mavjud. Ichki pastadirdan tashqarida qo'shimcha xarajatlarning bir qismini yo'q qilish mumkin va biz Java o'rniga C ichidagi ichki halqa bilan tajriba o'tkazishni rejalashtirmoqdamiz.

Biz kuch ishlatamiz

Biz jurnallarni qidirishni "taxminan" amalga oshirish mumkinligini muhokama qildik, ammo bizda qancha "quvvat" bor? Juda ko'p.

1 yadro: To'g'ri ishlatilsa, zamonaviy protsessorning bitta yadrosi o'z-o'zidan juda kuchli.

8 yadro: Biz hozirda Amazon hi1.4xlarge va i2.4xlarge SSD serverlarida ishlayapmiz, ularning har biri 8 yadroli (16 ta ip). Yuqorida aytib o'tilganidek, bu yadrolar odatda fon operatsiyalari bilan band. Foydalanuvchi qidiruvni amalga oshirganda, fondagi operatsiyalar to'xtatiladi va qidiruv uchun barcha 8 yadro bo'shatiladi. Qidiruv odatda bir soniya ichida tugaydi, shundan so'ng fon ishi tiklanadi (bosish dasturi qidiruv so'rovlarining to'siqlari muhim fon ishiga xalaqit bermasligini ta'minlaydi).

16 yadro: ishonchliligi uchun biz serverlarni master/slave guruhlariga ajratamiz. Har bir usta o'z buyrug'i ostida bitta SSD va bitta EBS serveriga ega. Agar asosiy server ishlamay qolsa, SSD server darhol o'z o'rnini egallaydi. Deyarli har doim master va slave yaxshi ishlaydi, shuning uchun har bir ma'lumot blokini ikki xil serverda qidirish mumkin (EBS slave server zaif protsessorga ega, shuning uchun biz buni hisobga olmaymiz). Biz vazifani ular o'rtasida taqsimlaymiz, shunda bizda jami 16 yadro mavjud.

Ko'p yadrolar: Yaqin kelajakda biz maʼlumotlarni serverlar boʻylab shunday tarqatamizki, ularning barchasi har bir ahamiyatsiz soʻrovni qayta ishlashda ishtirok etadi. Har bir yadro ishlaydi. [Eslatma: biz rejani amalga oshirdik va qidiruv tezligini 1 TB / s ga oshirdik, maqolaning oxiridagi eslatmaga qarang].

Oddiylik ishonchlilikni ta'minlaydi

Shafqatsiz kuch usulining yana bir afzalligi uning etarlicha izchil ishlashidir. Odatda, qidiruv muammo va ma'lumotlar to'plamining tafsilotlariga juda sezgir emas (menimcha, shuning uchun u "qo'pol" deb ataladi).

Kalit so'z indeksi ba'zida juda tez natijalar beradi, ba'zida esa yo'q. Aytaylik, sizda 50 Gb logingiz bor, unda "customer_5987235982" atamasi uch marta uch marta uchraydi. Ushbu atama uchun qidiruv to'g'ridan-to'g'ri indeksdan uchta joyni hisoblaydi va bir zumda yakunlanadi. Ammo murakkab joker belgilar yordamida qidirish minglab kalit so'zlarni skanerlashi va uzoq vaqt talab qilishi mumkin.

Boshqa tomondan, qo'pol qidiruvlar har qanday so'rov uchun ko'proq yoki kamroq tezlikda amalga oshiriladi. Uzoq so'zlarni qidirish yaxshiroq, lekin hatto bitta belgini qidirish juda tez.

Qo'pol kuch usulining soddaligi uning ishlashi nazariy maksimalga yaqinligini bildiradi. Kutilmagan diskni haddan tashqari yuklash, blokirovkalash, ko'rsatgichni quvish va muvaffaqiyatsizlikning minglab boshqa sabablari uchun kamroq imkoniyatlar mavjud. Men o'tgan hafta eng band serverimizda Scalyr foydalanuvchilari tomonidan qilingan so'rovlarni ko'rib chiqdim. 14 000 ta soʻrov boʻlgan. Ularning atigi sakkiztasi bir soniyadan ko'proq vaqtni oldi; 99% 111 millisekundda bajarildi (agar siz jurnalni tahlil qilish vositalaridan foydalanmagan boʻlsangiz, menga ishoning: bu tez).

Xizmatdan foydalanish qulayligi uchun barqaror, ishonchli ishlash muhim ahamiyatga ega. Agar u vaqti-vaqti bilan kechiksa, foydalanuvchilar uni ishonchsiz deb bilishadi va undan foydalanishni istamaydilar.

Qidiruvga kirish

Bu erda Scalyr qidiruvini amalda ko'rsatadigan qisqa animatsiya. Bizda har bir ommaviy Github omboridagi har bir voqeani import qiladigan demo hisob qaydnomamiz bor. Ushbu demoda men bir haftalik ma'lumotlarni ko'rib chiqaman: taxminan 600 MB xom jurnallar.

Video mening ish stolimda (serverdan taxminan 5000 kilometr uzoqlikda) maxsus tayyorgarliksiz jonli ravishda yozib olingan. Siz ko'rgan ishlash asosan bunga bog'liq veb-mijozlarni optimallashtirish, shuningdek, tez va ishonchli backend. "Yuklash" indikatorisiz pauza bo'lganda, men bosmoqchi bo'lgan narsani o'qish uchun men pauza qilaman.

1 TB/s tezlikda qidirish

Xulosa

Katta hajmdagi ma'lumotlarni qayta ishlashda yaxshi algoritmni tanlash muhim, ammo "yaxshi" "hayoliy" degani emas. Sizning kodingiz amalda qanday ishlashini o'ylab ko'ring. Algoritmlarning nazariy tahlili real dunyoda katta ahamiyatga ega bo'lishi mumkin bo'lgan ba'zi omillarni qoldiradi. Oddiy algoritmlarni optimallashtirish osonroq va chekka vaziyatlarda barqarorroq.

Shuningdek, kod qaysi kontekstda bajarilishi haqida o'ylang. Bizning holatlarimizda fon vazifalarini boshqarish uchun bizga etarlicha kuchli serverlar kerak. Foydalanuvchilar qidiruvni nisbatan kamdan-kam boshlashadi, shuning uchun biz har bir qidiruvni yakunlash uchun zarur bo'lgan qisqa muddatga butun serverlar guruhini qarzga olishimiz mumkin.

Qo'pol kuch usulidan foydalanib, biz jurnallar to'plami bo'ylab tez, ishonchli va moslashuvchan qidiruvni amalga oshirdik. Umid qilamizki, bu g'oyalar sizning loyihalaringiz uchun foydali bo'ladi.

Tahrirlash: Sarlavha va matn so‘nggi bir necha yil ichida ish unumdorligi oshishini aks ettirish uchun “Sekundida 20 GB tezlikda qidirish”dan “Sekundida 1 TB tezlikda qidirish” ga o‘zgartirildi. Tezlikning bunday o'sishi, birinchi navbatda, mijozlar bazamizning ko'payishiga xizmat ko'rsatish uchun bugungi kunda EC2 serverlarining turi va sonining o'zgarishi bilan bog'liq. Tez orada operatsion samaradorlikni yana bir keskin oshiradigan o'zgarishlar bo'ladi va biz ularni baham ko'rishni kuta olmaymiz.

Manba: www.habr.com

a Izoh qo'shish