mysql — хранит и извлекает миллионы JSON-кодированных событий (PHP / база данных)

Предположим, у нас есть следующий пример данных события JSON:

{
"eventId":"eb1363c3-6bf7-4a42-9daa-66270b922367",
"timestamp":"2014-10-28T09:12:22.628Z",
"ip":"1.2.3.4",
"device":{
"type":"mobile",
"os":{
"name":"iOS",
"version":"7.1.1"},
"name":"iPhone 4/4s",
...
},
"eventType":"AddedProductToCart",
"store":"US",
"product":{
"sku":"ABC123",
"name":"Yellow Socks",
"quantity":1,
"properties":{
"foo":"bar",
"bar":1
}
...
},
"user":{
"id":123456,
"name":"jeff",
"type":"registered"...
}
}

в то время как «eventId» и «timestamp» будут всегда предоставляться, структура массива может отличаться и не одинакова. Существует около 30-40 уникальных типов событий, все с различными свойствами событий. Большинство данных события имеют вложенную структуру.

Каков наилучший подход для хранения этих свойств события? Я посмотрел в MongoDB, DynamoDB и проект под названием EventStore (http://geteventstore.com). Очевидно, я также рассмотрел MySQL, но мне интересно, как он будет работать в нашем случае использования.

Хранение данных — это только первая часть. После этого мы должны иметь возможность запрашивать нашу базу данных / хранилище событий сложными запросами, подобными следующим (и не только извлекать, например, по индексированному идентификатору):

select all events where eventType is "AddedProductToCart" and timestamp > 2 weeks ago
-> should return all "AddedProductToCart" from 2 weeks ago until now

select all events where device.OS.name is "iOS" and device.OS.version is "7.1.1"-> should return all events from iOS 7.1.1

и т.п.

Мы ожидаем около 10 миллионов событий в месяц. В среднем это составляет 3-4 записи в секунду, и, вероятно, больше похоже на 30-40 операций записи в секунду в пиковом / наихудшем сценарии. Хранение не должно быть проблемой — общий размер на событие, скорее всего, не будет превышать 1 или 2 КБ (это составляет 1-2 ГБ на 1 миллион событий).

Запрашивающая часть должна быть на PHP, желательно. DynamoDB, например, имеет SDK для PHP, который, безусловно, облегчит нашу

Каково было бы наше лучшее решение для этого? Письма должны быть быстрыми, и наши запросы также должны быть приемлемыми. Короче говоря, мы ищем дешевое хранилище данных, которое бы легко сохраняло и затем извлекало (-> запрашивало не только с помощью индекса, но и с помощью свойств событий из вложенного JSON) наши данные.

Спасибо за любые предложения, и если для правильного ответа на этот вопрос потребуется дополнительная информация, я был бы рад предоставить дополнительную информацию.

0

Решение

DynamoDB от Amazon предлагает полностью управляемое (автоматическое масштабирование), надежное и предсказуемое решение.

Судя по ожидаемому объему трафика и данных, бесплатный уровень DynamoDB, состоящий из 25 единиц емкости записи / чтения и 25 ГБ, покрывает ваши операции в основном бесплатно.

Каждая единица емкости записи эквивалентна записи 1 КБ данных, поэтому, если вы ожидаете 3-4 записи в секунду данных 2 КБ, вам необходимо подготовить 8 WCU. Кроме того, производительность DynamoDB чрезвычайно предсказуема с быстрой задержкой в ​​одну миллисекунду. Для получения дополнительной информации о бесплатном уровне, проверьте http://aws.amazon.com/dynamodb/pricing/.

С точки зрения вашего набора данных, для объектов, не относящихся к документам, запрос относительно прост с использованием глобальных вторичных индексов.

Вот пример из PHP SDK.

$twoWeeksAgo = date("Y-m-d H:i:s", strtotime("-14 days"));
$response = $dynamoDB->query(array(
"TableName" => <Table Name>,
"KeyConditions => array(
"EventType" => array(
"ComparisonOperator" => ComparisonOperator::EQ,
"AttributeValueList" => array(
array(Type::STRING => "AddedProductToCart")
)
),
"Timestamp" => array(
"ComparisonOperator" => ComparisonOperator:GE,
"AttributeValueList" => array(
array(Type::STRING => $twoWeeksAgo)
)
)
)
));

Вы можете запросить «Device.OS.Name» и «Device.OS.Version» с помощью сканирования, но есть несколько оптимизаций, которые вы должны рассмотреть в зависимости от того, какие запросы вы хотите сделать.

Если вы хотите выполнять специальные запросы, вы можете выполнить параллельный вызов сканирования, а затем применить ScanFilter, используя ConditionalExpression для ваших вложенных атрибутов. Распараллеливая ваше сканирование, вы оптимизируете потребление единиц чтения емкости на вашем столе, а также скорость операции. Для получения дополнительной информации о параллельном сканировании, проверьте http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html#QueryAndScanParallelScan.

В качестве альтернативы, если у вас есть атрибуты select, которые вы хотите запросить, рассмотрите возможность создания некоторых из атрибутов верхнего уровня полей или переместите их в отдельную таблицу, сгладьте необходимые атрибуты (например, от os.name до osname) и получите обратную ссылку на ваш оригинал. пункт (в основном относится к вашим документам, как «устройство»). Делая это, вы можете добавлять индексы поверх этих атрибутов и быстро и эффективно запрашивать их. Кроме того, с предварительным объявлением об онлайновой индексации вы сможете добавлять и удалять индексы, если это необходимо, чтобы в скором времени удовлетворить ваши требования.

Если вы хотите обсудить это более подробно или задать общие вопросы об использовании DynamoDB, не стесняйтесь обращаться ко мне с помощью личного сообщения.

Спасибо

2

Другие решения

MongoDB — хорошая ставка здесь. Он может обрабатывать запись / с легко ( mongod видит больше действий на моем ноутбуке).

Упомянутые вами запросы являются основными. Например:

db.collection.find({"device.OS.name":"iOS","device.OS.version":"7.1.1"})

и (сокращено для удобства чтения)

db.collection.find({"eventType":"AddedProductToCart",timestamp:{$gte: ISODate(iso8601String)}})

С правильно установленными индексами они должны быть молниеносными. Вы даже можете использовать индексы TTL для автоматического удаления событий старше определенного времени.

Для анализа данных у вас есть и карта / сокращение, и чрезвычайно мощная структура агрегации MongoDB.

Давайте перейдем к минусам. Хотя с MongoDB масштабирование относительно просто, по некоторым причинам люди считают, что реплицированный сегментированный кластер с автоматическим распределением данных так же прост в управлении, как и остальная часть MongoDB. Ключевое слово в том, что это относительно легко (сравните это с реплицированным разделением данных с MySQL или — Господи, помогите нам — Oracle), но все же у него есть некоторые подводные камни.

Восстановление в определенный момент времени в защищенной среде без использования MMS возможно, но вы действительно должны знать, что делаете, поскольку синхронизация отдельных резервных копий сегментов довольно сложна.

Независимо от того, какую базу данных вы выберете, я настоятельно рекомендую связаться с соответствующим специалистом. Производственные данные являются элементарными, и никакие базы данных с ними не должны планироваться и поддерживаться неспециалистами.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector