Алматы кептелістері vs BigQuery: Біз 1 000 000 курьер бағдарын қалай талдап, локальді жарнаманы оңтайландырдық
Жұма. Кешкі сағат 19:00. Алматы, Әл-Фараби даңғылы қып-қызыл болып тұр. Жүргізушілер рульді ұрып, Яндекс Картаға қарап, күрсінумен уақыт өткізуде. Дәл осы сәт — жарнама берушілер үшін алтын уақыт. Неге? Өйткені адамның назары 100% бос, ал оның геолокациясы келесі 40 минут бойы өзгермейді. Осы бос уақытты аудиокітаптарға, жақын маңдағы мейрамханалардан тамаққа тапсырыс беруге немесе стресске қарсы қосымшаларға бағыттасақ қайтеді?
Бүгін біз Google Cloud (BigQuery GIS, Pub/Sub) көмегімен қаладағы миллиондаған координаттарды қалай талдап, «кептеліс полигондарын» нақты уақытта қалай тұрғызғанымызды және осы деректерді банерлік жарнаманы (Google Publisher Tag арқылы) 300%-ға дейін тиімдірек ету үшін қалай қолданғанымызды архитектуралық деңгейде талдаймыз.
Архитектура: Координаттар хаосынан нақты полигондарға дейін
Бізде серіктес курьерлік қызметтен (иә, сол сары және жасыл сөмкелері бар жігіттер) келетін үздіксіз гео-деректер ағыны бар. Олардың қолданбасы әр 10 секунд сайын MQTT арқылы локацияны жіберіп отырады. Бұл дегеніміз — секундына мыңдаған оқиғалар (events).
Егер біз мұның бәрін тікелей дерекқорға (PostgreSQL) жазатын болсақ, база бірнеше минут ішінде өліп қалады. Сондықтан біз серверсіз (serverless) ағындық архитектураны таңдадық.
1-қадам: Pub/Sub және Dataflow арқылы деректерді қабылдау
Барлық координаттар Google Cloud Pub/Sub топигіне түседі. Бұл біздің амортизаторымыз. Ол секундына миллиондаған хабарламаларды ешқандай баптаусыз-ақ қабылдай алады.
Pub/Sub-тан деректерді оқу үшін біз Cloud Dataflow (Apache Beam) құбырын (pipeline) көтердік. Оның міндеті — «қоқысты» тазарту: GPS секірулерін (аномалияларды) алып тастау, деректерді байыту (мысалы, H3 хэштерін қосу) және оларды сақтауға жіберу.
# Dataflow (Apache Beam) құбырының фрагменті
import apache_beam as beam
import json
def parse_and_clean_gps(message):
data = json.loads(message)
# GPS аномалияларын сүзу (мысалы, Қапшағайдағы нүктелерді алып тастау)
if 43.0 < data['lat'] < 43.6 and 76.6 < data['lon'] < 77.2:
yield data
(p
| 'ReadFromPubSub' >> beam.io.ReadFromPubSub(subscription='projects/ozat-kz/subscriptions/gps-sub')
| 'CleanData' >> beam.FlatMap(parse_and_clean_gps)
| 'WriteToBigQuery' >> beam.io.WriteToBigQuery(
table='ozat-kz:traffic_dataset.raw_gps',
create_disposition=beam.io.BigQueryDisposition.CREATE_NEVER,
write_disposition=beam.io.BigQueryDisposition.WRITE_APPEND
)
)GitHub-тағы кодты көру (OZAT-kz)
2-қадам: BigQuery GIS — Кептелістерді табу магиясы
Сонымен, бізде raw_gps кестесінде миллиондаған нүктелер бар. Енді ең қызықтысы басталады. Бізге жай ғана нүктелер емес, кептеліс полигондары (аудандары) қажет.
Біз BigQuery GIS (Geographic Information Systems) функцияларын қолданамыз. Бұл — геометриялық есептеулерді SQL арқылы петабайт деректерге секундтар ішінде жасауға мүмкіндік беретін құрал.
Логика келесідей: 1. Біз соңғы 5 минуттағы курьерлердің жылдамдығын есептейміз (егер ол 15 км/сағ-тан төмен болса — ол кептелісте). 2. Осындай "баяу" нүктелерді бір-бірінен 50 метр радиуста болса, ST_CLUSTERDBSCAN функциясы арқылы кластерлерге біріктіреміз. 3. Содан кейін осы кластерленген нүктелердің үстінен виртуалды полигон сызамыз (ST_CONVEXHULL).
-- Кептеліс полигонын құру SQL сұрауы
SELECT
ST_CONVEXHULL(ST_UNION_AGG(geo_point)) as traffic_jam_polygon,
COUNT(DISTINCT courier_id) as stuck_couriers_count
FROM clustered_data
WHERE cluster_id IS NOT NULL
GROUP BY cluster_id;GitHub-тағы кодты көру (OZAT-kz)
Бұл процесс әр 3 минут сайын қайталанады!
PageSpeed Insights-тің жасыл аймағы: сайтты оңтайландыру бизнесіңіз үшін неліктен маңызды екенінің 3 себебі
Клиентпен синхрондау: Полигондарды қолданбаға жеткізу
BigQuery-де кептелістерді есептеу — керемет. Бірақ дәл қазір телефонда қолданбаны ашып отырған пайдаланушының осы полигонның ішінде екенін қалай білеміз?
Мобильді қолданбадан тікелей BigQuery-ге сұрау жасауға болмайды — бұл өте баяу (2-3 секунд) және өте қымбат. Сондықтан біз әр 3 минут сайын BigQuery-ден өзекті кептеліс полигондарын алып, оларды Redis (Cloud Memorystore)-ға салатын Cloud Function орнаттық.
Пайдаланушы біздің қолданбаны (немесе жарнамамыз бар сайтты) ашқан кезде, біз оның GPS координаттарын аламыз (әрине, рұқсатымен) және Golang-та жазылған микросервисімізге өте жылдам сұрау жасаймыз. Микросервис нүктенің жадтағы полигондармен қиылысуын (Point-in-Polygon) небәрі 1 миллисекундта тексереді.
AdTech: Google Publisher Tag арқылы динамикалық таргетинг
Ендігі кезек — монетизация. Біз Google Ad Manager-мен интеграцияланғанбыз. Әдетте жарнама желісі не көрсету керектігін өзі шешеді. Бірақ біз оған Google Publisher Tag (GPT) кітапханасындағы Key-Value Targeting (Кілт-мән таргетингі) технологиясы арқылы көмектесе аламыз.
Егер біздің микросервис пайдаланушының кептелісте екенін (isInJam: true) деген жауап қайтарса, біз гуглдан баннер сұрамас БҰРЫН жарнамалық слотқа параметрді динамикалық түрде қосамыз.
// Қосымшадағы/сайттағы клиенттік код
// GPT + React интеграциясының толық мысалын GitHub-тан іздеңіз
async function initAds(userLat, userLon) {
// 1. Біздің кептеліс кэшімізді жылдам тексереміз
const trafficStatus = await checkTrafficJam(userLat, userLon);
window.googletag = window.googletag || {cmd: []};
googletag.cmd.push(function() {
var slot = googletag.defineSlot('/1234567/almaty_app_banner', [300, 250], 'div-gpt-ad-123')
.addService(googletag.pubads());
// 2. ҚҰПИЯ ИНГРЕДИЕНТ: Кептеліс контекстін Ad Manager-ге береміз
if (trafficStatus.isInJam) {
slot.setTargeting('context', 'traffic_jam');
slot.setTargeting('jam_severity', trafficStatus.severity); // e.g. '10_points'
} else {
slot.setTargeting('context', 'moving');
}
googletag.enableServices();
googletag.display('div-gpt-ad-123');
});
}GitHub-тағы кодты көру (OZAT-kz)
Google Ad Manager интерфейсінің өзінде біздің Trafficking-мамандарымыз (жарнамашылар) арнайы премиум науқандар (Line Items) жасады. Бұл науқандар ТЕК context=traffic_jam болған жағдайда ғана белсендіріледі. Жарнама берушілер (аудиокітап сервистері, онлайн-кинотеатрлар, аудандағы жергілікті мейрамханалар) бұл көрсетілімдер үшін бізге жоғары CPM төлейді, өйткені конверсияның жынды болатынын біледі.
Нәтижелер: А/В Тестілеу және Метрикалар
Біз 1 айға А/В тест іске қостық. Кептелісте тұрған пайдаланушылардың жартысына біз кәдімгі жарнама (Random) көрсеттік. Қалған жартысына — таргетингтелген "кептеліс" жарнамасын (Audiobooks, Food Pickup, Anti-stress apps) көрсеттік.
- CTR (Click-Through Rate): Көңілсіз 1.2%-дан пиктік сағаттарда (18:00 - 20:00) сенгісіз 4.5%-ға дейін өсті.
- eCPM (1000 көрсетілімнің тиімді құны): 210%-ға өсті. Жарнама берушілер біздің "қамалған" аудиториямыз үшін аукционда соғыса бастады.
- User Feedback: Қызығы, негатив азайды. Адамдар саппортқа былай деп жазды: «Сіздердің аудиоспектакль жарнамаларыңыз мені Сайын/Жандосовтағы жүйке жұқаруынан құтқарды». Релевантты жарнама контент ретінде қабылданады.
Кептелісте тұрған және қарапайым пайдаланушылар арасындағы аудиокітаптар мен фастфуд жарнамасының басылу жиілігін (CTR) салыстыру.
Қорытындылар
Гео-деректер — бұл жаңа мұнай. Бірақ шикі мұнай сіздің көлігіңізге май құймайды. Google Cloud Pub/Sub және BigQuery GIS сияқты құралдар миллиондаған координаталардың хаосынан мағына шығаруға мүмкіндік беретін сол мұнай өңдеу зауыты болып табылады.
Терең бэкенд-аналитиканы (Data Engineering) фронтенд-монетизация технологияларымен (AdTech / GPT) біріктіру Қазақстандағы мобильді қосымшалар мен веб-сайттардан ақша табу үшін мүлдем жаңа тауашалар ашады.
Сөз арзан, ал код мәңгілік екенін ұмытпаңыз. Егер сізде архитектура бойынша сұрақтар болса немесе интеграцияны талқылағыңыз келсе — сіздерді түсініктемелерде күтеміз.

Рустам Шарафутдинов
Google Cloud архитектурасы саласындағы сарапшы және 15 жылдан астам тәжірибесі бар Senior Full-Stack әзірлеушісі. Ақауға төзімді архитектураларға, жоғары жүктемелі жобаларды оңтайландыруға және AI (Vertex AI) интеграциясына маманданған.