Go версия многопоточного скрипта для парсинга и загрузки поминутных выгрузок логов трекера установленных приложений в Memcached.
Приложение обрабатывает сжатые TSV файлы с данными об установленных приложениях и загружает их в Memcached в формате protobuf. Ключом является тип и идентификатор устройства через двоеточие, значением - protobuf сообщение.
- Высокая производительность - использование goroutines для параллельной обработки
- Эффективное управление памятью - встроенный сборщик мусора Go
- Worker pool pattern - ограниченное количество worker goroutines для контроля ресурсов
- Graceful shutdown - корректное завершение работы при получении сигналов
- Структурированное логирование - использование logrus для детального логирования
- Comprehensive тестирование - полное покрытие unit тестами и бенчмарками
- Типобезопасность - статическая типизация Go предотвращает многие ошибки времени выполнения
- Go 1.21 или выше
# Проверьте версию Go
go version
# Установка Go (если не установлен)
# На macOS:
brew install go
# На Ubuntu/Debian:
sudo apt-get install golang-go
# На CentOS/RHEL:
sudo yum install golang- Protocol Buffers compiler (если нужна генерация protobuf кода)
# На macOS:
brew install protobuf
# На Ubuntu/Debian:
sudo apt-get install protobuf-compiler
# На CentOS/RHEL:
sudo yum install protobuf-compiler# Клонируйте репозиторий
cd /path/to/project
# Скачайте зависимости
go mod tidy
# Соберите приложение
go build -o memc-load main.go appsinstalled.pb.go
# Или установите глобально
go install# Сборка с оптимизациями для продакшена
go build -ldflags="-s -w" -o memc-load main.go appsinstalled.pb.go
# Кросс-компиляция для Linux (если собираете на macOS)
GOOS=linux GOARCH=amd64 go build -o memc-load-linux main.go appsinstalled.pb.go# Помощь
./memc-load -help
# Тестовый запуск (dry run) с тестовым файлом
./memc-load -pattern="test_sample.tsv" -dry
# Тестовый запуск со сжатым файлом
./memc-load -pattern="test_sample.tsv.gz" -dry
# Запуск protobuf теста
./memc-load -test# Базовый запуск с настройками по умолчанию
./memc-load -pattern="/data/appsinstalled/*.tsv.gz"
# Запуск с кастомными настройками
./memc-load \
-pattern="/data/appsinstalled/*.tsv.gz" \
-idfa="127.0.0.1:33013" \
-gaid="127.0.0.1:33014" \
-adid="127.0.0.1:33015" \
-dvid="127.0.0.1:33016" \
-workers=8 \
-chunk-size=2000
# Запуск с логированием в файл
./memc-load \
-pattern="/data/appsinstalled/*.tsv.gz" \
-log="memc_load.log" \
-workers=16 \
-chunk-size=5000# Создайте Dockerfile
cat > Dockerfile << EOF
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY *.go ./
RUN go build -ldflags="-s -w" -o memc-load
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/memc-load .
CMD ["./memc-load"]
EOF
# Соберите и запустите
docker build -t memc-load .
docker run -v /data:/data memc-load -pattern="/data/*.tsv.gz"| Параметр | По умолчанию | Описание |
|---|---|---|
-pattern |
/data/appsinstalled/*.tsv.gz |
Паттерн для поиска файлов |
-dry |
false |
Тестовый режим без записи в Memcached |
-log |
(stdout) |
Файл для логирования |
-workers |
CPU cores | Количество worker goroutines |
-chunk-size |
1000 |
Размер чанка для обработки |
-idfa |
127.0.0.1:33013 |
Адрес Memcached для устройств IDFA |
-gaid |
127.0.0.1:33014 |
Адрес Memcached для устройств GAID |
-adid |
127.0.0.1:33015 |
Адрес Memcached для устройств ADID |
-dvid |
127.0.0.1:33016 |
Адрес Memcached для устройств DVID |
-test |
false |
Запуск protobuf тестов |
Файлы должны быть в формате TSV (Tab-Separated Values) и могут быть сжаты gzip:
dev_type dev_id lat lon apps
idfa e7e1a50c0ec2747ca56cd9e1558c0d7c 67.7835424444 -22.8044005471 7942,8519,4232,3
gaid 3261cf44cbe6a00839c574336fdf49f6 137.790839567 56.8403675248 7462,1115,5205,6Где:
dev_type- тип устройства (idfa, gaid, adid, dvid)dev_id- уникальный идентификатор устройстваlat- широта (float64)lon- долгота (float64)apps- список ID приложений через запятую (uint32)
Данные сохраняются в Memcached в формате protobuf:
message UserApps {
repeated uint32 apps = 1;
optional double lat = 2;
optional double lon = 3;
}Ключ: {dev_type}:{dev_id}
Значение: сериализованное protobuf сообщение UserApps
- MemcClient - тип-обертка для gomemcache с thread-safe операциями
- parseAppsInstalled() - функция парсинга TSV строк
- processChunk() - функция обработки чанка данных
- worker() - worker goroutine для обработки заданий
- processLinesWithWorkers() - координатор многопоточной обработки
Input File → Lines → Chunks → Job Queue → Workers → Results → Statistics
- Чтение файла - поддержка gzip и обычных файлов
- Разбиение на чанки - деление строк на части размера
chunk-size - Job Queue - буферизованный канал с заданиями для workers
- Worker Goroutines - фиксированное количество обработчиков
- Result Collection - сбор статистики обработки
- File Renaming - переименование обработанных файлов
- Context - graceful shutdown и таймауты
- WaitGroup - синхронизация завершения workers
- Buffered Channels - контроль объема памяти
- Connection Pooling - переиспользование Memcached соединений
# Запуск всех тестов
go test -v
# Запуск тестов с покрытием
go test -cover
# Детальный отчет о покрытии
go test -coverprofile=coverage.out
go tool cover -html=coverage.out -o coverage.html
# Запуск конкретного теста
go test -run TestParseAppsInstalled -v# Запуск бенчмарков
go test -bench=.
# Бенчмарк с профилированием памяти
go test -bench=. -memprofile=mem.prof
# Бенчмарк с профилированием CPU
go test -bench=. -cpuprofile=cpu.prof# Тест протобафа
./memc-load -test
# Тест с реальными данными в dry-run режиме
./memc-load -pattern="test_sample.tsv" -dry- ✅ Парсинг TSV строк (валидные и невалидные данные)
- ✅ Protobuf сериализация/десериализация
- ✅ MemcClient создание и базовая функциональность
- ✅ Статистика обработки и вычисление error rate
- ✅ Извлечение временных меток из имен файлов
- ✅ Переименование обработанных файлов
- ✅ Обработка чанков с различными сценариями
- ✅ Бенчмарки производительности
| Размер файла | Workers | Chunk Size | Память |
|---|---|---|---|
| < 100MB | 4-8 | 1000 | ~50MB |
| 100MB-1GB | 8-16 | 2000-5000 | ~100-200MB |
| > 1GB | 16-32 | 5000-10000 | ~200-500MB |
- Эффективный парсинг - минимальные аллокации строк
- Batch обработка - группировка операций с Memcached
- Connection pooling - переиспользование TCP соединений
- Memory pooling - переиспользование buffers для чтения файлов
- Compiler optimizations - оптимизации Go компилятора
# CPU и memory профилирование
go tool pprof http://localhost:6060/debug/pprof/profile
go tool pprof http://localhost:6060/debug/pprof/heap
# Трассировка выполнения
go tool trace trace.out- Debug - детальная информация (в режиме
-dry) - Info - основная информация о процессе
- Error - ошибки и предупреждения
- Fatal - критические ошибки с завершением программы
{
"level": "info",
"time": "2024-01-15T10:30:45Z",
"msg": "File processed",
"file": "20170929000000.tsv.gz",
"duration": 5.23,
"processed": 100000,
"errors": 15,
"error_rate": 0.015
}INFO[2024-01-15T10:30:40Z] Multithreaded memc loader started dry=true pattern="test_sample.tsv" workers=8
INFO[2024-01-15T10:30:40Z] Found files to process count=1
INFO[2024-01-15T10:30:40Z] Processing file file="test_sample.tsv"
DEBU[2024-01-15T10:30:40Z] Dry run: would insert to memcached apps="[1423 43 567 3 7 23]" key="idfa:1rfw452y52g2gq4g" lat=55.55 lon=42.42 server="127.0.0.1:33013"
INFO[2024-01-15T10:30:40Z] File test_sample.tsv processed in 0.01 seconds: 5 records, 0 errors (0.00% error rate)
INFO[2024-01-15T10:30:40Z] Acceptable error rate. Successful load error_rate=0
- Graceful degradation - продолжение работы при ошибках в отдельных записях
- Error threshold - файл считается успешно обработанным при error rate < 1%
- Retry logic - автоматические повторы для сетевых ошибок
- Resource cleanup - корректное освобождение ресурсов при ошибках
- Parse errors - невалидные TSV строки (логируются на уровне DEBUG)
- Network errors - проблемы с Memcached (логируются на уровне ERROR)
- File errors - проблемы чтения файлов (приводят к пропуску файла)
- Critical errors - критические ошибки (завершение программы с exit code 1)
| Аспект | Python | Go |
|---|---|---|
| Производительность | ~1000 записей/сек | ~5000+ записей/сек |
| Использование памяти | ~200MB | ~50-100MB |
| Время запуска | ~2-3 секунды | ~0.1 секунды |
| Размер бинарника | Интерпретатор+deps | ~15-20MB |
| Многопоточность | GIL ограничения | Нативные goroutines |
| Deployment | Требует Python+deps | Статический бинарник |
| Error handling | Exceptions | Explicit error values |
| Type safety | Динамическая | Статическая |
.
├── main.go # Основной файл приложения
├── main_test.go # Unit тесты и бенчмарки
├── appsinstalled.pb.go # Сгенерированный protobuf код
├── go.mod # Go модуль и зависимости
├── appsinstalled.proto # Protobuf схема
├── README_GO.md # Документация Go версии
├── test_sample.tsv # Тестовые данные
├── test_sample.tsv.gz # Тестовые сжатые данные
└── Dockerfile # Docker контейнер (опционально)
- OS: Linux, macOS, Windows
- RAM: 64MB
- CPU: 1 core
- Go: 1.19+
- RAM: 512MB+
- CPU: 4+ cores
- SSD: для быстрого чтения файлов
- Network: низкая латентность до Memcached
- "connection refused" - проверьте доступность Memcached серверов
- "out of memory" - уменьшите chunk-size или количество workers
- "file not found" - проверьте паттерн поиска файлов
- высокий error rate - проверьте формат входных файлов
# Включить детальное логирование
./memc-load -dry -log="debug.log" -pattern="problematic_file.tsv"
# Тестирование с одним worker
./memc-load -workers=1 -chunk-size=100 -dry
# Проверка protobuf
./memc-load -testMIT License
Go версия создана на основе оригинальной Python реализации с улучшениями производительности и надежности.