Freigeben über


Azure Cosmos DB-Spark-Connector: Durchsatzsteuerung

GILT FÜR: NoSQL

Mit dem Spark-Connector können Sie über Apache Spark mit Azure Cosmos DB kommunizieren. In diesem Artikel wird beschrieben, wie die Durchsatzsteuerungsfunktion funktioniert. Eine Einführung in die Durchsatzsteuerung bieten unsere Spark-Beispiele in GitHub.

In diesem Artikel wird die Verwendung globaler Steuergruppen für den Durchsatz im Azure Cosmos DB-Spark-Connector dokumentiert. Die Funktion ist aber auch im Java SDK verfügbar. Im SDK können Sie globale und lokale Durchsatzsteuerungsgruppen verwenden, um den Verbrauch von Anforderungseinheiten (Request Units, RUs) im Kontext einer einzelnen Clientverbindungsinstanz zu begrenzen. Dieser Ansatz kann beispielsweise auf verschiedene Vorgänge innerhalb eines einzelnen Microservice oder auf ein einzelnes Datenladeprogramm angewendet werden. Weitere Informationen zur Verwendung der Durchsatzsteuerung im Java SDK finden Sie hier.

Warnung

Die Durchsatzsteuerung wird für den Gatewaymodus nicht unterstützt. Bei serverlosen Azure Cosmos DB-Konten führt der Versuch, mit targetThroughputThreshold einen Prozentsatz zu definieren, derzeit zu einem Fehler. Mit spark.cosmos.throughputControl.targetThroughput kann nur ein absoluter Wert für den Zieldurchsatz/RU angegeben werden.

Warum ist die Durchsatzsteuerung wichtig?

Die Durchsatzsteuerung hilft dabei, den Leistungsbedarf von Anwendungen, die in einem Container ausgeführt werden, zu isolieren. Sie schränkt die Anzahl von Anforderungseinheiten ein, die von einem bestimmten Spark-Client verbraucht werden können.

Eine clientseitige Durchsatzsteuerung ist in verschiedenen weitergehenden Szenarien von Vorteil:

  • Verschiedene Vorgänge und Aufgaben mit unterschiedlichen Prioritäten: Manchmal muss verhindert werden, dass normale Transaktionen durch Datenerfassung oder Kopieraktivitäten gedrosselt werden. Manche Vorgänge oder Aufgaben sind nicht wartezeitempfindlich und können eine Drosselung eher tolerieren als andere.
  • Sicherstellen von Fairness/Isolation für verschiedene Benutzer oder Mandanten: Eine Anwendung wird in der Regel von vielen Benutzern verwendet. Einige Benutzer senden möglicherweise zu viele Anforderungen, die den gesamten verfügbaren Durchsatz beanspruchen und so dazu führen, dass andere Benutzer gedrosselt werden.
  • Lastenausgleich zwischen verschiedenen Azure Cosmos DB-Clients: In manchen Anwendungsfällen muss sichergestellt sein, dass alle Clients einen fairen (gleichen) Anteil des Durchsatzes erhalten.

Die Durchsatzsteuerung ermöglicht eine präzisere Begrenzung der RU-Rate nach Bedarf.

Wie funktioniert die Durchsatzsteuerung?

Um die Durchsatzsteuerung für den Spark-Connector zu konfigurieren, erstellen Sie zunächst einen Container, der Metadaten für die Durchsatzsteuerung definiert. Der Partitionsschlüssel ist groupId, und ttl ist aktiviert. Hier wird dieser Container mithilfe von Spark SQL erstellt und ThroughputControl genannt:

    %sql
    CREATE TABLE IF NOT EXISTS cosmosCatalog.`database-v4`.ThroughputControl 
    USING cosmos.oltp
    OPTIONS(spark.cosmos.database = 'database-v4')
    TBLPROPERTIES(partitionKeyPath = '/groupId', autoScaleMaxThroughput = '4000', indexingPolicy = 'AllProperties', defaultTtlInSeconds = '-1');

Im obigen Beispiel wird ein Container mit Autoskalierung erstellt. Wenn Sie die Standardbereitstellung bevorzugen, können Sie autoScaleMaxThroughput durch manualThroughput ersetzen.

Wichtig

Damit die Durchsatzsteuerung funktioniert, muss der Partitionsschlüssel als /groupId definiert und ttl aktiviert werden.

Innerhalb der Spark-Konfiguration einer bestimmten Anwendung können Sie dann Parameter für die Workload angeben. Im folgenden Beispiel wird die Durchsatzsteuerung als enabled festgelegt. In dem Beispiel werden ein name-Parameter für die Durchsatzsteuerungsgruppe und ein targetThroughputThreshold-Parameter definiert. Außerdem werden die Parameter database und container für die Verwaltung der Durchsatzsteuerungsgruppe definiert:

    "spark.cosmos.throughputControl.enabled" -> "true",
    "spark.cosmos.throughputControl.name" -> "SourceContainerThroughputControl",
    "spark.cosmos.throughputControl.targetThroughputThreshold" -> "0.95", 
    "spark.cosmos.throughputControl.globalControl.database" -> "database-v4", 
    "spark.cosmos.throughputControl.globalControl.container" -> "ThroughputControl"

Im obigen Beispiel wurde der targetThroughputThreshold-Parameter als 0.95 definiert. Das bedeutet, es kommt zu einer Ratenbegrenzung (und zur Wiederholung von Anforderungen), wenn Clients mehr als 95 Prozent (+/- fünf bis zehn Prozent) des Durchsatzes beanspruchen, der dem Container zugeordnet ist. Diese Konfiguration wird als Dokument im Durchsatzcontainer gespeichert, was wie im folgenden Beispiel aussieht:

    {
        "id": "ZGF0YWJhc2UtdjQvY3VzdG9tZXIvU291cmNlQ29udGFpbmVyVGhyb3VnaHB1dENvbnRyb2w.info",
        "groupId": "database-v4/customer/SourceContainerThroughputControl.config",
        "targetThroughput": "",
        "targetThroughputThreshold": "0.95",
        "isDefault": true,
        "_rid": "EHcYAPolTiABAAAAAAAAAA==",
        "_self": "dbs/EHcYAA==/colls/EHcYAPolTiA=/docs/EHcYAPolTiABAAAAAAAAAA==/",
        "_etag": "\"2101ea83-0000-1100-0000-627503dd0000\"",
        "_attachments": "attachments/",
        "_ts": 1651835869
    }

Die Durchsatzsteuerung führt keine RU-Vorabberechnung für die einzelnen Vorgänge aus. Vielmehr wird die RU-Nutzung nach dem Vorgang basierend auf dem Antwortheader nachverfolgt. Insofern basiert die Durchsatzsteuerung auf einer Näherung, sodass nicht garantiert ist, dass der gewünschte Durchsatz jederzeit für die Gruppe verfügbar ist.

Wenn die konfigurierte RU also so niedrig ist, dass sie von einem einzigen Vorgang vollständig ausgeschöpft werden kann, kann die Durchsatzsteuerung nicht verhindern, dass die RU den konfigurierten Grenzwert überschreitet. Die Durchsatzsteuerung funktioniert am besten, wenn der konfigurierte Grenzwert höher ist als ein beliebiger Einzelvorgang, der von einem Client in der spezifischen Steuerungsgruppe ausgeführt werden kann.

Wenn Sie zum Lesen eine Abfrage oder einen Änderungsfeed verwenden, empfiehlt es sich, die Seitengröße in spark.cosmos.read.maxItemCount (Standard: 1.000) auf eine moderate Größe festzulegen. Dadurch kann die Clientdurchsatzsteuerung häufiger neu berechnet und jederzeit präziser widergespiegelt werden. Wenn Sie die Durchsatzsteuerung für einen Massenschreibauftrag verwenden, wird die Anzahl der in einer einzelnen Anforderung ausgeführten Dokumente automatisch auf der Grundlage der Drosselungsrate angepasst, damit die Durchsatzsteuerung so früh wie möglich beginnen kann.

Warnung

Der targetThroughputThreshold-Parameter ist unveränderlich. Wenn Sie den Schwellenwert für den Zieldurchsatz ändern, wird eine neue Durchsatzsteuerungsgruppe erstellt. (Ab der Version 4.10.0 kann diese den gleichen Namen haben.) Wenn Sie sicherstellen möchten, dass der neue Schwellenwert sofort verwendet wird, müssen Sie alle Spark-Aufträge neu starten, die die Gruppe verwenden. Andernfalls wird der neue Schwellenwert nach dem nächsten Neustart verwendet.

Für jeden Spark-Client, der die Durchsatzsteuerungsgruppe verwendet, wird ein Datensatz im ThroughputControl-Container mit einem ttl-Wert von wenigen Sekunden erstellt. Daher verschwinden die Dokumente schnell, wenn ein Spark-Client nicht mehr aktiv ausgeführt wird. Ein Beispiel:

    {
        "id": "Zhjdieidjojdook3osk3okso3ksp3ospojsp92939j3299p3oj93pjp93jsps939pkp9ks39kp9339skp",
        "groupId": "database-v4/customer/SourceContainerThroughputControl.config",
        "_etag": "\"1782728-w98999w-ww9998w9-99990000\"",
        "ttl": 10,
        "initializeTime": "2022-06-26T02:24:40.054Z",
        "loadFactor": 0.97636377638898,
        "allocatedThroughput": 484.89444487847,
        "_rid": "EHcYAPolTiABAAAAAAAAAA==",
        "_self": "dbs/EHcYAA==/colls/EHcYAPolTiA=/docs/EHcYAPolTiABAAAAAAAAAA==/",
        "_etag": "\"2101ea83-0000-1100-0000-627503dd0000\"",
        "_attachments": "attachments/",
        "_ts": 1651835869
    }

In jedem Clientdatensatz stellt das loadFactor-Attribut die Last auf dem spezifischen Client relativ zu anderen Clients in der Durchsatzsteuerungsgruppe dar. Das allocatedThroughput-Attribut gibt an, wie viele RUs derzeit diesem Client zugewiesen werden. Der Spark-Connector passt den zugeordneten Durchsatz für jeden Client basierend auf der jeweiligen Last an. Dadurch erhält jeder Client einen Anteil des verfügbaren Durchsatzes, der proportional zu seiner Last ist. Alle Clients verbrauchen zusammen nicht mehr als die Gesamtmenge, die für die Durchsatzsteuerungsgruppe zugeordnet ist, zu der sie gehören.