O blog da AWS

Gerenciando objetos duplicados no Amazon S3

Esta postagem foi escrita por Tamelly Lim. Adaptada para o português por Rogerio Xavier, Arquiteto de Soluções Sênior para Parceiros AWS.

Ao gerenciar um grande volume de dados em um sistema de armazenamento, é comum que ocorra duplicação de dados. A duplicação de dados no gerenciamento de dados se refere à presença de várias cópias dos mesmos dados em seu sistema, gerando uso adicional de armazenamento e sobrecarga adicional ao lidar com várias cópias do mesmo arquivo. Para melhorar o gerenciamento de dados e a eficiência de custos, a deduplicação de dados é a prática de identificar e remover dados duplicados por meio de vários métodos, como mesclagem e eliminação, ao mesmo tempo em que garante que a integridade dos dados não seja comprometida.

No Amazon Simple Storage Service (Amazon S3), objetos duplicados podem existir dentro do mesmo bucket, seja devido à duplicação acidental de arquivos, processos de sincronização de dados ou operações de backup. Para dados menos críticos, como arquivos de log temporários, os usuários podem preferir reter apenas uma cópia se um processo gerar vários arquivos com exatamente o mesmo conteúdo para otimizar seus custos de armazenamento.

Neste post, mostraremos como você pode iniciar seu próprio processo de deduplicação de dados para objetos armazenados em um bucket do S3. Identificamos os objetos duplicados em seu bucket usando o Amazon Athena, validamos que as duplicatas podem ser removidas e os excluímos usando o AWS Lambda e o S3 Batch Operations. Isso ajudará você a reduzir os custos de armazenamento de objetos com conteúdo duplicado sem precisar selecionar manualmente os objetos a serem excluídos.

Identificação de objetos duplicados

Organizamos uma lista de objetos duplicados usando a entity tag (ETag) dos objetos. A ETag é um hash do objeto, refletindo as alterações somente no conteúdo de um objeto, não em seus metadados. Para objetos criptografados por SSE-S3 ou texto simples e não carregados Multipart Upload or Part Copy operation, a ETag é um resumo MD5 dos dados do objeto. MD5 é um algoritmo de hash criptográfico usado para produzir um valor de hash consistente de 128 bits a partir de uma string de entrada. Ao comparar o resumo MD5 desses objetos, podemos identificar objetos duplicados em um único bucket, mesmo que eles tenham chaves diferentes ou estejam localizados em prefixos separados.

Essa solução usa o Amazon S3 Inventory para fornecer uma lista de todos os objetos e seus metadados em seu bucket S3 de destino. Em seguida, ele usa o Amazon Athena para consultar a lista e identificar os objetos duplicados. Depois de analisar os resultados do Athena e garantir que os objetos listados sejam considerados seguros para exclusão, você usa o S3 Batch Operations para invocar uma função do AWS Lambda que executa a exclusão em massa em grande escala dos objetos. Essa solução se concentra em bucket que não têm controle de versão ativado, mas também pode funcionar para buckets com controle de versão ativado com alguns ajustes que serão mencionados posteriormente.

Observe que essa solução só se aplica a objetos criptografados com SSE-S3 ou texto sem formatação, que são criados pela operação PUT Object, POST Object ou Copy. Desde janeiro de 2023, todos os novos uploads de objetos para o Amazon S3 são criptografados automaticamente com um mínimo de SSE-S3, e essa solução é aplicável a esses objetos. Como a ETag não é necessariamente a mesma para objetos duplicados criptografados com chaves SSE-KMS ou SSE-C, não podemos usar a ETag para identificar dados duplicados, e esses objetos estão fora do escopo desta postagem. Além disso, objetos que são carregados por meio da operação de carregamento em várias partes ou cópia parcial não têm uma ETag que possa ser usada para deduplicação de dados e, portanto, esses objetos estão fora do escopo desta postagem.

Visão geral da solução

Identificamos objetos duplicados dentro do seu bucket S3 usando Athena para consultar o relatório do S3 Inventory. Em seguida, esses objetos são excluídos usando as S3 Batch Operations por meio de uma função Lambda após você revisar que eles são apropriados para exclusão.

Figura 1: Diagrama de arquitetura da solução que consulta o relatório do S3 Inventory com a Amazon Athena para identificar objetos duplicados a serem excluídos com o S3 Batch Operations invocando uma função Lambda

Pré-requisitos

Os seguintes pré-requisitos são necessários para continuar com este post:

  1. Bucket S3 de destino sem controle de versão habilitado.
  2. Permissões adequadas do AWS Identity and Access Management (IAM) para gerar relatórios do S3 Inventory, criar tabelas e views no Athena, e configurar tarefas do S3 Batch Operations. Esta é uma política de exemplo do IAM que tem as permissões mínimas necessárias, além da política gerenciada da AWSLambda_FullAccess.
{
    "Version": "2012-10-17",
    "Statement": [{
            "Sid": "S3Actions",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:PutObject",
                "s3:PutBucketPolicy",
                "s3:GetBucketPolicy",
                "s3:ListBucket",
                "s3:GetBucketLocation",
                "s3:GetInventoryConfiguration",
                "s3:PutInventoryConfiguration"
            ],
            "Resource": [
                "arn:aws:s3:::",
                "arn:aws:s3:::/*"
            ]
        },
        {
            "Sid": "CreateS3BatchOperationsJob",
            "Effect": "Allow",
            "Action": [
                "s3:CreateJob",
                "s3:ListAllMyBuckets",
                "s3:ListJobs",
                "s3:DescribeJob",
                "s3:UpdateJobStatus"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Lambda",
            "Effect": "Allow",
            "Action": [
                "iam:CreateRole",
                "iam:CreatePolicy",
                "iam:AttachRolePolicy",
                "iam:ListPolicies",
                "iam:CreatePolicyVersion"
            ],
            "Resource": [
                "arn:aws:iam::111122223333:policy/service-role/AWSLambdaBasicExecutionRole*",
                "arn:aws:iam::111122223333:role/service-role/DeleteS3Objects*"
            ]
        },
        {
            "Sid": "S3BatchOperations",
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "arn:aws:iam::111122223333:role/"
        },
        {
            "Sid": "RunAthenaQueries",
            "Effect": "Allow",
            "Action": [
                "athena:GetWorkGroup",
                "athena:StartQueryExecution",
                "athena:StopQueryExecution",
                "athena:GetQueryExecution",
                "athena:GetQueryResults",
                "glue:GetTables",
                "glue:GetTable",
                "glue:CreateTable",
                "glue:GetDatabase",
                "glue:GetDatabases"
            ],
            "Resource": "*"
        }
    ]
}

Passo a passo

Configuramos os recursos necessários nesta arquitetura com as seguintes etapas:

  1. Configurar o relatório do S3 Inventory
  2. Consultar o relatório do S3 Inventory usando o Athena
  3. Criar a função Lambda para excluir um único objeto
  4. Configurar o S3 Batch Operations Job para excluir objetos

Passo 1. Configurar o relatório do S3 Inventory

S3 Inventory permite gerar uma lista de objetos e seus metadados associados para um determinado bucket S3 que você pode usar para consultar e gerenciar seus objetos. Usamos este recurso para gerar uma lista de objetos para que você possa comparar seus valores de ETag.

  1. Selecione o bucket de destino armazenando objetos duplicados no console de gerenciamento da Amazon S3 e navegue até a guia Gerenciamento.
  2. Na seção Configurações de inventário, selecione Criar configuração de inventário.
  3. Defina o nome da configuração e o escopo do inventário, limitando ao nível de prefixo desejado. Deixe como padrão Somente versão atual para versões de objeto. Para o bucket com controle de versão habilitado, você pode selecionar Incluir todas as versões se quiser remover duplicatas em todas as versões de objetos no bucket.
  4. Defina o bucket de destino e aplique a política de exemplo fornecida na política do bucket de destino. Você pode usar um bucket diferente do bucket de destino para facilitar o gerenciamento.
  5. Selecione Frequência, Formato e Habilite o relatório de inventário. Escolha Diário ou Semanal para frequência. Para saída, você pode escolher entre CSV, Apache ORC e Apache Parquet. O uso de formatos em colunas pode resultar em melhor desempenho de consulta, especialmente se seu bucket S3 de destino tiver milhões de objetos. Este post usa o formato Apache ORC como saída.
  6. Dentro do campos metadados adicionais, selecione Tamanho, Última modificação, Criptografia na seção Objeto e ETag na seção Integridade de dados.

    Figura 2: Opções selecionadas no S3 Inventory conforme exemplo descrito acima.

  7. Selecione Criar para concluir a configuração. O primeiro relatório chegará ao seu bucket de destino dentro das próximas 48 horas.

Passo 2. Consultar o relatório de Inventário do S3 usando o Athena

O Athena é um serviço de consulta interativa que facilita a análise de dados no Amazon S3 usando SQL padrão. Ele é serverless, sem infraestrutura para gerenciar, e você só precisa pagar pelas consultas executadas. Você usa isso para consultar o relatório de Inventário do S3 gerado, a fim de identificar arquivos que são duplicados e podem ser excluídos. Por padrão, o Athena não suporta consultar diretamente objetos armazenados nas classes de armazenamento S3 Glacier Flexible Retrieval ou S3 Glacier Deep Archive, então os objetos arquivados são ignorados e não consultados. Para consultar objetos arquivados, você deve restaurá-los primeiro antes de executar consultas nos dados restaurados. Consulte este blog para obter orientação adicional sobre como consultar dados arquivados em seu bucket usando o Amazon Athena.

  1. Abra o Amazon Athena em seu console e selecione as guias do Editor de Consulta na barra lateral esquerda. Certifique-se de estar na mesma Região da AWS que seus buckets S3.
  2. Execute a primeira consulta na guia Editor da seguinte forma. Isso cria o schema de tabela do relatório do S3 Inventory no Athena em um catálogo de dados e o usa quando você executa consultas. Se seu relatório estiver no formato Parquet ou CSV, consulte a documentação da AWS sobre como criar o schema de tabela adequadamente. Para buckets com controle de versão habilitado, inclua uma coluna extra para ID da Versão.
  3. Substitua <S3 Inventory Location> pelo local do Inventário S3 configurado no Passo 1. Por exemplo, se o nome do meu bucket for “s3-duplicatebucket” com o nome da configuração de inventário como “inventorycheck”, para usar o relatório gerado em 12 de dezembro de 2023, o local será “s3://s3-duplicatebucket/inventorycheck/hive/dt=2023-12-13-01-00/”.

    Se houver objetos no bucket criptografados com SSE-KMS ou SSE-C, filtre esses objetos criando outra view e selecionando apenas os objetos com SSE-S3 ou NOT-SSE como seu status de criptografia. Consulte a partir da view criada em vez da tabela nas etapas seguintes.

    CREATE EXTERNAL TABLE s3inventory(
             bucket string,
             key string,
             size bigint,
             last_modified_date timestamp,
             etag string,
             encryption_status string
    ) 
    ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.orc.OrcSerde'
      STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.SymlinkTextInputFormat'
      OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat'
      LOCATION '<S3 Inventory Location>'
    
    

3. Após a criação do schema de tabela, a próxima consulta ajuda a criar uma view que lista todos os ETags que se repetem mais de uma vez no relatório do S3 Inventory. Execute esta consulta.

CREATE VIEW duplicate_etag AS
SELECT DISTINCT etag FROM "default"."s3inventory"
GROUP BY etag
HAVING COUNT(key) > 1 

4. Para identificar qual objeto duplicado manter, mantemos o objeto com os metadados de data da última modificação mais recente em relação a outros objetos que têm o mesmo ETag e tamanho de objeto. Com isso, estamos comparando cada objeto contra seu ETag e tamanho de objeto antes de determinar que são duplicados. Esta consulta identifica os metadados de data da última modificação mais recente para cada ETag distinto.

CREATE VIEW etag_max_date as
SELECT etag, size, MAX(last_modified_date) as max_date from "default"."s3inventory"
GROUP BY etag, size 

5. Esta última consulta gera uma lista de objetos que são duplicados, deixando de fora aqueles que estão em etag_max_date, que são os objetos a serem mantidos no bucket. Para buckets com controle de versão habilitado, inclua a ID da versão na consulta de seleção.

SELECT s3inventory.bucket, s3inventory.key
FROM (s3inventory
LEFT JOIN etag_max_date
ON ((s3inventory.etag = etag_max_date.etag) AND (s3inventory.last_modified_date = etag_max_date.max_date) AND (s3inventory.size = etag_max_date.size)))
WHERE (etag_max_date.max_date IS NULL)

6. Faça o download dos resultados, revise os objetos retornados e certifique-se de que é seguro excluí-los. Revisar os objetos listados é importante para garantir que eles sejam apropriados para exclusão, pois não é possível recuperar os arquivos depois que forem permanentemente excluídos nas etapas posteriores. Remova a linha de cabeçalho e salve como um CSV em seu bucket S3 preferido para ser usado posteriormente pelo S3 Batch Operations.

Passo 3. Criar a função Lambda para excluir um único objeto

O Lambda é um serviço de computação sem servidor e orientado a eventos que permite executar código sem provisionar ou gerenciar servidores. Para excluir cada objeto, configuramos um código Lambda que passa uma API de exclusão para o objeto especificado.

    1. Acesse a página do console do Lambda na mesma Região da AWS.
    2. Após selecionar Painel na barra de navegação lateral, selecione Criar função.
    3. Deixe o modo como Autor do zero e insira o nome da função como DeleteS3Objects. Escolha a última versão do Python como Runtime e deixe tudo mais como padrão. Selecione Criar função.
    4. Na página da função, insira o seguinte código na fonte de código. Este código exclui qualquer chave que for passada pela função. Para buckets com controle de versão habilitado, você deve passar a ID da versão do objeto através da chamada da API DeleteObject para remover permanentemente a versão do objeto.
import logging
from urllib import parse
import boto3
from botocore.exceptions import ClientError

logger = logging.getLogger(__name__)
logger.setLevel("INFO")

s3 = boto3.client("s3")

def lambda_handler(event, context):
    """
    Permanently deletes the object.
    SPECIFIED OBJECT VERSION WILL BE PERMANENTLY REMOVED

    :param event: The S3 batch event that contains the key of the object
                  to remove.
    :param context: Context about the event.
    :return: A result structure that Amazon S3 uses to interpret the result of the
             operation. When the result code is TemporaryFailure, S3 retries the
             operation.
    """
    # Parse job parameters from Amazon S3 batch operations
    logger.info(event)

    invocation_id = event["invocationId"]
    invocation_schema_version = event["invocationSchemaVersion"]

    results = []
    result_code = None
    result_string = None

    task = event["tasks"][0]
    task_id = task["taskId"]

    try:
        obj_key = parse.unquote_plus(task["s3Key"], encoding="utf-8")
        bucket_name = task["s3BucketArn"].split(":")[-1]

        logger.info("Got task: remove object %s.", obj_key)

        try:
            s3.delete_object(
                Bucket=bucket_name, Key=obj_key
            )
            result_code = "Succeeded"
            result_string = (
                f"Successfully removed object {obj_key}"
            )
            logger.info(result_string)            
            logger.warning(result_string)
        except ClientError as error:
            # Mark request timeout as a temporary failure so it will be retried.
            if error.response["Error"]["Code"] == "RequestTimeout":
                result_code = "TemporaryFailure"
                result_string = (
                    f"Attempt to delete {obj_key} timed out."
                )
                logger.info(result_string)
            else:
                raise
            
    except Exception as error:
        # Mark all other exceptions as permanent failures.
        result_code = "PermanentFailure"
        result_string = str(error)
        logger.exception(error)
    finally:
        results.append(
            {
                "taskId": task_id,
                "resultCode": result_code,
                "resultString": result_string,
            }
        )
    return {
        "invocationSchemaVersion": invocation_schema_version,
        "treatMissingKeysAs": "PermanentFailure",
        "invocationId": invocation_id,
        "results": results,
    }

5. Selecione Deploy para salvar as alterações na função.

6. Aplique as permissões apropriadas para que a função Lambda execute a operação de exclusão. Navegue até Configuração, depois Permissões. Selecione o nome da função de serviço do Lambda para abrir uma guia no console do IAM. Adicione uma política adicional que permita que a função Lambda execute a operação de exclusão no bucket de destino. Substitua <target-bucket> pelo nome do seu bucket.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ObjectActions",
            "Effect": "Allow",
            "Action": [
                "s3:DeleteObject"
            ],
            "Resource:": "arn:aws:s3:::<target-bucket>/*"
        }
    ]
}

7. Sua função Lambda está pronta para uso.

Passo 4. Configurar S3 Batch Operations para excluir objetos

S3 Batch Operations é um recurso de gerenciamento de dados que permite gerenciar bilhões de objetos em escala, criando um trabalho com uma lista de objetos e a ação a ser executada. Ações comuns seriam copiar objetos entre buckets ou restaurar objetos arquivados das classes de armazenamento S3 Glacier. Neste caso, usamos as S3 Batch Operations para invocar a função Lambda que você acabou de criar em cada objeto especificado nos resultados CSV baixados do Athena no Passo 2.

    1. Acesse o console de gerenciamento da Amazon S3 e selecione Batch Operations na barra lateral. Selecione Criar Trabalho.
    2. Certifique-se de estar na Região AWS correta. Selecione CSV para o formato do Manifesto e inclua o caminho para o arquivo criado anteriormente a partir dos resultados do Athena.
    3. Para buckets com controle de versão habilitado, selecione a caixa para Manifesto inclui IDs de versão. Caso contrário, deixe-a desmarcada. Escolha Próximo.
    4. Escolha Invocar função AWS Lambda e selecione a função Lambda DeleteS3Objects da mesma Região AWS que você implantou no Passo 3. Escolha Próximo.
    5. Dê uma descrição para seu trabalho, defina seu nível de prioridade e escolha um tipo de relatório e seu local.
    6. Especifique a S3 Batch Operations IAM role. Você pode usar o modelo de política de role do IAM fornecido e a política de confiança do IAM e atribuir a uma nova função do IAM especificamente para que o S3 Batch Operations tenham permissões apropriadas para excluir os objetos da lista. Selecione Próximo.
    7. Revise os detalhes do trabalho e selecione Create job.

O trabalho agora passa para o estado Preparando para ler o manifesto do trabalho, verificar erros e calcular o número de objetos. Dependendo do tamanho do manifesto, a leitura pode levar minutos ou horas. Assim que estiver pronto, o trabalho passa para o estado Aguardando sua confirmação para executar.

8. Quando o trabalho estiver nesse estado, selecione o trabalho, verifique os detalhes e selecione Executar trabalho quando estiver pronto.

Após a conclusão, um relatório de conclusão é gerado no local que você especificou durante a criação do trabalho. Seus objetos duplicados agora foram excluídos.

Se você experimentar falhas, poderá investigar verificando o relatório de conclusão ou os logs do Amazon CloudWatch através da função Lambda para identificar quais arquivos falharam na transferência. Usando o log de erros, você pode filtrar os objetos que falharam em um arquivo csv e executar um novo S3 Batch Operations para tentar novamente.

Pontos de atenção

Embora excluir objetos possa ajudar a economizar custos de armazenamento, é importante revisar a lista de objetos e garantir que eles possam ser excluídos, já que não é possível recuperar os objetos depois que forem excluídos. Como essa abordagem depende do uso do hash MD5, pode haver objetos que são diferentes em conteúdo com uma baixa possibilidade de ter o mesmo hash MD5. Para diminuir a probabilidade disso, as consultas Athena que revisamos fazem uma correspondência em ambos o ETag e o tamanho dos objetos antes de determinar que são objetos duplicados. No entanto, ainda é crucial revisar as chaves de objeto antes de executar o S3 Batch Operations nos resultados.

Embora essa solução se concentre em buckets sem controle de versão, com alguns ajustes mencionados no post, também pode funcionar para buckets com controle de versão habilitado. Você deve incluir a ID da versão na geração de relatórios do S3 Inventory, editar a consulta Athena para refletir a ID da versão nos resultados e passar a ID da versão através da API Delete na função Lambda.

Se você tiver objetos no bucket criptografados com SSE-KMS ou SSE-C, poderá filtrar esses objetos na consulta Athena selecionando apenas objetos que tenham SSE-S3 ou NOT-SSE como seu status de criptografia.

Há custos associados a esta solução com os recursos usados. O Athena é precificado em US$ 5 por TB de dados examinados, o Lambda é precificado de acordo com as cobranças de solicitação e computação, enquanto a geração de S3 Inventory e S3 Batch Operations são cobradas com base no número de objetos e trabalhos executados. Você deve estimar os encargos para ver se sua economia de custos em comparação com os custos de armazenamento é substancial o suficiente para testar esta solução em seu bucket.

Limpeza dos recursos

Limpe o bucket S3 contendo o relatório do S3 Inventory e o relatório de conclusão do S3 Batch Operations criados durante as etapas anteriores para evitar incorrer em custos adicionais de armazenamento. Você também deve excluir a configuração do S3 Inventory configurada para parar de gerar relatórios em seu bucket S3 de destino. Para evitar invocar acidentalmente a função Lambda que foi configurada, você deve excluir a função. Por último, descarte o banco de dados Amazon Athena para concluir a limpeza dos recursos criados.

Conclusão

Neste post, foi abordado como você pode excluir objetos duplicados no Amazon S3 usando o Amazon Athena para identificá-los e S3 Batch Operations para invocar uma função AWS Lambda para excluí-los. Isso permite reduzir a duplicação de objetos no nível do bucket para otimizar os custos de armazenamento e limpar vários objetos idênticos para melhorar o desempenho de consulta.

Este blog foi traduzido para o Português, e o conteúdo original pode ser acessado aqui.

Autora

Tamelly Lim Tamelly Lim é uma Arquiteta de Soluções Associate com base em Cingapura e ela trabalha em estreita colaboração com clientes em soluções da AWS. Ela começou sua jornada na nuvem em 2022, logo após sair da universidade, e gosta de ajudar os usuários enquanto aprende e constrói na nuvem. No seu tempo livre, ela adora praticar esportes e viajar para experimentar novas culturas.
Tradutor

Rogerio Xavier Rogerio Xavier é Arquiteto de Soluções Sênior para parceiros da AWS, atua ajudando parceiros na jornada de parceria com a AWS e a entregar a melhor solução aos clientes. Com mais de 15 anos de experiência em infraestrutura de TI, arquitetura e administração de sistemas. Nos ultimos 7 anos ele se dedicou em Redes, Storage (Block e Object), Sistemas Operacionais, Messaging, Migração de dados, Serverless, além de modernização de aplicações. Ele adora passar o tempo livre com a família e jogar video-game.
Revisora

Jhennyfer Oliveira Jhennyfer Oliveira é Arquiteta de Soluções baseada em São Paulo que apoia clientes de diferentes segmentos. Após experiência com gestão de projetos, qualidade de software, analise e desenvolvimento de aplicações, decidiu se especializar na arquitetura de soluções ao ingressar na AWS em 2020.