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.
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:
Voir la documentation pour plus de détails: https://docs.aws.Amazon.com/firehose/latest/dev/record-format-conversion.html
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:
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:
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
Copiez la fonction lambda dans lambda.Zip et déployez la fonction lambda_function:
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).
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.
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.