web-dev-qa-db-fra.com

Ecrire du parquet de AWS Kinesis firehose vers AWS S3

Je voudrais ingérer des données dans s3 à partir d'un tuyau d'incendie kinesis formaté en parquet. Jusqu'à présent, je viens de trouver une solution qui implique la création d'un DME, mais je recherche quelque chose de moins cher et plus rapide comme stocker le json reçu en tant que parquet directement à partir de firehose ou utiliser une fonction Lambda.

Merci beaucoup, Javi.

23
bracana

Bonne nouvelle, cette fonctionnalité est sortie aujourd'hui!

Amazon Kinesis Data Firehose peut convertir le format de vos données d'entrée de JSON en Apache Parquet ou Apache ORC avant de stocker les données dans Amazon S3. Parquet et ORC sont des formats de données en colonnes qui économisent de l'espace et permettent des requêtes plus rapides

Pour l'activer, accédez à votre flux Firehose et cliquez sur Edit. Vous devriez voir la section Conversion de format d'enregistrement comme sur la capture d'écran ci-dessous:

enter image description here

Voir la documentation pour plus de détails: https://docs.aws.Amazon.com/firehose/latest/dev/record-format-conversion.html

15
Vlad Holubiev

Après avoir traité du service de support AWS et d'une centaine d'implémentations différentes, je voudrais expliquer ce que j'ai accompli.

Enfin, j'ai créé une fonction Lambda qui traite chaque fichier généré par Kinesis Firehose, classe mes événements en fonction de la charge utile et stocke le résultat dans des fichiers Parquet en S3.

Ce n'est pas très facile:

  1. Tout d'abord, vous devez créer un environnement virtuel Python, y compris toutes les bibliothèques requises (dans mon cas Pandas, NumPy, Fastparquet, etc.). En tant que fichier résultant (qui inclut toutes les bibliothèques et mon La fonction Lambda est lourde, il est nécessaire de lancer une instance EC2, j'ai utilisé celle incluse dans le niveau gratuit. Pour créer l'environnement virtuel, procédez comme suit:

    • Connectez-vous dans EC2
    • Créez un dossier appelé lambda (ou tout autre nom)
    • Mise à jour Sudo yum -y
    • Sudo yum -y upgrade
    • Sudo yum -y groupinstall "Outils de développement"
    • Sudo yum -y install blas
    • Sudo yum -y install lapack
    • Sudo yum -y install atlas-sse3-devel
    • Sudo yum install python27-devel python27-pip gcc
    • Virtualenv env
    • source env/bin/activate
    • pip installer boto3
    • pip installer fastparquet
    • pip installer des pandas
    • pip installer thriftpy
    • installer pip s3fs
    • installation de pip (toute autre bibliothèque requise)
    • trouver ~/lambda/env/lib */python2.7/site-packages/-name "* .so" | bande de xargs
    • pushd env/lib/python2.7/site-packages /
    • Zip -r -9 -q ~/lambda.Zip *
    • Popd
    • pushd env/lib64/python2.7/site-packages /
    • Zip -r -9 -q ~/lambda.Zip *
    • Popd
  2. Créez correctement la fonction lambda_function:

    import json
    import boto3
    import datetime as dt
    import urllib
    import zlib
    import s3fs
    from fastparquet import write
    import pandas as pd
    import numpy as np
    import time
    
    def _send_to_s3_parquet(df):
        s3_fs = s3fs.S3FileSystem()
        s3_fs_open = s3_fs.open
        # FIXME add something else to the key or it will overwrite the file 
        key = 'mybeautifullfile.parquet.gzip'
        # Include partitions! key1 and key2
        write( 'ExampleS3Bucket'+ '/key1=value/key2=othervalue/' + key, df,
                compression='GZIP',open_with=s3_fs_open)            
    
    def lambda_handler(event, context):
        # Get the object from the event and show its content type
        bucket = event['Records'][0]['s3']['bucket']['name']
        key = urllib.unquote_plus(event['Records'][0]['s3']['object']['key'])
        try:
            s3 = boto3.client('s3')
            response = s3.get_object(Bucket=bucket, Key=key)
            data = response['Body'].read()
            decoded = data.decode('utf-8')
            lines = decoded.split('\n')
            # Do anything you like with the dataframe (Here what I do is to classify them 
            # and write to different folders in S3 according to the values of
            # the columns that I want
            df = pd.DataFrame(lines)
            _send_to_s3_parquet(df)
        except Exception as e:
            print('Error getting object {} from bucket {}.'.format(key, bucket))
            raise e
    
  3. Copiez la fonction lambda dans lambda.Zip et déployez la fonction lambda_function:

    • Revenez à votre instance EC2 et ajoutez la fonction lambda souhaitée au Zip: Zip -9 lambda.Zip lambda_function.py (lambda_function.py est le fichier généré à l'étape 2)
    • Copiez le fichier Zip généré sur S3, car il est très lourd à déployer sans le faire via S3. aws s3 cp lambda.Zip s3: // support-bucket/lambda_packages /
    • Déployez la fonction lambda: aws lambda update-function-code --function-name --s3-bucket support-bucket --s3-key lambda_packages/lambda.Zip
  4. Déclenchez l'exécution à votre guise, par exemple, à chaque fois qu'un nouveau fichier est créé dans S3, ou même vous pouvez associer la fonction lambda à Firehose. (Je n'ai pas choisi cette option car les limites 'lambda' sont inférieures aux limites Firehose, vous pouvez configurer Firehose pour écrire un fichier chaque 128 Mo ou 15 minutes, mais si vous associez cette fonction lambda à Firehose, la fonction lambda sera exécutée toutes les 3 minutes ou 5 Mo, dans mon cas, j'ai eu le problème de générer beaucoup de petits fichiers parquet, car à chaque fois que la fonction lambda est lancée je génère au moins 10 fichiers).

20
bracana

Amazon Kinesis Firehose reçoit des enregistrements en streaming et peut les stocker dans Amazon S3 (ou Amazon Redshift ou Amazon Elasticsearch Service).

Chaque enregistrement peut atteindre 1 000 Ko.

Kinesis flow

Cependant, les enregistrements sont ajoutés ensemble dans un fichier texte, avec un traitement basé sur le temps ou la taille. Traditionnellement, les enregistrements sont au format JSON.

Vous serez impossible d'envoyer un fichier parquet car il ne sera pas conforme à ce format de fichier.

Il est possible de déclencher une fonction de transformation de données Lambda, mais cela ne sera pas non plus capable de sortir un fichier parquet.

En fait, étant donné la nature des fichiers de parquet, il est peu probable que vous puissiez les créer un enregistrement à la fois . Étant un format de stockage en colonnes, je soupçonne qu'ils doivent vraiment être créés dans un lot plutôt que d'avoir des données ajoutées par enregistrement.

Conclusion: Non.

9
John Rotenstein