Concurrency в Amazon S3

В настоящее время я создаю систему, в которой S3 будет использоваться как постоянный хеш-набор (URL-адрес S3 определяется из данных) множеством компьютеров через Интернет. Если два узла хранят одни и те же данные, он будет сохранен с использованием одного и того же ключа, и поэтому он не будет храниться дважды. Когда объект удаляется, мне нужно знать, используют ли другие другие node (s) эти данные. В этом случае я не удалю его.

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

  • Прочитайте объект с S3.
  • Дезертициализация объекта.
  • Добавить новый node id в список хранения узлов.
  • Сериализовать новый объект (данные для хранения и node -list).
  • Запишите сериализованные данные на S3.

Это создаст форму подсчета ссылок idempotent. Поскольку запросы через Интернет могут быть довольно ненадежными, я не хочу просто подсчитывать количество узлов хранения. Поэтому я сохраняю список вместо счетчика (в случае, если node отправляет один и тот же запроs > 1 раз).

Этот подход работает до тех пор, пока два узла не записываются одновременно. S3 не знает (насколько я знаю) любого способа блокировки объекта, чтобы все эти 5 шагов стали атомарными.

Как бы вы решили эту проблему concurrency? Я рассматриваю возможность реализации некоторой формы оптимизма concurrency. Как мне это сделать для S3? Должен ли я использовать совершенно другой подход?

Ответ 1

Рассмотрим сначала разделение списка блокировки из ваших (защищенных) данных. Создайте отдельный ведро, специфичное для ваших данных, чтобы содержать список блокировок (имя байта должно быть производным от имени вашего объекта данных). Используйте отдельные файлы в этом втором ковше (по одному на node, с именем объекта, полученным из имени node). Узлы добавляют новый объект ко второму ведру перед доступом к защищенным данным, узлы удаляют свой объект из второго ведра, когда они закончены.

Это позволяет вам перечислить второе ведро, чтобы определить, заблокированы ли ваши данные. И позволяет двум узлам одновременно обновлять список блокировок без конфликтов.

Ответ 2

Чтобы добавить то, что сказал amadeus, если ваши потребности не являются реляционными, вы даже можете использовать AWD SimpleDB, значительно дешевле.

Ответ 3

Я не работал с Amazon S3, но вот мое упорство-невежественное предложение.

  • Можете ли вы использовать сегрегацию запроса команды? Будет приятно отделить чтения от команд, так как эта проверка будет выполняться только для команды (DELETE), и вам не нужно ее читать (если я правильно ее понял).

  • Если для такой синхронизации не существует встроенной поддержки, тогда ваше собственное свернутое решение может быть горлом бутылки с точки зрения высокой нагрузки (что может быть разрешено [3] и [4]). Все ваши DELETE должны проходить через центральное место - очередь запросов.

  • Я бы сделал выделенную службу (например, WCF) с параллельной очередью запросов в ней. Каждый раз, когда вам нужно УДАЛИТЬ объект, вы введете элемент в очередь. Служба, в своем собственном темпе, отключит элемент и выполнит все ваши 5 шагов как одну транзакцию. Это может привести к задержкам, которые, однако, могут быть не видны, если система прочна для чтения.

  • Если система тяжелая для записи, вам может потребоваться добавить работников, которые помогут удалить запрос из очереди [3]

Ответ 4

Может быть хорошей идеей отделить ссылки от ресурса.

Вы можете построить concurrency поверх версии S3 версии. Или пусть каждый референт /node создает и удаляет свой собственный ресурс блокировки на S3. Или используйте службу реляционных баз данных Amazon (RDS).

Ответ 5

Вы можете реализовать свой собственный механизм блокировки как службу на вашем ec2 и использовать ее для синхронизации доступа к S3. В этом случае вы можете хранить подсчеты мониторов в S3 (отдельно или нет)