Paweł Łukasiewicz
2023-11-15
Paweł Łukasiewicz
2023-11-15
Udostępnij Udostępnij Kontakt
Wprowadzenie

W tym wpisie spojrzymy nieco szerzej na komponenty i ekosystem DynamoDB. Pracujemy tutaj z tabelami, atrybutami i elementami. Tabela zawiera zestaw elementów a elementy zawierają zestawy atrybutów. Atrybut to podstawowy element danych, który nie wymaga dalszej dekompozycji, np. pole.

Klucz główny

Klucz ten służy do unikalnej identyfikacji dla elementów tabeli a indeksy wtórne (o nich za chwilę) zapewniają elastyczność zapytań. DynamoDB strumieniowo rejestruje zdarzenia poprzez modyfikacje danych tabeli.

Przy tworzeniu tabeli, oprócz podania jej nazwy, należy utworzyć klucz główny, który identyfikuje elementy tabeli. Żadne dwa elementy nie mają wspólnego klucza. DynamoDB używa dwóch typów kluczy głównych:

  • partition key (klucz partycji) – ten prosty klucz główny składa się z pojedynczego atrybutu określanego jako ‘klucz partycji’. Wewnętrznie DynamoDB używa wartości klucza jako danych wejściowych dla funkcji haszującej;
  • partition key and sort key (klucz partycji i klucz sortowania) – zwany również Composite Primary Key (złożony klucz podstawowy), to klucz składający się z dwóch atrybutów:
    • klucz partycji;
    • klucz sortowania.

Pierwszy z nich używany jest jako atrybut funkcji haszującej. Atrybut ten pozwala na przechowywanie elementów z tym samym kluczem razem, przy czym ich kolejność jest określona przez klucz sortowania. Elementy takie mogą współdzielić klucz partycji ale nie klucz sortowania.

Atrybuty klucza głównego pozwalają jedynie na wartości skalarne (pojedyncze) oraz łańcuchy znaków, liczby oraz binarne typy danych. Atrybuty nie będące kluczami nie mają tych ograniczeń.

Indeksy pomocnicze

Indeksy te pozwalają na zapytanie o dane z tabeli za pomocą alternatywnego klucza. Ich użycie nie jest wymuszone przez DynamoDB przy czym pozwala na optymalizację zapytań.

W DynamoDB możemy się spotkać z dwoma typami indeksów wtórnych:

  • Global Secondary Index (globalny indeks wtórny) – indeks ten składa się z klucza partycji i klucza sortowania, które mogą różnić się od kluczy tabeli;
  • Local Secondary Index (lokalny indeks wtórny) – indeks ten składa się klucza partycji, który jest identyczny z kluczem tabeli ale różni się kluczem sortowania.

Znamy już podstawowe pojęcia, spójrzmy teraz na możliwe operacje z perspektywy API.

API

API pozwala nam na wykonanie operacji na dwóch płaszczyznach, tj. płaszczyzna danych (tworzenie, odczyt, aktualizacja i usuwanie) oraz operacje strumieniowe, tj. uporządkowany przepływ informacji o zmianach elementów w tabeli DynamoDB.

Do pierwszej grupy zaliczamy poniższe operacje:

  • CreateTable;
  • DescribeTable (operacja zwraca informacje o tabeli, w tym bieżący stan tabeli, czas jej utworzenia, schemat klucza podstawowego i wszelkie indeksy w tabeli);
  • ListTables;
  • UpdateTable;
  • DeleteTable;

W ramach operacji na płaszczyźnie danych możemy wykonywać poniższe operacje CRUD:

Create Read Update Delete
PutItem
BatchWriteItem
GetItem
BatchGetItem
Query
Scan
UpdateItem DeleteItem
BatchWriteItem

Większość operacji nie wymaga większego komentarza. Warto jednak znać różnicę pomiędzy Query a Scan. Pierwsza z nich używa klucza podstawowego lub klucza indeksu. Z kolei Scan (jak sama nazwa wskazuje), skanuje całą tabelę w poszukiwaniu określonego wyniku. DynamoDB zostało zaprojektowane tak, aby być w pełni zoptymalizowane pod kątem zapytań. Na to zagadnienie poświecimy więcej czasu w kolejnych wpisach.

Wracając jednak do omawianych zagadnień...operacje strumieniowe możemy zdefiniować jako:

  • ListStreams;
  • DescribeStream;
  • GetShardIterator;
  • GetRecords;

Wszystkie powyższe operacje najłatwiej opisać jako zmiany zachodzące w naszej aplikacji, które są odzwierciedlone w postaci operacji aktualizacji, tworzenia czy kasowania elementów z tabeli. DynamoDB Streams zapisuje rekord strumienia z atrybutami klucza głównego elementów, które zostały zmodyfikowane. Rekord strumienia zawiera informacji o modyfikacji danych do pojedynczego elementu w tabeli a może zostać skonfigurowany tak, aby przechwytywał dodatkowe informacje takie jak obrazy "przed" i "po" zmodyfikowaniu elementów. Więcej informacji możecie znaleźć tutaj: https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Operations_Amazon_DynamoDB_Streams.html

Przepustowość

W tym wpisie poznajemy jedynie podstawowe pojęcia. Przepustowość, towarzyszące jej jednostki odczytu i zapisu, tryby przetwarzania takie jak On-demand oraz Provisioned, radzenie sobie ze zwiększonym ruchem czy pojęcie throttlingu to niezwykle istotny temat ale trudny do omówienia we wpisie "podstawowe pojęcia". Na ten moment chciałbym, żebyście wiedzieli, że podczas tworzenia tabeli ustawiamy przepustowość, która jest odzwierciedlona przez zarezerwowane jednostki odczytu i zapisu. W momencie przekroczenia tych wartości przez naszą aplikację dochodzi do zakończenia rosnącej liczby żądań niepowodzeniem. W tym celu należy monitorować ustawioną vs używaną przepustowość dla lepszej obsługi żądań. Ten temat zostanie omówiony bardzo dokładnie na późniejszym etapie tego cyklu ponieważ prędzej czy później każdy spotka się z tym tematem – nie chcę jednak na tym etapie komplikować poziomu wpisu i poznanych zagadnień.

Spójność odczytu

Read consistency to kolejne niezwykle ważne pojęcie. DynamoDB używa dwóch trybów odczytu: eventually consistent oraz strong consistent. Ten pierwszy, jak sama nazwa wskazuje, nie gwarantuje, że odczyty zawsze dostarczają aktualne dane. W przypadku rozproszonych systemów może dojść do sytuacji, że dane odczytywane z tabeli DynamoDB mogą nie odzwierciedlać stanu niedawno zakończonej (innej operacji) mającej wpływ na dane zawarte w tabeli. Jeżeli dane żądanie odczytu zostanie powtórzone po krótkim czasie, odpowiedź powinna zawierać najnowsze (aktualne) dane. Musimy pamiętać, że odczyt w trybie eventually consistent jest ustawieniem domyślnym.

Przeciwieństwem tego trybu jest silnie spójny odczyt, tj. strongly consistent read - odczyt zawsze dostarcza aktualnych danych (za wyjątkiem awarii sprzętu czy problemów sieciowych). Na ten moment więcej szczegółowych informacji możecie znaleźć w oficjalnej dokumentacji: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html - na późniejszym etapie tego cyklu skupimy się również na tym problemie, zagłębimy się w jego przyczyny oraz poszukamy rozwiązań mając na uwadze jakie ograniczenia niesie za sobą silnie spójny odczyt.

Partycje

Ostatnie pojęcie, na które spojrzymy w tym wpisie to tzw. partycje. DynamoDB używa partycji do przechowywania danych. To nic innego jak alokacje pamięci masowej w postaci dysków SSD oraz automatyczna funkcjonalność replikowania danych w wielu stefach dostępności w ramach danego regionu AWS. Zarządzanie to odbywa się automatycznie przez DynamoDB.

Na ten moment skupimy się jedynie na informacji, że podczas tworzenia tabeli wchodzi ona w stan CREATING. Jeżeli wszystko przebiegnie pomyślnie, proces tworzenia zostanie ukończony, tabela przejdzie w stan ACTIVE, który pozwala na wykonywanie różnych operacji. Do zmiany partycji dochodzi zwykle po osiągnięciu maksymalnej pojemności bądź zmianie przepustowości. Jest to temat, który poruszymy również w dalszej części cyklu – jak widzicie, podstawowe pojęcia/koncepcje są ze sobą bardzo mocno powiązane. Spróbujmy jednak w pierwszej kolejności utworzyć tabele, wykonać różne operacje, wyszukać interesujące nas informacje – w dalszej części rozszerzymy wszelkie pojęcia. Jeżeli jednak chcecie dowiedzieć się więcej o tym procesie w szczegółach odsyłam do oficjalnej dokumentacji: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.Partitions.html

My przechodzimy do kolejnego wpisu w którym utworzymy sobie lokalną instancję DynamoDB i zaczniemy eksperymentować.