Tratando inconsistências em requisições PUT do S3 na Transloadit
O Amazon S3 é ótimo. Exceto quando não é. Quando você o usa bastante (até agora armazenamos cerca de um milhão de objetos de clientes), começa a notar algumas coisas estranhas que parecem mais uma “loucura eventual” do que uma “consistência eventual”.
Uma das coisas que aprendemos logo de cara é que não dá para confiar nos códigos de erro do S3. Às
vezes você recebe um 403 Permission Denied, mas, quando executa exatamente a mesma requisição
de novo, ela milagrosamente funciona de repente. Por isso, em geral é preciso tentar novamente
sempre que você recebe uma mensagem de erro. Só vale a pena dar atenção a um erro específico quando
ele ocorre várias vezes. Atualmente, fazemos até 6 novas tentativas, com tempos de espera
crescentes.
A novidade mais recente que encontramos é que as confirmações do S3 para requisições PUT também não são confiáveis. O sintoma que vimos foi que algumas das URLs do S3 que devolvíamos aos nossos clientes simplesmente não funcionavam. Reproduzir isso foi um enorme desafio. Em um momento, conseguimos ver o problema depois de ~25 PUTs; em outro, nada aconteceu depois de 2500 PUTs (10 GB no total). Então ainda existe uma pequena chance de haver um bug em algum lugar do nosso sistema, mas, a esta altura, estamos bastante convencidos de que se trata de um problema da Amazon que ocorre com pouca frequência.
Bem-vindo à terra da loucura. Ao lidar com um sistema eventualmente consistente, em que “eventualmente” às vezes pode significar “nunca”, como você verifica o sucesso de uma operação de escrita? É claro que você pode checar o bucket para ver se o objeto existe após cada escrita, mas e se ele não existir? Quando isso passa a ser uma condição de erro? Além disso, quando o objeto existe, o que isso significa? É seguro supor que pelo menos um cliente consegue ver o objeto, mas não que a replicação dele terminou e que, portanto, ele está disponível para todos os clientes.
Embora não exista uma resposta perfeita, decidimos verificar a presença de um arquivo armazenado com até onze checagens ao longo de dois minutos. Se o arquivo não existir até lá, tentaremos executar o Job novamente até seis vezes. Embora isso esteja longe do ideal, provavelmente vai reduzir a chance de entregarmos URLs inválidas do S3 a um nível parecido com a de ganhar um bom prêmio na loteria.
Outra coisa que nos chamou a atenção é que o modelo de consistência do S3 não é o mesmo em todas as regiões. Enquanto a “US Default” adota o modelo tradicional de “consistência eventual”, todas as outras regiões oferecem consistência “read-after-write” (leitura após escrita). Embora isso seja extremamente confuso do ponto de vista do cliente, o motivo parece ser que a “US Default” se estende da costa leste à costa oeste, então a velocidade da luz atrapalha o fornecimento das mesmas garantias.
Estamos coletando dados melhores sobre a nossa experiência com o S3 e vamos compartilhá-los no futuro. Na maior parte do tempo, o S3 definitivamente funciona muito bem para nós e, se ficar claro que o estávamos usando da forma errada, também vamos publicar uma atualização sobre isso.
