Upload
yandex
View
2.063
Download
2
Embed Size (px)
DESCRIPTION
На примере Python, MongoDB и Яндекс.Такси рассказывается о том, как хранить логи сервиса в базе данных — о том, какие задачи помогает решать такое хранилище логов и чем оно отличается от других, более распространенных вариантов.
Citation preview
Как хранить логи сервиса в базе данныхАлексей КирпичниковСтарший разработчикЯ.Субботник, Екатеринбург, 6 июля 2013 года
Яндекс.Такси
Типичное устройство логов
Balancer (nginx, lighttpd, etc.)access.logerror.log
Backend (django, twisted, etc.)main.logtraceback.log
• проблемы с сортировкой и поиском• проблемы с хранением сложных данных• недоступность для простых смертных
Чем плохи файлы?
• capped и TTL-коллекции• гибкая схема• шардирование• удобный поиск по метаданным
MongoDB
Что записывать в базу?
Что записывать в базу?
Что записывать в базу?
log = {}log['request'] = { 'user_phone': '+79122250228', 'body': request_body}log['inner'] = []...log['inner'].append('something happened')...log['inner'].append('something else happened')...log['response'] = { 'code': 200, 'body': response_body}
db.logs.insert(log)
Ужасная идея
Одна запись на один запрос — плохая идея
db.logs.insert({'_id': 'someid', 'request': { 'user_phone': '+79122250228', 'body': request_body }})...db.logs.update({'_id': 'someid'}, {'$push': {'inner': 'something happened'}})...db.logs.update({'_id': 'someid'}, {'$push': {'inner': 'something else happened'}})...db.logs.update({'_id': 'someid'}, {'$set': {'response': {'code': 200}}})
Довольно плохая идея
Операция update — плохая идея, если у вас MongoDB
Плохая идея
db.logs.insert({ '_type': 'request', 'user_phone': '+79122250228', 'body': request_body})...db.logs.insert({ '_type': 'inner', 'user_phone': '+79122250228', 'message': 'something happened'})...db.logs.insert({ '_type': 'response', 'user_phone': '+79122250228', 'code': 200})
Нет смысла хранить метаданные в каждом логе
Уже лучше
db.logs.insert({ '_type': 'request', '_link': 'somelink', 'user_phone': '+79122250228', 'body': request_body})...db.logs.insert({ '_type': 'inner', '_link': 'somelink', 'message': 'something happened'})...db.logs.insert({ '_type': 'response', '_link': 'somelink', 'code': 200})
Чем меньше записей в коллекции, тем удобнее с ней
работать
С этим можно жить
db.logs_request.insert({ '_link': 'somelink', 'body': request_body})...db.logs_inner.insert({ '_link': 'somelink', 'message': 'something happened'})...db.logs_response.insert({ '_link': 'somelink', 'user_phone': '+79122250228', 'code': 200})
• минимальное вмешательство в основной поток• гибкая адаптация под нагрузку• дублирование в файловые логи
Отказоустойчивость
• 50 RPS в среднем, 100-150 в пике• хранятся логи за 7 дней• около 20 миллионов записей• остальное - в файлах
Как это работает в Такси?
Старший разработчикЯндекс.Такси
Спасибо
Алексей Кирпичников