Лучший способ иметь хранилище с быстрым доступом для огромного набора данных (5 ГБ)

Существует набор данных размером ~ 5 ГБ. Этот большой набор данных содержит только пару ключ-значение в каждой строке. Теперь это нужно прочитать для значения ключей несколько миллиардов раз.

Я уже пробовал дисковый подход MapDB, но он выдает ConcurrentModification Exception и недостаточно зрел для использования в производственной среде еще.

Я также не хочу иметь его в БД и совершать вызовы миллиард раз (хотя здесь можно выполнить определенный уровень кэширования в памяти).

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


person Amar    schedule 04.12.2012    source источник
comment
Сколько ключей? Какой формат, простой текст типа key=value или что-то двоичное? Как выглядят данные, числовые/строковые клавиши?   -  person Philipp Reichart    schedule 04.12.2012
comment
Это не так уж и много. Это даже уместится в памяти при использовании адекватной машины. В этом случае вы можете поместить его в распределенный кеш.   -  person Jorge González Lorenzo    schedule 04.12.2012
comment
@PhilippReichart: если быть точным, есть 103302034 ключа. И да, это CSV, в каждой строке которого есть key,value.   -  person Amar    schedule 04.12.2012
comment
@ JorgeGonzálezLorenzo, да, но распределенный кеш будет создавать только копию этого файла в каждом узле, это не поможет мне легко получить доступ к значениям, верно?   -  person Amar    schedule 04.12.2012
comment
Как выглядят ключи? Есть дубликаты ключей? Как именно вы хотите их запрашивать, то есть шаблоны чтения/доступа? Если бы ключи можно было представить в виде 32-битных целых чисел, весь набор ключей уместился бы на ‹400 МБ.   -  person Philipp Reichart    schedule 04.12.2012
comment
Нет, дубликатов ключей нет, но могут быть дубликаты значений, но я не думаю, что мы сможем их использовать. У меня есть ключи, и я хотел бы запросить их напрямую. Как вы предлагаете представить его в виде 32-битных целых чисел?   -  person Amar    schedule 04.12.2012
comment
Если ключи на самом деле являются числами (и просто оказались строками из-за формата CSV), вы можете просто parseInt() их и использовать некоторую карту, оптимизированную для int, чтобы сделать все это в памяти. Если вам нужно получить доступ к значениям по ключу, как выглядят значения (формат содержимого/данных, любые свойства, которые можно использовать)? Не могли бы вы описать, как вы будете получать доступ к карте с помощью клавиш: что входит, что должно выйти? Возможно, есть другая более компактная структура данных.   -  person Philipp Reichart    schedule 04.12.2012
comment
Ключи представляют собой смесь цифр и букв. Пример ключа будет похож на AAAAA111111, а значение будет похоже на abcdefghijklmno pqrstuvw, простой текст с одним или двумя словами.   -  person Amar    schedule 04.12.2012
comment
@Amar Вы можете взглянуть на Волдеморта в LinkedIn. Если требуется только поиск, вы можете создать «хранилище только для чтения» Voldemort из ваших данных с помощью задания Hadoop. Мы использовали эту настройку несколько раз из задания MR в качестве поиска KV без каких-либо проблем.   -  person Lorand Bendig    schedule 04.12.2012
comment
@Amar: вы можете заполнить карту в памяти при настройке чтения задачи из файла удаленного кеша. Конечно, это решение не масштабируется, как другие решения, предлагаемые здесь.   -  person Jorge González Lorenzo    schedule 04.12.2012
comment
@LorandBendig: Насколько легко это будет сочетаться с кодом Java?   -  person Amar    schedule 06.12.2012
comment
@JorgeGonzálezLorenzo: Это именно то, чего мы не хотим здесь делать. то есть иметь все в памяти, так как у нас не так много доступной памяти. В любом случае спасибо.   -  person Amar    schedule 06.12.2012
comment
@Amar, когда у вас есть работающий кластер Voldemort, вы можете инициализировать соединение с БД в setup(), выполнить поиск в map() и закрыть соединение в cleanup(). Пример установки соединения: github. com/волдеморт/волдеморт/blob/мастер/пример/java/   -  person Lorand Bendig    schedule 06.12.2012
comment
@LorandBendig: мы не хотели, чтобы для этой цели всегда работал выделенный кластер.   -  person Amar    schedule 13.12.2012


Ответы (4)


Итак, перепробовав кучу вещей, мы теперь используем SQLite.

Вот что мы сделали:

  1. Мы загружаем все данные пары ключ-значение в предварительно определенный файл базы данных (проиндексировали его в ключевом столбце, хотя это увеличило размер файла, но оно того стоило).
  2. Сохраните этот файл (key-value.db) в S3.
  3. Теперь это передается заданиям Hadoop в виде распределенного кеша.
  4. В Configure Mapper/Reducer открывается соединение (около 50 мс) с файлом db.
  5. В методе map/reduce запросите эту базу данных с помощью ключа (это заняло незначительное время, даже не нужно было его профилировать, это было так незначительно!)
  6. Закрыто соединение в методе очистки Mapper/Reducer
person Amar    schedule 13.12.2012

Попробуйте Redis. Кажется, это именно то, что вам нужно.

person AlexR    schedule 04.12.2012
comment
Редис хорош. Но, насколько мне известно, у него нет встроенной таблицы поиска. Это похоже на memcache, не так ли? Но что делать, если у вас не так много свободной памяти. За исключением того, что он поддерживает определенные структуры данных и атомарные операции, такие как увеличение/уменьшение, это не поможет. Дайте мне знать, если вы думаете иначе. - person Amar; 04.12.2012

Я бы попробовал Oracle Berkerley DB Java Edition Эта поддержка Карт и является зрелым и масштабируемым.

person Peter Lawrey    schedule 04.12.2012
comment
Как это было бы полезно в среде mapred? Буду ли я настраивать БД каждый раз при создании кластера. Здесь это работает следующим образом: кластер из 10, 20 машин и т. д. запускается, выполняет некоторые задания, и все они гаснут после выполнения заданий. Мне нужно получить доступ к этим парам ключ-значение внутри этих заданий. И если у нас есть постоянная настройка БД где-то еще (в другом ящике), то сетевую задержку, какой бы малой она ни была, будет трудно сдержать, поскольку поиск происходит несколько миллиардов раз. - person Amar; 04.12.2012
comment
Вы правы в том, что база данных RDBMS — не лучшая идея, но Berkerley DB так не работает, поэтому я и предложил ее. Существует много других решений nosql-database.org, но это одно из самых зрелых. - person Peter Lawrey; 04.12.2012
comment
Спасибо, Питер, позвольте мне проверить это. - person Amar; 04.12.2012
comment
Ради интереса, сколько у вас ключей и какова их средняя длина? - person Peter Lawrey; 04.12.2012
comment
Есть 103302034 ключей. И все они текстовые с 11 символами. - person Amar; 04.12.2012
comment
Попробуйте HBASE на своих узлах Hadoop. - person Thomas Jungblut; 04.12.2012
comment
Можно ли хранить их в отсортированном порядке в виде записей фиксированной длины и загружать их через файлы с отображением памяти? Чтобы выполнить поиск, вы можете выполнить двоичный поиск, который может занять около пары микросекунд. Или вам также нужно иметь возможность изменять данные? - person Peter Lawrey; 04.12.2012
comment
@PeterLawrey Спасибо, Питер :) ваше предложение было очень полезным, и в итоге мы использовали SQLite, и, как вы, возможно, знаете, он использует файлы с отображением памяти внутри. - person Amar; 13.12.2012

Я заметил, что вы пометили это с помощью elastic-map-reduce... если вы работаете на AWS, возможно, DynamoDB подойдет.

Кроме того, я хотел бы уточнить: будет ли этот набор данных вводом для вашего задания MapReduce, или это дополнительный набор данных, доступ к которому будет осуществляться случайным образом во время задания MapReduce?

person Joe K    schedule 05.12.2012
comment
Мы уже пробовали это, но заполнение DynamoDB занимало гораздо больше времени! Если вы пробовали это и знаете, что 103302034 много записей могут быть вставлены в течение допустимого срока, пожалуйста, поделитесь ими со мной. - person Amar; 06.12.2012
comment
Я верю, что они могут быть. Вам просто нужно обеспечить очень высокую пропускную способность записи и использовать многопоточный код для этого. DynamoDB определенно поддерживает не менее 10 000 операций записи в секунду и, возможно, даже больше, если вы обратитесь к AWS и запросите это. Просто убедитесь, что заполняющий его код является либо асинхронным, либо правильно распределенным по потокам, и что он записывает записи с равномерным распределением ключей (т. е. порядок ключей является случайным). - person Joe K; 06.12.2012
comment
Да, Джо, но мы попробовали это в потоковом режиме, использовали даже EMR, чтобы сделать это, как описано ниже: stackoverflow.com/questions/10683136/ Но даже с 1000 в качестве пропускная способность записи он написал всего 40К записей за каких-то 16 часов! - person Amar; 13.12.2012