Udostępnij za pośrednictwem


trwałość ziarna ADO.NET

Kod zaplecza magazynu relacyjnego w systemie Orleans jest oparty na ogólnych funkcjach ADO.NET i w związku z tym niezależny od dostawcy bazy danych. Układ Orleans magazynu danych został już wyjaśniony w tabelach środowiska uruchomieniowego. Konfigurowanie parametry połączenia odbywa się zgodnie z opisem w Orleans przewodniku konfiguracji.

Aby utworzyć Orleans funkcję kodu z danym zapleczem relacyjnej bazy danych, wymagane są następujące elementy:

  1. Do procesu należy załadować odpowiednią bibliotekę ADO.NET. Należy to zdefiniować jak zwykle, np. za pośrednictwem elementu DbProviderFactories w konfiguracji aplikacji.
  2. Skonfiguruj ADO.NET niezmienne za pośrednictwem Invariant właściwości w opcjach.
  3. Baza danych musi istnieć i być zgodna z kodem. Jest to wykonywane przez uruchomienie skryptu tworzenia bazy danych specyficznego dla dostawcy. Aby uzyskać więcej informacji, zobacz ADO.NET Configuration (Konfiguracja ADO.NET).

Dostawca magazynu ziarna platformy ADO .NET umożliwia przechowywanie stanu ziarna w relacyjnych bazach danych. Obecnie obsługiwane są następujące bazy danych:

  • SQL Server
  • MySQL/MariaDB
  • PostgreSQL
  • Oracle

Najpierw zainstaluj pakiet podstawowy:

Install-Package Microsoft.Orleans.Persistence.AdoNet

Zapoznaj się z artykułem dotyczącym konfiguracji ADO.NET, aby uzyskać informacje na temat konfigurowania bazy danych, w tym odpowiedniego ADO.NET niezmiennego i skryptów konfiguracji.

Poniżej przedstawiono przykład konfigurowania dostawcy magazynu ADO.NET za pomocą polecenia ISiloHostBuilder:

var siloHostBuilder = new HostBuilder()
    .UseOrleans(c =>
    {
        c.AddAdoNetGrainStorage("OrleansStorage", options =>
        {
            options.Invariant = "<Invariant>";
            options.ConnectionString = "<ConnectionString>";
            options.UseJsonFormat = true;
        });
    });

Zasadniczo musisz ustawić tylko parametry połączenia specyficzne dla dostawcy bazy danych i (Invariantzobacz ADO.NET Configuration), który identyfikuje dostawcę. Możesz również wybrać format, w którym są zapisywane dane, które mogą być binarne (domyślne), JSON lub XML. Chociaż plik binarny jest najbardziej kompaktowy, jest nieprzezroczysty i nie będzie można odczytywać ani pracować z danymi. Plik JSON jest zalecaną opcją.

Następujące właściwości można ustawić za pomocą polecenia AdoNetGrainStorageOptions:

/// <summary>
/// Options for AdoNetGrainStorage
/// </summary>
public class AdoNetGrainStorageOptions
{
    /// <summary>
    /// Define the property of the connection string
    /// for AdoNet storage.
    /// </summary>
    [Redact]
    public string ConnectionString { get; set; }

    /// <summary>
    /// Set the stage of the silo lifecycle where storage should
    /// be initialized.  Storage must be initialized prior to use.
    /// </summary>
    public int InitStage { get; set; } = DEFAULT_INIT_STAGE;
    /// <summary>
    /// Default init stage in silo lifecycle.
    /// </summary>
    public const int DEFAULT_INIT_STAGE =
        ServiceLifecycleStage.ApplicationServices;

    /// <summary>
    /// The default ADO.NET invariant will be used for
    /// storage if none is given.
    /// </summary>
    public const string DEFAULT_ADONET_INVARIANT =
        AdoNetInvariants.InvariantNameSqlServer;

    /// <summary>
    /// Define the invariant name for storage.
    /// </summary>
    public string Invariant { get; set; } =
        DEFAULT_ADONET_INVARIANT;

    /// <summary>
    /// Determine whether the storage string payload should be formatted in JSON.
    /// <remarks>If neither <see cref="UseJsonFormat"/> nor <see cref="UseXmlFormat"/> is set to true, then BinaryFormatSerializer will be configured to format the storage string payload.</remarks>
    /// </summary>
    public bool UseJsonFormat { get; set; }
    public bool UseFullAssemblyNames { get; set; }
    public bool IndentJson { get; set; }
    public TypeNameHandling? TypeNameHandling { get; set; }

    public Action<JsonSerializerSettings> ConfigureJsonSerializerSettings { get; set; }

    /// <summary>
    /// Determine whether storage string payload should be formatted in Xml.
    /// <remarks>If neither <see cref="UseJsonFormat"/> nor <see cref="UseXmlFormat"/> is set to true, then BinaryFormatSerializer will be configured to format storage string payload.</remarks>
    /// </summary>
    public bool UseXmlFormat { get; set; }
}

Trwałość ADO.NET ma funkcjonalność danych wersji i definiuje dowolne (de)serializatory z dowolnymi regułami aplikacji i przesyłaniem strumieniowym, ale obecnie nie ma metody uwidaczniania jej w kodzie aplikacji.

uzasadnienie trwałości ADO.NET

Zasady dotyczące magazynu trwałego opartego na ADO.NET są następujące:

  1. Zapewnij bezpieczeństwo i dostępność danych krytycznych dla działania firmy, gdy dane, format danych i kod ewoluują.
  2. Korzystaj z funkcji specyficznych dla dostawcy i magazynu.

W praktyce oznacza to przestrzeganie ADO.NET celów implementacji i niektórych dodanych logiki implementacji w usłudze ADO. Dostawcy magazynu specyficzne dla platformy NET, którzy umożliwiają ewolucję kształtu danych w magazynie.

Oprócz zwykłych możliwości dostawcy magazynu dostawca ADO.NET ma wbudowaną funkcję:

  1. Zmień dane magazynu z jednego formatu na inny (np. z formatu JSON na binarny), gdy stan zaokrąglania.
  2. Kształtowanie typu, który ma zostać zapisany lub odczytany z magazynu w dowolny sposób. Dzięki temu wersja stanu może ewoluować.
  3. Przesyłanie strumieniowe danych z bazy danych.

Zarówno 1. , jak i 2. można stosować na podstawie dowolnych parametrów decyzyjnych, takich jak identyfikator ziarna, typ ziarna, dane ładunku.

Jest to przypadek, aby można było wybrać format serializacji, np. Proste kodowanie binarne (SBE) i implementuje IStorageDeserializer i IStorageSerializer. Wbudowane serializatory zostały skompilowane przy użyciu tej metody:

Po zaimplementowaniu serializatorów należy dodać je do StorageSerializationPicker właściwości w pliku AdoNetGrainStorage. Oto implementacja elementu IStorageSerializationPicker. Domyślnie StorageSerializationPicker będzie używany. Przykład zmiany formatu magazynu danych lub użycie serializatorów można zobaczyć na stronie RelationalStorageTests.

Obecnie nie ma metody uwidocznienia selektora serializacji do Orleans aplikacji, ponieważ nie ma metody uzyskiwania dostępu do utworzonej AdoNetGrainStoragestruktury .

Cele projektu

1. Zezwalaj na korzystanie z dowolnego zaplecza z dostawcą ADO.NET

Powinno to obejmować najszerszy możliwy zestaw zapleczy dostępnych dla platformy .NET, co jest czynnikiem w instalacjach lokalnych. Niektórzy dostawcy są wyświetlani na liście ADO.NET przegląd, ale nie wszystkie są wymienione, takie jak Teradata.

2. Zachowaj potencjał, aby odpowiednio dostosować zapytania i strukturę bazy danych, nawet jeśli wdrożenie jest uruchomione

W wielu przypadkach serwery i bazy danych są hostowane przez inną firmę w stosunku umownym z klientem. Nie jest to nietypowa sytuacja, w której można znaleźć środowisko hostingu, które jest zwirtualizowane i gdzie wydajność ulega wahaniom z powodu nieprzewidzianych czynników, takich jak hałaśliwe sąsiady lub wadliwy sprzęt. Może nie być możliwe zmianę i ponowne wdrożenie Orleans plików binarnych (ze względów umownych) lub nawet plików binarnych aplikacji, ale zwykle jest możliwe dostosowanie parametrów wdrożenia bazy danych. Zmiana standardowych składników, takich jak Orleans pliki binarne, wymaga bardziej długiej procedury optymalizacji w danej sytuacji.

3. Umożliwia korzystanie z możliwości specyficznych dla dostawcy i specyficznych dla wersji

Dostawcy zaimplementowali różne rozszerzenia i funkcje w swoich produktach. Rozsądnie jest korzystać z tych funkcji, gdy są dostępne. Są to funkcje, takie jak natywna funkcja UPSERT lub PipelineDB w bazie danych PostgreSQL, technologia PolyBase lub natywnie skompilowane tabele i procedury składowane w programie SQL Server.

4. Umożliwia optymalizowanie zasobów sprzętowych

Podczas projektowania aplikacji często można przewidzieć, które dane muszą być wstawiane szybciej niż inne dane, i które dane mogą być najprawdopodobniej umieszczane w zimnym magazynie, co jest tańsze (np. dzielenie danych między dyski SSD i HDD). Dodatkowe zagadnienia obejmują fizyczną lokalizację danych (niektóre dane mogą być droższe (np. SSD RAID viz HDD RAID) lub bardziej zabezpieczone) lub inne podstawy decyzyjne. Powiązane z punktem 3., niektóre bazy danych oferują specjalne schematy partycjonowania, takie jak tabele i indeksy partycjonowane programu SQL Server.

Te zasady mają zastosowanie w całym cyklu życia aplikacji. Biorąc pod uwagę, że jedną z zasad Orleans jest wysoka dostępność, powinno być możliwe dostosowanie systemu magazynu bez przerwy we wdrożeniu Orleans lub powinno być możliwe dostosowanie zapytań zgodnie z danymi i innymi parametrami aplikacji. Przykład dynamicznych zmian można zobaczyć we wpisie w blogu Briana Harry'ego:

Gdy tabela jest mała, prawie nie ma znaczenia, czym jest plan zapytania. Jeśli jest średnio, plan zapytania OK jest w porządku, ale gdy jest ogromny (miliony milionów lub miliardów wierszy), nawet niewielkie różnice w planie zapytania mogą cię zabić. Z tego powodu w dużym stopniu sugerujemy nasze wrażliwe zapytania.

5. Brak założeń dotyczących narzędzi, bibliotek lub procesów wdrażania używanych w organizacjach

Wiele organizacji zna określony zestaw narzędzi bazy danych, na przykład Dacpac lub Red Gate. Może się zdarzyć, że wdrożenie bazy danych wymaga uprawnień lub osoby, takiej jak osoba w roli administratora bazy danych, aby to zrobić. Zwykle oznacza to również, że docelowy układ bazy danych i przybliżony szkic zapytań, które aplikacja utworzy do użycia podczas szacowania obciążenia. Mogą istnieć procesy, na które mogą mieć wpływ standardy branżowe, które nakazują wdrażanie oparte na skryptach. Wykonywanie zapytań i struktur baz danych w skrycie zewnętrznym umożliwia wykonanie tych kroków.

6. Użyj minimalnego zestawu funkcji interfejsu wymaganych do załadowania bibliotek i funkcji ADO.NET

Jest to zarówno szybkie, jak i mniej narażone na rozbieżności implementacji biblioteki ADO.NET.

7. Umożliwianie fragmentowania projektu

Jeśli ma to sens, na przykład u dostawcy magazynu relacyjnego, należy łatwo udostępnić projekt jako fragmentowalny. Oznacza to na przykład brak danych zależnych od bazy danych (np. IDENTITY). Informacje, które odróżniają dane wierszy, powinny opierać się tylko na danych z rzeczywistych parametrów.

8. Łatwe testowanie projektu

Utworzenie nowego zaplecza powinno być tak proste, jak tłumaczenie jednego z istniejących skryptów wdrażania do dialektu SQL zaplecza, który próbujesz zastosować, dodając nowy parametry połączenia do testów (przy założeniu domyślnych parametrów), sprawdzając, czy dana baza danych jest zainstalowana, a następnie uruchamiając testy względem niej.

9. Biorąc pod uwagę poprzednie punkty, wykonaj zarówno przenoszenie skryptów dla nowych zapleczy, jak i modyfikowanie już wdrożonych skryptów zaplecza tak przezroczyste, jak to możliwe

Realizacja celów

Platforma Orleans nie wie o sprzęcie specyficznym dla wdrożenia (który sprzęt może ulec zmianie podczas aktywnego wdrażania), zmianie danych w cyklu życia wdrożenia lub niektórych funkcjach specyficznych dla dostawcy, które mogą być używane tylko w niektórych sytuacjach. Z tego powodu interfejs między bazą danych i Orleans powinien być zgodny z minimalnym zestawem abstrakcji i reguł, aby spełnić te cele, zapewnić niezawodność przed nieprawidłowym użyciem i ułatwić testowanie w razie potrzeby. Tabele środowiska uruchomieniowego, zarządzanie klastrem i konkretna implementacja protokołu członkostwa. Ponadto implementacja programu SQL Server zawiera dostrajanie specyficzne dla wersji programu SQL Server. Kontrakt interfejsu między bazą danych i Orleans jest zdefiniowany w następujący sposób:

  1. Ogólną ideą jest to, że dane są odczytywane i zapisywane za pomocą Orleanszapytań specyficznych dla danego typu. Orleans działa na nazwach kolumn i typach podczas odczytywania oraz nazw parametrów i typów podczas zapisywania.
  2. Implementacje muszą zachowywać nazwy danych wejściowych i wyjściowych oraz typy. Orleans używa tych parametrów do odczytywania wyników zapytania według nazwy i typu. Dostrajanie specyficzne dla dostawcy i specyficzne dla wdrożenia jest dozwolone, a współtworzenie jest zachęcane do obsługi umowy interfejsu.
  3. Implementacja między skryptami specyficznymi dla dostawcy powinna zachować nazwy ograniczeń. Upraszcza to rozwiązywanie problemów ze względu na jednolite nazewnictwo we konkretnych implementacjach.
  4. Version — lub ETag w kodzie aplikacji — dla Orleanselementu reprezentuje unikatową wersję. Typ rzeczywistej implementacji nie jest ważny, o ile reprezentuje unikatową wersję. W implementacji Orleans kod oczekuje podpisanej liczby całkowitej 32-bitowej.
  5. Ze względu na jawność i usuwanie niejednoznaczności oczekuje, Orleans że niektóre zapytania zwracają wartość TRUE jako > wartość 0 lub FALSE jako = 0 . Oznacza to, że liczba wierszy, których dotyczy problem, nie ma znaczenia. Jeśli zostanie zgłoszony błąd lub zostanie zgłoszony wyjątek, zapytanie musi upewnić się, że cała transakcja zostanie wycofana i może zwrócić wartość FALSE lub propagować wyjątek.
  6. Obecnie wszystkie oprócz jednego zapytania to wstawiania lub aktualizowania pojedynczego wiersza (należy pamiętać, że można zamienić UPDATE zapytania na INSERT, pod warunkiem, że skojarzone SELECT zapytania wykonały ostatni zapis).

Aparaty baz danych obsługują programowanie w bazie danych. Jest to podobne do idei ładowania skryptu wykonywalnego i wywoływania go w celu wykonywania operacji bazy danych. W pseudokodzie można go przedstawić jako:

const int Param1 = 1;
const DateTime Param2 = DateTime.UtcNow;
const string queryFromOrleansQueryTableWithSomeKey =
    "SELECT column1, column2 "+
    "FROM <some Orleans table> " +
    "WHERE column1 = @param1 " +
    "AND column2 = @param2;";
TExpected queryResult =
    SpecificQuery12InOrleans<TExpected>(query, Param1, Param2);

Te zasady są również zawarte w skryptach bazy danych.

Niektóre pomysły dotyczące stosowania dostosowanych skryptów

  1. Zmień skrypty na OrleansQuery potrzeby trwałości IF ELSE ziarna, aby niektóre stany zostały zapisane przy użyciu domyślnego INSERT, podczas gdy niektóre stany ziarna mogą używać tabel zoptymalizowanych pod kątem pamięci. Zapytania SELECT muszą zostać odpowiednio zmienione.
  2. Pomysł w 1. programie może służyć do korzystania z innych aspektów specyficznych dla wdrożenia lub dostawcy, takich jak dzielenie danych między SSD lub HDD, umieszczanie niektórych danych w zaszyfrowanych tabelach, a może wstawianie danych statystycznych za pośrednictwem programu SQL-Server-to-Hadoop, a nawet serwerów połączonych.

Zmienione skrypty można przetestować, uruchamiając Orleans zestaw testów lub bezpośrednio w bazie danych przy użyciu na przykład projektu testów jednostkowych programu SQL Server.

Wskazówki dotyczące dodawania nowych dostawców ADO.NET

  1. Dodaj nowy skrypt konfiguracji bazy danych zgodnie z powyższą sekcją Realizacji celów .
  2. Dodaj niezmienną nazwę dostawcy ADO do AdoNetInvariants i ADO.NET danych specyficznych dla dostawcy do dbConstantsStore. Są one (potencjalnie) używane w niektórych operacjach zapytań. np. aby wybrać prawidłowy tryb wstawiania statystyk (np. UNION ALL z lub bez FROM DUAL).
  3. Orleans zawiera kompleksowe testy dla wszystkich magazynów systemowych: członkostwa, przypomnień i statystyk. Dodawanie testów dla nowego skryptu bazy danych odbywa się przez wklejanie istniejących klas testowych i zmianę niezmiennej nazwy ADO. Ponadto należy pochodzić z RelationalStorageForTesting w celu zdefiniowania funkcji testowych dla niezmiennego obiektu ADO.