Amazon DVA-C02: Amazon DynamoDB i projektowanie NoSQL — Przewodnik do nauki
Część AWS Developer Associate DVA-C02 — Przewodnik do nauki. Ćwicz ze zweryfikowanymi odpowiedziami w centrum egzaminów Amazon, albo rozwiąż testy na czas na ExamRoll.io.
Modelowanie danych i wzorce dostępu
Projektowanie DynamoDB zaczyna się od wzorców dostępu: każde zapytanie powinno mapować się na klucz podstawowy, globalny indeks pomocniczy (GSI) lub lokalny indeks pomocniczy (LSI); projekt tabeli jest podyktowany tym, jak aplikacja odczytuje i zapisuje elementy, a nie strukturą schematu relacyjnego. Wybierz klucz partycji o wysokiej kardynalności, aby uniknąć gorących partycji (hot partitions), i użyj złożonego klucza podstawowego (klucz partycji + klucz sortowania), gdy potrzebujesz zapytań o zakres; operacje Query wymagają warunku równości na kluczu partycji i opcjonalnie KeyConditionExpression na kluczu sortowania. W przypadku SDK preferuj abstrakcje DynamoDB Document: użyj DynamoDBDocumentClient z AWS SDK for JavaScript v3 (marshalling/unmarshalling jest obsługiwany automatycznie) lub DynamoDB Enhanced Client w Javie, aby mapować obiekty na atrybuty. Implementuj wzorce jednotabelowe (single-table patterns) tylko wtedy, gdy wzorce odczytu współdzielą klucze i możesz zakodować typy elementów za pomocą atrybutu typu; używaj rzadkich GSI (sparse GSIs), aby udostępniać dodatkowe ścieżki dostępu, zapisując atrybuty tylko w tych elementach, które ich potrzebują. Częstą pułapką jest nadużywanie operacji Scan: skanowanie dużych tabel jest kosztowne i paginowane (LastEvaluatedKey); preferuj Query z ProjectionExpression, aby zmniejszyć zużycie RCU. Do zapisów warunkowych używaj UpdateItem z ConditionExpression lub TransactWriteItems dla zapewnienia atomowości operacji na wielu elementach; obsługuj wyjątek ConditionalCheckFailedException i stosuj mechanizm backoff z jitterem.
Indeksy, zapytania i wzorce transakcyjne
Lokalne indeksy pomocnicze (LSI) są tworzone tylko podczas tworzenia tabeli, współdzielą ten sam klucz partycji co tabela bazowa i zużywają pojemność odczytu tabeli na potrzeby zapytań, podczas gdy GSI można dodawać po utworzeniu tabeli, mają one niezależną pojemność lub rozliczenie na żądanie i pozwalają na użycie innych kluczy partycji. Wywołania Query używają KeyConditionExpression oraz ExpressionAttributeNames/Values; wyrażenia projekcji (projection expressions) zmniejszają transfer danych. GSI są domyślnie ostatecznie spójne (eventually consistent) i generują dodatkowy koszt zapisu, ponieważ każdy zapis do tabeli bazowej, który obejmuje indeksowane atrybuty, tworzy odpowiednie zapisy w GSI — planuj WCUs odpowiednio i monitoruj ConsumedWriteCapacityUnits dla indeksu. Aby uzyskać silną spójność (strong consistency), użyj GetItem lub Query z ConsistentRead=true na tabeli bazowej (GSI nie obsługują odczytów o silnej spójności). Transakcje (TransactWriteItems i TransactGetItems) gwarantują atomowość dla maksymalnie 25 elementów lub 4 MB danych; użyj ReturnValuesOnConditionCheckFailure, aby analizować przyczyny niepowodzeń. BatchWriteItem i BatchGetItem są ograniczone odpowiednio do 25 i 100 elementów i nie są transakcyjne; kod powinien obsługiwać UnprocessedItems, ponawiając operację z użyciem wykładniczego backoffu (exponential backoff). Częstym błędem jest zapominanie o kosztach i implikacjach ostatecznej spójności GSI podczas migracji złączeń relacyjnych (joins) na rzecz indeksów.
Tryby pojemności, optymalizacja wydajności i rozwiązywanie problemów
Wybierz między trybem provisioned a on-demand na podstawie przewidywalności obciążenia: tryb provisioned z Auto Scaling (Application Auto Scaling for DynamoDB) daje kontrolę nad RCU/WCU i kosztami dla stabilnych obciążeń, podczas gdy tryb on-demand upraszcza obsługę nagłych skoków ruchu bez konieczności planowania pojemności, ale przy wyższej cenie za żądanie. Włącz Auto Scaling z docelowym wykorzystaniem (target utilization) i wieloma politykami skalowania; monitoruj metryki CloudWatch, takie jak ConsumedReadCapacityUnits, ConsumedWriteCapacityUnits, ThrottledRequests, SuccessfulRequestLatency, SystemErrors i ConditionalCheckFailedRequests, aby wykrywać gorące punkty (hotspots) i dławienie (throttling). Używaj pojemności adaptacyjnej (adaptive capacity), aby łagodzić dławienie spowodowane pojedynczym kluczem, ale unikaj polegania na niej — projektuj pod kątem równomiernej dystrybucji kluczy. Dla obciążeń z dużą liczbą odczytów rozważ użycie DAX w celu uzyskania odczytów na poziomie mikrosekund lub buforowanie za pomocą Amazon ElastiCache; dla obciążeń z dużą liczbą zapisów stosuj sharding zapisu (przez prefiksy lub kubełki), aby rozproszyć zapisy między partycjami. Rozwiązuj problemy, analizując wyjątek ProvisionedThroughputExceededException i implementując w klientach SDK mechanizm exponential backoff z jitterem, włącz CloudWatch Contributor Insights, aby znaleźć gorące klucze (hot keys), i używaj Parallel Scan do jednorazowych, dużych analiz z segmentowanymi workerami. Pamiętaj o limitach rozmiaru elementu (400 KB) i o tym, że duże elementy zwiększają zużycie RCU/WCU; w razie potrzeby dziel duże obiekty binarne (bloby) na części w S3, przechowując metadane w DynamoDB.
Strumienie, integracje, kopie zapasowe i najlepsze praktyki operacyjne
DynamoDB Streams przechwytują zmiany na poziomie elementów (INSERT, MODIFY, REMOVE) w kolejności dla każdego klucza partycji i integrują się bezpośrednio z Lambda poprzez mapowanie źródła zdarzeń (skonfiguruj startingPosition jako TRIM_HORIZON lub LATEST, ustaw batchSize i maximumBatchingWindowInSeconds oraz dostosuj bisectBatchOnError i maximumRetryAttempts). Aby zapewnić niezawodne przetwarzanie, użyj Lambda z kolejką martwych listów (Dead-Letter Queue - SQS lub SNS) lub przekieruj rekordy strumienia do Kinesis lub Kinesis Data Firehose w celach analitycznych. Włącz Time To Live (TTL), aby elementy automatycznie wygasały; pamiętaj, że usunięcia TTL są przetwarzane ostatecznie (eventually processed) i nie należy na nich polegać w celu uzyskania natychmiastowej spójności. Używaj Point-in-Time Recovery (PITR) i kopii zapasowych na żądanie do odtwarzania po awarii (disaster recovery); w celu zapewnienia dostępności w wielu regionach użyj Global Tables do replikacji zmian między regionami. Stosuj role IAM z zasadą najmniejszych uprawnień (least-privilege) do usług i nadawaj funkcjom Lambda tylko niezbędne akcje, takie jak dynamodb:Query, dynamodb:PutItem, dynamodb:UpdateItem, dynamodb:GetItem, dynamodb:DescribeStream i dynamodb:ListStreams. Częste pułapki operacyjne obejmują brak logiki ponawiania prób/wycofywania (retry/backoff) w konsumentach, nieodpowiednie planowanie przepustowości GSI oraz brak monitorowania IteratorAge strumieni w celu wykrywania opóźnień; instrumentuj za pomocą CloudWatch Logs i X-Ray, aby śledzić opóźnienia end-to-end.
Problem praktyczny: Scenariusz użycia
Scenariusz: Firma AcmeMedia prowadzi katalog metadanych w pojedynczej tabeli DynamoDB w regionie us-east-1, zawierającej dziesiątki milionów elementów. Nowo uruchomiony potok przetwarzania obrazów wymaga zapytań o niskim opóźnieniu według photographerId i zakresu uploadTimestamp, a konsumenci Lambda w dalszej części procesu muszą niezawodnie przetwarzać zmiany.
Wyzwanie: Dodaj wydajną ścieżkę zapytań dla photographerId + zakresu timestamp bez przeprojektowywania tabeli, zapewnij, że procesy Lambda w dalszej części przetwarzają rekordy strumienia z semantyką „co najmniej raz” (at-least-once) i unikaj gorących partycji (hot partitions) dla fotografów o dużej aktywności.
Zalecane podejście:
- Utwórz GSI o nazwie
photographer-gsiz kluczem partycjiphotographerIdi kluczem sortowaniauploadTimestamp; użyj APIUpdateTablelub konsoli, aby dodać GSI i określić rozliczenieProvisionedThroughputlubOn-Demandza pomocąUpdateTableoraz ustawić monitorowanieIndexStatus. - Podczas zapisywania elementów dołączaj atrybuty
photographerIdiuploadTimestamp, aby projekcja indeksu była rzadka (sparse); wybierzProjectionType=INCLUDEz atrybutami niebędącymi kluczami, które są potrzebne do zapytań, aby zmniejszyć koszty przechowywania i zapisu. - Skonfiguruj DynamoDB Streams jako
ENABLEDna tabeli i utwórz mapowanie źródła zdarzeń Lambda zstartingPosition=TRIM_HORIZON, dostosowanymbatchSize(np. 100),bisectBatchOnError=true,maximumRetryAttempts=2oraz ustaw kolejkę SQS jako miejsce docelowe dla martwych listów (Dead-Letter Destination) w konfiguracji funkcji Lambda. - Zaimplementuj ponawianie prób po stronie klienta SDK z losowym opóźnieniem (jitter) (użyj wbudowanej strategii ponawiania prób w AWS SDK) i zastosuj sharding zapisu (write sharding), jeśli pojedynczy
photographerIdnadal powoduje dławienie (throttling) (dodaj prefiks dophotographerIdz N kubełków podczas zapisu i usuń prefiks po stronie klienta podczas odczytu).
Uzasadnienie: Dodanie GSI udostępnia wymagany wzorzec dostępu bez zmiany podstawowego klucza głównego; projekcja tylko niezbędnych atrybutów zmniejsza koszt zapisu do GSI. Strumienie + Lambda z DLQ i mechanizmami ponawiania prób zapewniają niezawodne przetwarzanie „co najmniej raz” (at-least-once), podczas gdy sharding chroni przed gorącymi partycjami (hot partitions) wynikającymi z ruchu o wysokiej kardynalności.
← Amazon API Gateway i integracja aplikacji · Wszystkie domeny · CloudFormation i infrastruktura jako kod (SAM →
Przećwicz te pytania → · Testy na czas na ExamRoll.io →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
Zdaj egzamin →Related guides
- Amazon DVA-C02: Amazon API Gateway i integracja aplikacji — Przewodnik do nauki
- Amazon DVA-C02: Bazy danych i buforowanie (RDS, Aurora, ElastiCache, Timestream, Proxy) — Przewodnik do nauki
- Amazon DVA-C02: Bezpieczeństwo, IAM, KMS i zarządzanie sekretami (Cognito, Secrets Manager, SSM) — Przewodnik do nauki