Logo DynamoDB

Amazon DynamoDB

La base de données NoSQL d'Amazon Web Services qui offre des performances fiables à n'importe quelle échelle, avec une haute disponibilité et une sécurité intégrée.

Pour les non-initiés

Qu'est-ce que DynamoDB ?

Imaginez une immense bibliothèque capable de stocker des milliards de livres, où vous pourriez instantanément retrouver n'importe quel livre, même si des millions de personnes font la même recherche en même temps. Cette bibliothèque fonctionnerait 24h/24, 7j/7, sans jamais tomber en panne ni ralentir, et s'agrandirait automatiquement lorsque de nouveaux livres arrivent.

DynamoDB est l'équivalent numérique de cette bibliothèque pour les données. C'est un service de base de données proposé par Amazon Web Services (AWS) qui permet de stocker et d'accéder à d'énormes quantités d'informations de manière fiable, rapide et économique.

Pourquoi est-ce important ?

Performances garanties

DynamoDB assure des temps de réponse rapides et constants, même pendant les pics d'activité intenses, comme un Black Friday pour les sites d'e-commerce.

Scalabilité automatique

Contrairement aux bases de données traditionnelles qui nécessitent une planification complexe pour gérer la croissance, DynamoDB s'adapte automatiquement aux besoins de votre application.

En résumé, DynamoDB est la solution idéale pour les entreprises qui ont besoin de stocker et d'accéder à de grandes quantités de données rapidement et de manière fiable, sans se soucier de la maintenance ou de la mise à l'échelle de l'infrastructure sous-jacente.

Pour les développeurs

Fonctionnement technique

DynamoDB est une base de données NoSQL totalement gérée qui prend en charge à la fois les modèles de données clé-valeur et document. Elle offre une latence constante en millisecondes, quelle que soit la taille de la base de données, et intègre des fonctionnalités avancées comme la réplication multi-région, le chiffrement au repos et la gestion des flux de données en temps réel.

Concepts fondamentaux

Structure des tables et clés

DynamoDB organise les données en tables, qui sont des collections d'items (similaires aux rangées). Chaque item a une clé primaire obligatoire qui peut être simple (partition key) ou composite (partition key + sort key). Cette conception est essentielle pour des performances optimales.

  • Clé de partition (Partition Key) : Détermine où les données sont stockées physiquement
  • Clé de tri (Sort Key) : Permet de trier les données partageant la même clé de partition
  • Attributs : Valeurs associées à chaque item, sans schéma rigide (flexibilité NoSQL)

Création de table

Voici comment créer une table DynamoDB avec l'AWS SDK pour JavaScript :

Création d'une table DynamoDB
// Création d'une table DynamoDB avec AWS SDK pour JavaScript const AWS = require('aws-sdk'); AWS.config.update({ region: 'eu-west-3' }); const dynamoDB = new AWS.DynamoDB(); const params = { TableName: 'Users', KeySchema: [ { AttributeName: 'userId', KeyType: 'HASH' }, // Partition key { AttributeName: 'email', KeyType: 'RANGE' } // Sort key ], AttributeDefinitions: [ { AttributeName: 'userId', AttributeType: 'S' }, { AttributeName: 'email', AttributeType: 'S' }, { AttributeName: 'userStatus', AttributeType: 'S' } ], GlobalSecondaryIndexes: [ { IndexName: 'UserStatusIndex', KeySchema: [ { AttributeName: 'userStatus', KeyType: 'HASH' }, { AttributeName: 'email', KeyType: 'RANGE' } ], Projection: { ProjectionType: 'ALL' }, ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 } } ], BillingMode: 'PROVISIONED', ProvisionedThroughput: { ReadCapacityUnits: 10, WriteCapacityUnits: 10 }, StreamSpecification: { StreamEnabled: true, StreamViewType: 'NEW_AND_OLD_IMAGES' }, Tags: [ { Key: 'Environment', Value: 'Production' }, { Key: 'Team', Value: 'UserManagement' } ] }; dynamoDB.createTable(params, (err, data) => { if (err) { console.error('Erreur lors de la création de la table', err); } else { console.log('Table créée avec succès', data); } });

Opérations CRUD

Le DocumentClient est une abstraction de plus haut niveau qui simplifie l'interaction avec DynamoDB :

Opérations CRUD avec DocumentClient
// Opérations CRUD avec le DocumentClient const AWS = require('aws-sdk'); AWS.config.update({ region: 'eu-west-3' }); // Création d'une instance DocumentClient const docClient = new AWS.DynamoDB.DocumentClient(); // 1. Création d'un élément async function createUser(user) { const params = { TableName: 'Users', Item: { userId: user.id, email: user.email, firstName: user.firstName, lastName: user.lastName, userStatus: 'ACTIVE', createdAt: new Date().toISOString(), preferences: { theme: 'dark', notifications: ['email', 'push'] }, permissions: ['read', 'write'] }, // Vérification de non-existence d'un utilisateur avec cette clé ConditionExpression: 'attribute_not_exists(userId)' }; try { await docClient.put(params).promise(); console.log('Utilisateur créé avec succès'); return true; } catch (error) { console.error('Erreur lors de la création :', error); return false; } } // 2. Lecture d'un élément async function getUser(userId, email) { const params = { TableName: 'Users', Key: { userId: userId, email: email } }; try { const data = await docClient.get(params).promise(); return data.Item; // Renvoie l'utilisateur ou undefined s'il n'existe pas } catch (error) { console.error('Erreur lors de la lecture :', error); return null; } } // 3. Mise à jour d'un élément async function updateUserStatus(userId, email, newStatus) { const params = { TableName: 'Users', Key: { userId: userId, email: email }, UpdateExpression: 'set userStatus = :status, updatedAt = :time', ExpressionAttributeValues: { ':status': newStatus, ':time': new Date().toISOString(), ':expectedStatus': 'ACTIVE' }, ConditionExpression: 'userStatus = :expectedStatus', ReturnValues: 'UPDATED_NEW' }; try { const data = await docClient.update(params).promise(); console.log('Utilisateur mis à jour avec succès', data); return data.Attributes; } catch (error) { console.error('Erreur lors de la mise à jour :', error); return null; } } // 4. Suppression d'un élément async function deleteUser(userId, email) { const params = { TableName: 'Users', Key: { userId: userId, email: email }, ReturnValues: 'ALL_OLD' }; try { const data = await docClient.delete(params).promise(); console.log('Utilisateur supprimé avec succès'); return data.Attributes; // Renvoie l'utilisateur supprimé } catch (error) { console.error('Erreur lors de la suppression :', error); return null; } }

Requêtes et filtres

Exemples de requêtes avancées dans DynamoDB :

Requêtes avancées avec DynamoDB
// Exemples de requêtes avancées avec DynamoDB const AWS = require('aws-sdk'); AWS.config.update({ region: 'eu-west-3' }); const docClient = new AWS.DynamoDB.DocumentClient(); // 1. Requête de base sur la clé de partition async function getUsersByStatus(status) { const params = { TableName: 'Users', IndexName: 'UserStatusIndex', KeyConditionExpression: 'userStatus = :status', ExpressionAttributeValues: { ':status': status } }; try { const data = await docClient.query(params).promise(); return data.Items; } catch (error) { console.error('Erreur lors de la requête :', error); return []; } } // 2. Requête avec filtre async function getActiveUsersByDomain(status, emailDomain) { const params = { TableName: 'Users', IndexName: 'UserStatusIndex', KeyConditionExpression: 'userStatus = :status', FilterExpression: 'contains(email, :domain)', ExpressionAttributeValues: { ':status': status, ':domain': emailDomain } }; try { const data = await docClient.query(params).promise(); return data.Items; } catch (error) { console.error('Erreur lors de la requête filtrée :', error); return []; } } // 3. Scan avec filtre (attention aux performances sur les grandes tables) async function searchUsersByName(nameFragment) { const params = { TableName: 'Users', FilterExpression: 'contains(firstName, :name) OR contains(lastName, :name)', ExpressionAttributeValues: { ':name': nameFragment } }; try { const data = await docClient.scan(params).promise(); return data.Items; } catch (error) { console.error('Erreur lors du scan :', error); return []; } } // 4. Batch Get - Récupération de plusieurs éléments à la fois async function getUsersInBatch(userKeys) { const params = { RequestItems: { 'Users': { Keys: userKeys // tableau de clés [{userId: 'id1', email: 'email1'}, ...] } } }; try { const data = await docClient.batchGet(params).promise(); return data.Responses.Users; } catch (error) { console.error('Erreur lors du batch get :', error); return []; } }

Single-Table Design

Une approche avancée pour organiser différents types d'entités dans une seule table DynamoDB :

Single-Table Design dans DynamoDB
// Exemple de Single-Table Design dans DynamoDB // 1. Structure des clés pour différents types d'entités dans une même table const exampleItems = [ // Utilisateur { PK: 'USER#123', SK: 'PROFILE#123', Type: 'USER', Email: 'user@example.com', Name: 'John Doe', CreatedAt: '2023-01-15T12:00:00Z' }, // Adresse de l'utilisateur { PK: 'USER#123', SK: 'ADDRESS#HOME', Type: 'ADDRESS', Street: '123 Main St', City: 'Paris', Country: 'France', IsDefault: true }, // Commande de l'utilisateur { PK: 'USER#123', SK: 'ORDER#456', Type: 'ORDER', OrderDate: '2023-02-20T14:30:00Z', Status: 'DELIVERED', Total: 129.99, GSI1PK: 'ORDER#456', // Pour accès direct à la commande GSI1SK: '2023-02-20' // Pour filtrer par date }, // Produit de la commande { PK: 'ORDER#456', SK: 'PRODUCT#789', Type: 'ORDER_ITEM', ProductName: 'Smartphone XYZ', Quantity: 1, Price: 129.99 }, // Information du produit { PK: 'PRODUCT#789', SK: 'METADATA', Type: 'PRODUCT', Name: 'Smartphone XYZ', Category: 'Electronics', GSI1PK: 'CATEGORY#Electronics', // Pour requêtes par catégorie GSI1SK: 'PRODUCT#789' } ]; // 2. Exemples de requêtes efficaces dans ce modèle // Récupérer toutes les informations d'un utilisateur (profil, adresses, commandes) const userParams = { TableName: 'AppData', KeyConditionExpression: 'PK = :pk', ExpressionAttributeValues: { ':pk': 'USER#123' } }; // Récupérer une commande spécifique avec tous ses produits const orderParams = { TableName: 'AppData', KeyConditionExpression: 'PK = :pk', ExpressionAttributeValues: { ':pk': 'ORDER#456' } }; // Récupérer tous les produits d'une catégorie (utilisant GSI) const categoryParams = { TableName: 'AppData', IndexName: 'GSI1', KeyConditionExpression: 'GSI1PK = :category', ExpressionAttributeValues: { ':category': 'CATEGORY#Electronics' } };

Fonctionnalités avancées

  • Indexes secondaires : Index secondaires globaux (GSI) et locaux (LSI) pour des accès efficaces via des attributs non-clés
  • Auto-scaling : Ajustement automatique de la capacité de lecture/écriture en fonction de la charge
  • Transactions : Opérations ACID pour garantir l'intégrité des données à travers plusieurs tables
  • Time To Live (TTL) : Suppression automatique des items après une date d'expiration
  • DynamoDB Streams : Capture des modifications pour le traitement en temps réel avec Icône LambdaLambda
  • DynamoDB Accelerator (DAX) : Cache en mémoire pour réduire la latence à la microseconde
  • Tables globales : Réplication multi-régions pour la haute disponibilité et la résilience
  • Backup et restauration : Sauvegardes complètes à la demande et continues via AWS Backup

Modèles de tarification

  • Mode provisionné : Définir à l'avance les capacités de lecture/écriture, idéal pour les charges prévisibles
  • Mode à la demande : Paiement par requête, adapté aux charges variables ou imprévisibles
  • Crédits Capacity : Économies réalisées via l'achat de capacités réservées

Bonnes pratiques

  • Choisir des clés de partition optimales : Assurer une distribution uniforme des données et éviter les "hot spots"
  • Concevoir pour les accès : Structurer les données en fonction des patterns d'accès de l'application
  • Utiliser le modèle Single-Table : Regrouper les entités liées dans une même table pour minimiser les requêtes
  • Gestion des données volumineuses : Stocker les grands objets dans Icône S3S3 avec des références dans DynamoDB
  • Comprendre les limites : 400KB par item, quotas de partition, limitations des LSI
  • Mettre en cache les résultats : Utiliser DAX ou d'autres systèmes de cache pour réduire les coûts
  • Surveiller les métriques : Analyser les patterns d'utilisation via CloudWatch
Applications concrètes

Cas d'usage

E-commerce

Gérer efficacement les paniers d'achat, les profils utilisateurs et les historiques de commandes, tout en absorbant les pics de trafic lors des périodes de forte activité comme le Black Friday sans dégradation de performance.

Applications mobiles

Stocker les données utilisateurs, les préférences et l'historique des activités des applications mobiles avec une synchronisation en temps réel et une disponibilité hors ligne via AWS AppSync et Amazon Cognito.

Analyse de données d'IoT

Traiter et stocker les flux massifs de données générées par des capteurs et appareils IoT, permettant l'analyse en temps réel et le déclenchement d'alertes ou d'actions automatisées via DynamoDB Streams.

Microservices et applications serverless

S'intègre parfaitement avec AWS Lambda pour créer des architectures serverless qui s'adaptent instantanément à la demande, réduisant à zéro les coûts d'infrastructure en période d'inactivité.

Entreprises qui utilisent DynamoDB

De nombreuses entreprises de premier plan exploitent DynamoDB pour leurs applications critiques :

Airbnb
Lyft
Netflix
Samsung
Capital One
BMW
Dropbox
Snapchat