S3 asosidagi ma’lumotlarni darajalashni joriy etish tajribamiz

S3 asosidagi ma’lumotlarni darajalashni joriy etish tajribamiz

-DB xarajatlari bombasini zararsizlantirgan qutqaruvchi: S3 asosidagi ma’lumotlarni tierlarga ajratish-

Ko‘proq xizmatlar va sezdirmay kattalashgan DB xarajatlari bombasi

So‘nggi loyihalarimizda xizmatlar soni ortib, ko‘plab yangi imkoniyatlarni qo‘shayotgan edik. Natijada ma’lumotlar eksponensial o‘sishi va infratuzilma xarajatlari ham shunga mutanosib ravishda ortishi bilan yuzlashdik.

Mikroxizmatlar arxitekturasini (MSA) qabul qilganimiz sababli, loglar hajmining o‘sishi ayniqsa keskin bo‘ldi. Hatto bitta foydalanuvchi so‘rovi ham gateway orqali ko‘plab mikroxizmatlar bo‘ylab ichki taqsimlangan chaqiruvlar zanjirini ishga tushirardi. Butun tizim bo‘ylab tranzaksiyalarni kuzatish va monitoring qilish uchun har bir mustaqil xizmatning taqsimlangan loglarini sinchiklab qayd etishimiz kerak edi. Natijada bir vaqtning o‘zida juda katta hajmdagi log ma’lumotlari hosil bo‘ldi — bu monolit arxitekturadagi hajm bilan solishtirib bo‘lmaydigan darajada edi.

Dastlab bu taqsimlangan loglar uchun saqlash tizimi sifatida MongoDB’ni tanladik. MSA muhitida har bir xizmat biroz boshqacha log formatidan foydalanishi mumkin, MongoDB’ning moslashuvchan hujjat tuzilmasi esa sxema o‘zgarishlari haqida bosh qotirmaslik imkonini berdi. Uning bir nechta mikroxizmatdan bir vaqtda oqib keladigan ulkan hajmdagi loglarni qayta ishlay oladigan tezkor yozish samaradorligi hamda boshqaruv paneli bilan qulay integratsiyasi ham katta afzalliklar edi.

Biroq mikroxizmatlar soni ortib, xizmatlar tez kengaygani sari, oyiga yuzlab GB bo‘lgan log ma’lumotlari tez orada bir necha TB’gacha kattalashib, ma’lumotlar bazasi sig‘imini tezda to‘ldirdi. Samaradorlik esa bundan ham katta muammo bo‘ldi. Samaradorlikni saqlash uchun MongoDB indekslar va tez-tez foydalaniladigan ma’lumotlarni xotirada (RAM) saqlaydigan WiredTiger kesh mexanizmidan foydalanadi. Log ma’lumotlari hajmi ortgani sayin indekslar ham kattalashdi. Ular cheklangan RAM sig‘imimizdan oshgach, zararli zanjirli reaksiya yuz berdi.-

  • RAM bosimi va disk kiritish-chiqarishidagi to‘siqlar: Xotira kamaygani sari ma’lumotlar bazasi diskdagi sahifalarni ancha tez-tez o‘qib-yozishga majbur bo‘ldi va bu darhol ishlab chiqarish xizmatlarida so‘rovlar kechikishiga olib keldi.

  • Replica set xarajatlarni uch baravar oshirdi: Mavjudlikni ta’minlash uchun yuqori samarali SSD’li uchta EC2 nusxasidan iborat klasterni sozlagan edik. Bu 1 TB logni saqlash uchun aslida yuqori narxli 3 TB xotira haqini to‘lashimiz kerakligini anglatardi.

Amaliyotlarimiz tahlili shuni ko‘rsatdiki, loglarga oid so‘rovlarning aksariyati oxirgi uch kunlik ma’lumotlar bilan cheklangan. Eski loglardan faqat vaqti-vaqti bilan, masalan, hodisadan keyingi tahlil yoki me’yoriy auditlar uchun foydalanilardi. Qimmat DB xotirasi va RAM’ni egallab turgan eski ma’lumotlarni ajratishga qaror qildik. Bu infratuzilma xarajatlarimizni keskin kamaytirardi. Yechimimiz — samaradorlik va xarajatlarni tejashni birgalikda ta’minlaydigan arxitektura, ya’ni ma’lumotlarni tierlarga ajratishni joriy etish bo‘ldi.

Ma’lumotlarni tierlarga ajratish arxitekturasini loyihalash

Ma’lumotlarni tierlarga ajratishning asosiy mohiyati — hamma narsani bitta saqlash tizimiga joylash o‘rniga, foydalanish tezligi va biznes talablariga qarab ma’lumotlarni qayerda saqlashni optimallashtirish. Operatsion yukni kamaytirgan holda xarajatlarni maksimal tejash uchun murakkab, ko‘p pog‘onali tuzilma o‘rniga saqlashni oddiy qilib, atigi ikki tierga — Hot Tier va Cold Tier’ga ajratdik:

- Hot Tier (oxirgi 30 kun): Real vaqt rejimida nosozliklarni tuzatish uchun yuqori samarali tier

  • Saqlash: MongoDB

  • Maqsad: Jonli xatolar monitoringi, yaqinda joriy qilingan imkoniyatlardagi muammolarni kuzatish va MSA xizmatlari bo‘ylab taqsimlangan tracing

  • Loyihalash yondashuvi: Oxirgi bir oylik ma’lumotlar “issiq” ma’lumotlar hisoblanadi. Rivojlantirish va operatsiyalar guruhlari hodisalarga javob berish va muammolarni tuzatish uchun ulardan eng ko‘p so‘rov yuboradi. Shu sababli samaradorlik biz uchun eng ustuvor vazifa hisoblanadi.

- Cold Tier (31 kundan 1 yilgacha): Me’yoriy talablarga rioya qilish va arxivlash uchun xarajatlarni tejaydigan tier

  • Saqlash: AWS S3 Standard

  • Maqsad: Bir necha oy oldingi kam uchraydigan xatolarni kuzatish, uzoq muddatli statistik tahlil va xavfsizlik hamda huquqiy auditlarga javob berish

  • Loyihalash yondashuvi: Bir oydan so‘ng log ma’lumotlari “sovuq” bo‘ladi, chunki ularga yuboriladigan so‘rovlar soni keskin kamayadi. Bu tier uchun barcha indekslarni olib tashlab, ma’lumotlarni S3 Standard’da siqilgan fayllar ko‘rinishida saqlaymiz. S3 Standard’da ma’lumotlarni alohida indekslash xarajati yo‘q va saqlash birligi uchun narxi MongoDB’niki bilan solishtirganda 10–25 baravar yoki undan ham arzon.

Ushbu ikki tierli arxitekturaning muhandislik nuqtayi nazaridan eng katta foydasi — saqlashni hisoblash resurslaridan butunlay ajratishidir. Eski arxitekturada loglar hajmining ortishi nafaqat disk sig‘imini, balki tobora kattalashayotgan indekslarni boshqarish uchun MongoDB serverining o‘zini ham kengaytirishni anglatardi. Boshqacha aytganda, ma’lumotlarni shunchaki “saqlash” uchun qimmat hisoblash va xotira resurslariga birgalikda haq to‘layotgan edik. 30 kundan eski ma’lumotlarni serverlarsiz obyekt saqlash xizmati bo‘lgan S3’ga ko‘chirish orqali ushbu ikki resursni mustaqil ravishda kengaytirish imkoniga ega bo‘ldik. Endi MongoDB faqat oldindan belgilangan oxirgi 30 kunlik ma’lumotlarni saqlaydi va minimal, qat’iy xarajat evaziga yuqori samaradorlikni ta’minlaydi. Shu bilan birga, tarixiy ma’lumotlarning bir necha terabaytini saqlash uchun S3’ning arzon va deyarli cheksiz sig‘imidan foydalanib, infratuzilmamizning kengayuvchanligini maksimal darajaga olib chiqamiz.

Avtomatlashtirish pipeline’ini yaratish

Muhandislar ma’lumotlarni qo‘lda ko‘chirishi va o‘chirishi kerak bo‘lsa, hatto eng ideal arxitektura ham barqaror bo‘lmaydi. MongoDB’dan 30 kundan eski loglarni xavfsiz o‘chirib, S3 Standard’da arxivlash uchun avtomatlashtirilgan ma’lumotlar pipeline’ini yaratdik. Pipeline quyidagi asosiy bosqichlardan iborat:

  1. MongoDB’dan 30 kundan eski loglarni topib, ma’lumotlarni qayta ishlash

  2. Ma’lumotlarning zaxira nusxasini S3’ga olish va nusxani bir yildan keyin avtomatik o‘chiriladigan qilib sozlash

  3. Zaxira nusxasi olingan ma’lumotlarni MongoDB’dan o‘chirish

Haqiqiy ishlab chiqarish muhitida bir kun ichida o‘nlab million log yozuvlari kelib tushishi mumkin. Bu ma’lumotlarning barchasini birdaniga xotiraga yuklash darhol OOM (Out Of Memory) xatosiga olib keladi. Xotiraga tushadigan bosimni kamaytirish uchun quyidagi strategiyalarni qo‘lladik:

  • Kursor asosidagi sahifalash: Ma’lumotlarni bir necha ming yozuvdan iborat (2 000 ta yozuv) to‘plamlarda xavfsiz olish.

  • Diskka oqimli yozish: DB’dan o‘qilgan ma’lumotlarni xotirada saqlash o‘rniga, darhol fayl tizimiga oqim ko‘rinishida uzatib, mahalliy vaqtinchalik faylga (Temp File) yozish.

  • To‘plamlar bilan o‘chirish: Ko‘chirilgan yozuvlarning ID’larini yig‘ib, diskka ortiqcha yuk tushirmaslik uchun ularni 10 000 tadan xavfsiz o‘chirish.

Mana shu asosiy jarayonni amalga oshiradigan migratsiya pipeline’ining kodi.

private <T> void executeLogMigrationPipeline(...) {
    List<String> logIds = new ArrayList<>();

    // 1. 메모리 오버헤드를 방지하기 위한 임시(Temp) 파일 생성
    Path tempFile = Files.createTempFile(filePrefix, ".json");

    // 2. Jackson SequenceWriter를 활용해 디스크로 즉시 스트리밍 (JSON Array 구조)
    try (var fileOut = Files.newOutputStream(tempFile);
         var seqWriter = objectMapper.writer().writeValuesAsArray(fileOut)) {

        int pageCounter = 0;
        int pageSize = 2000;

        while (true) {
            // DB에서 정해진 배치 사이즈만큼 순차 조회
            Pageable pageable = PageRequest.of(pageCounter++, pageSize, Sort.by("registrationTime"));
            List<T> logs = logFinder.apply(targetEpochMillisToMove, pageable);
            if (logs.isEmpty()) break;

            // ID 수집 및 파일에 즉시 기록 (메모리 점유 방지)
            logIds.addAll(logs.stream().map(idExtractor).toList());
            LogHelper.appendLogsToJsonStream(logs, seqWriter);

            if (logs.size() < pageSize) break;
        }
    }

    // 3. S3 스토리지(Depot)로 안전하게 파일 업로드
    if (!logIds.isEmpty() && Files.exists(tempFile)) {
        depotProxy.uploadDTSPFiles(remoteFilePath, new FileSystemResource(tempFile.toFile()), targetEpochMillisToRemoval);

        // 4. 대량의 DB 쓰기 부하를 방지하기 위해 10,000건씩 쪼개서 삭제(Bulk Delete)
        int deleteBatchSize = 10000;
        for (int i = 0; i < logIds.size(); i += deleteBatchSize) {
            List<String> subBatchIds = logIds.subList(i, Math.min(i + deleteBatchSize, logIds.size()));
            batchRemover.accept(subBatchIds);
        }
    }

    // 5. 작업이 끝나면 로컬 임시 파일 자원 해제 (Retry 로직 포함)
    cleanUpTempFile(tempFile);
}

Generiklar (T) va funksional interfeyslardan (BiFunction, Consumer) foydalanadigan loyihalash yondashuvi tufayli ayni migratsiya pipeline’i mantiqini turli log turlari va formatlarida qayta ishlatish imkoniga ham ega bo‘ldik. Endi MongoDB’da faqat eng so‘nggi 30 kunlik loglar saqlanadi va ilgari haddan tashqari kattalashgan indekslarimiz RAM sig‘imiga bemalol sig‘adi. Natijada disk kiritish-chiqarishidagi to‘siqlar butunlay bartaraf etildi va ishlab chiqarish muhitidagi so‘rovlarga o‘rtacha javob berish vaqti (Latency) yaxshilandi. Ilgari sezilarli xarajat bo‘lgan DB xotirasi uchun to‘lovlarni ham tejadik. Bir TB uchun xarajatlarni solishtirganda, S3 Standard MongoDB klasterimizdan ancha arzon bo‘lib chiqdi va umumiy log infratuzilmasi xarajatlarimizning salmoqli qismini tejash imkonini berdi.

Xulosa

Ko‘plab xizmatlar tez sur’atda rivojlanganda, jamoalar ko‘pincha tezkor choraga qo‘l uradi: ma’lumotlar hajmi ortgani sari ma’lumotlar bazasini kengaytiradi. Biroq ma’lumotlarning biznes uchun qiymati va ulardan foydalanish tezligi vaqt o‘tishi bilan muqarrar ravishda o‘zgaradi. S3 asosidagi ma’lumotlarni tierlarga ajratishni joriy etishimiz xarajatlardan bir necha dollar tejash bilangina cheklanmagan; bu biznes talablari va texnik xarajatlar o‘rtasidagi nomutanosiblikni arxitektura darajasida bartaraf etish tajribasi bo‘ldi. Eng qimmat va qudratli saqlash tizimi har doim ham to‘g‘ri tanlov bo‘lavermaydi. Tizimimizdagi ma’lumotlarning tabiati va “haroratini” tushunib, ularni tegishli joyga joylashtirish — infratuzilma xarajatlari bombasiga qarshi kurashayotgan muhandisning haqiqiy vazifasi shudir, balki. Ushbu maqola ma’lumotlar va infratuzilma xarajatlarining o‘sishi bilan kurashayotganlarga foydali maslahat beradi, degan umiddaman.

Hustle Paul

Site footer