Zurück zum Katalog
Season 17 12 Episoden 46 min 2026

Apache Cassandra with Python

Ausgabe 2026. Eine technische Podcast-Serie, die die verteilte Architektur von Apache Cassandra untersucht und zeigt, wie man mithilfe des DataStax Python Driver damit interagiert. Behandelt Datenmodellierung, Execution Profiles, LWTs, Async-Abfragen und den cqlengine Object Mapper.

Datenbanken Verteiltes Rechnen
Apache Cassandra with Python
Aktuelle Wiedergabe
Click play to start
0:00
0:00
1
Das große Ganze
Eine Einführung in Apache Cassandra. Erfahren Sie, warum global skalierende Anwendungen diese verteilte NoSQL-Datenbank wählen und wie sie sich von traditionellen relationalen Systemen unterscheidet.
4m 04s
2
Consistent Hashing und der Ring
Tauchen Sie in die Architektur von Cassandra ein. Wir untersuchen Consistent Hashing, den Token Ring und wie Daten über mehrere Knoten hinweg ohne einen Master-Server partitioniert werden.
4m 05s
3
Query-Driven Data Modeling
Vergessen Sie alles, was Sie über relationale Datenbanken wissen. Erfahren Sie, wie die abfragegesteuerte Modellierung von Cassandra Denormalisierung erfordert und was der entscheidende Unterschied zwischen Partition Keys und Clustering Keys ist.
3m 14s
4
Verbindung mit Python herstellen
Der Einstieg in den DataStax Python Driver. Lernen Sie, wie man einen Cluster instanziiert, sich mit einer Session verbindet und die Kommunikation mit Ihren Cassandra-Knoten herstellt.
4m 06s
5
Execution Profiles
Verwalten Sie komplexe Workloads nahtlos durch die Verwendung von Execution Profiles. Erfahren Sie, wie Sie Load Balancing, Timeouts und Consistency Levels pro Abfrage konfigurieren, ohne Ihr Cluster-Setup zu verunreinigen.
4m 14s
6
Prepared Statements
Lernen Sie, wie man CQL-Befehle aus Python heraus ausführt. Wir behandeln Simple Statements und die entscheidenden Performance-Vorteile bei der Verwendung von Prepared Statements für häufige Abfragen.
3m 18s
7
Paging von großen Abfragen
Bringen Sie Ihre App niemals zum Absturz, indem Sie einen riesigen Datensatz in den Arbeitsspeicher laden. Entdecken Sie, wie der Python Driver große Abfrageergebnisse automatisch paginiert und wie Sie Fetch Sizes verwalten.
3m 37s
8
Async-Abfragen mit hohem Durchsatz
Maximieren Sie den Durchsatz Ihrer Anwendung. Lernen Sie, wie Sie execute_async, ResponseFutures und Callbacks verwenden, um nebenläufige Anfragen an Cassandra zu stellen.
4m 06s
9
Lightweight Transactions
Implementieren Sie Compare-and-Set-Operationen sicher. Erfahren Sie, wie Lightweight Transactions (LWTs) in Cassandra funktionieren und wie Sie die spezielle applied-Spalte in Ihren Python-Ergebnissen untersuchen.
3m 40s
10
Die Object Mapper Modelle
Vermeiden Sie rohe CQL-Strings und modellieren Sie Ihre Daten mit Python-Klassen. Erfahren Sie, wie Sie cqlengine verwenden, um Tabellen zu definieren, Primary Keys festzulegen und Ihr Schema zu synchronisieren.
4m 04s
11
Abfragen mit cqlengine erstellen
Rufen Sie Daten fließend ab und filtern Sie sie mithilfe von QuerySet-Objekten im cqlengine Object Mapper. Wir behandeln Filteroperatoren, Immutability und Einschränkungen bei der Sortierung.
4m 21s
12
Vector Search für KI
Machen Sie Ihre Fähigkeiten mit der Vector Search von Cassandra 5.0 zukunftssicher. Entdecken Sie, wie Sie hochdimensionale Vektoren speichern und abfragen können, um moderne KI- und Machine-Learning-Anwendungen anzutreiben.
4m 10s

Episoden

1

Das große Ganze

4m 04s

Eine Einführung in Apache Cassandra. Erfahren Sie, warum global skalierende Anwendungen diese verteilte NoSQL-Datenbank wählen und wie sie sich von traditionellen relationalen Systemen unterscheidet.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 1 von 12. Relationale Datenbanken stoßen hart an ihre Grenzen, wenn du versuchst, sie über mehrere Kontinente hinweg zu deployen. Am Ende kämpfst du mit Latenz, Downtime oder einer instabilen Architektur, bei der ein einziger ausfallender Server deine Write Operations lahmlegt. Massiver globaler Scale erfordert ein völlig anderes Datenbankparadigma. Dieses Paradigma ist Apache Cassandra. Es ist eine verteilte Open-Source-NoSQL-Datenbank, die für immensen Scale gebaut wurde. Wenn Engineers sich Cassandra zum ersten Mal ansehen, bringen sie oft Altlasten aus relationalen Systemen mit. Sie suchen nach dem Primary Node, der die Writes verarbeitet, und den Read-Only Replicas, die ihm folgen. Du musst dieses mentale Modell sofort über Bord werfen. Cassandra verwendet kein Primary-Replica-Design. Es arbeitet komplett mit einer masterlosen Multi-Primary-Architektur. Jeder einzelne Node im Cluster ist identisch. Jeder Node kann einen Read Request annehmen, und jeder Node kann einen Write Request annehmen. Um zu verstehen, warum das so funktioniert, wirf einen Blick auf seine Geschichte. Cassandra wurde ursprünglich entwickelt, indem zwei große Forschungsdurchbrüche kombiniert wurden. Erstens übernahm es das vollständig verteilte, masterlose Netzwerkdesign von Amazon Dynamo. Das legt fest, wie Nodes kommunizieren, sich gegenseitig entdecken und Daten im Netzwerk replizieren. Zweitens adaptierte es die Log-Structured Storage Engine von Google Bigtable, die regelt, wie Daten physisch auf die Disk geschrieben werden. Das Ergebnis ist ein System, das speziell für kontinuierliche Verfügbarkeit über mehrere Datacenter hinweg entwickelt wurde. Stell dir ein globales soziales Netzwerk vor. Du hast gleichzeitig aktive User in Tokio, London und New York. Wenn ein User in London sein Profil updatet, muss diese Write Operation sofort passieren. Das Routing dieses Requests über den Atlantik zu einer einzigen zentralen Datenbank ist zu langsam. Mit Cassandra schreibt der User auf einen lokalen Node im Londoner Datacenter. Dieser Node nimmt den Write lokal an und übernimmt sofort die Verantwortung dafür, ihn im Hintergrund nach Tokio und New York zu replizieren. Hier ist die entscheidende Erkenntnis. Weil jeder Node als Primary agiert, gibt es keinen Single Point of Failure. Cassandra ordnet seine Nodes in einem logischen Ring an. Wenn Daten in das System kommen, bestimmt ein mathematischer Hash exakt, welche Nodes im Ring diese spezifischen Daten besitzen. Wenn ein großer Ausfall das komplette Londoner Datacenter vom Netz nimmt, geht das soziale Netzwerk nicht down. Tokio und New York akzeptieren weiterhin Reads und Writes ohne Unterbrechung. Wenn London wieder online kommt, syncen die anderen Datacenter die fehlenden Daten automatisch auf die wiederhergestellten Nodes. So erreichst du echte globale Verfügbarkeit mit Zero Downtime. Dieses masterlose Design bedeutet auch, dass das Scaling vorhersehbar und linear ist. Wenn du mehr Storage oder mehr Write Capacity brauchst, hängst du einfach einen weiteren Node in den Ring. Der Cluster erkennt die neue Hardware automatisch und verteilt die Daten neu, um die Last gleichmäßig auf die aktiven Maschinen zu verteilen. Cassandra zwingt dich, den Komfort traditioneller Database Queries gegen etwas einzutauschen, das at scale viel schwieriger zu bauen ist: die absolute Garantie, dass deine Datenbank online bleibt und deine Operations erfolgreich sind, egal welche Hardware ausfällt. Wenn du die Show unterstützen möchtest, kannst du auf Patreon nach DevStoriesEU suchen. Das war’s für diese Folge. Danke fürs Zuhören und keep building!
2

Consistent Hashing und der Ring

4m 05s

Tauchen Sie in die Architektur von Cassandra ein. Wir untersuchen Consistent Hashing, den Token Ring und wie Daten über mehrere Knoten hinweg ohne einen Master-Server partitioniert werden.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 2 von 12. Naives Data Hashing bricht in dem Moment komplett zusammen, in dem du einen neuen Server zu deinem Database Cluster hinzufügst. Wenn sich die Anzahl der Server ändert, müssen fast alle Daten an einen neuen Ort verschoben werden. Die Lösung für dieses Skalierungschaos ist Consistent Hashing und The Ring. Eine Standardmethode, um Daten auf mehrere Server zu verteilen, ist Modulo Hashing. Wenn du acht Nodes hast, nimmst du einen Partition Key wie eine User ID, hashst ihn und teilst das Ergebnis durch acht. Der Restwert sagt dir, welche Node das User Profile bekommt. Das funktioniert perfekt, bis dein Storage voll ist und du eine neunte Node anschließt. Jetzt teilst du durch neun. Die Restwerte ändern sich. Fast jedes User Profile in deinem System gehört plötzlich auf einen anderen Server. Das verursacht einen massiven Sturm an Datenbewegungen, der den Cluster in die Knie zwingt. Cassandra vermeidet das komplett. Es nutzt Consistent Hashing, um Daten berechenbar über den Cluster zu verteilen, ohne sich auf einen zentralen Coordinator zu verlassen. Statt einer einfachen Modulo-Berechnung mappt Cassandra sowohl die Daten als auch die Nodes auf einen festen, durchgehenden kreisförmigen Raum, den sogenannten Token Ring. Standardmäßig nutzt Cassandra eine Hash-Funktion, die einen riesigen Bereich an möglichen Zahlen generiert. Der niedrigste mögliche Hash-Wert verbindet sich direkt wieder mit dem höchsten und bildet so einen geschlossenen Kreis. Jeder physischen Node im Cluster wird eine bestimmte Nummer, ein sogenanntes Token, irgendwo auf diesem Ring zugewiesen. Wenn du ein User Profile einfügst, hasht Cassandra die User ID, um ein Token zu generieren. Um herauszufinden, welcher Node dieses Profil gehört, lokalisiert das System das Data Token auf dem Ring und bewegt sich im Uhrzeigersinn. Die erste Node, auf die es trifft, ist der Owner. Denk nochmal an unseren Acht-Node-Cluster zurück. Wenn wir eine neunte physische Node hinzufügen, bekommt sie ein einzelnes neues Token auf dem Ring zugewiesen und landet zwischen zwei existierenden Nodes. Weil die Data Ownership dadurch bestimmt wird, dass man den Ring im Uhrzeigersinn abläuft, übernimmt diese neue neunte Node nur ein bestimmtes Slice an Daten von ihrem direkten Nachbarn im Uhrzeigersinn. Die anderen sieben Nodes machen gar nichts. Ihre Daten bleiben komplett unberührt. Hier ist der entscheidende Punkt. Genau ein Token an eine physische Node zuzuweisen, sorgt für operative Probleme. Es ist schwierig, die Daten perfekt zu balancen, und wenn du eine neue Node hinzufügst, ist nur ein benachbarter Server dafür verantwortlich, die Daten zu übergeben. Dieser einzelne Nachbar wird unter der hohen Last komplett plattgemacht. Um das zu fixen, nutzt Cassandra Virtual Nodes, oder vNodes. Anstatt einem physischen Server ein riesiges, zusammenhängendes Slice des Rings zu geben, zerteilen vNodes den Ring in viele kleinere Ranges. Einer einzelnen physischen Node werden Hunderte verschiedener Tokens zugewiesen, die zufällig auf dem Ring verteilt sind. Wenn du diese neunte physische Node mit vNodes hinzufügst, beansprucht sie viele kleine Slices des Rings von allen existierenden Servern gleichzeitig. Statt dass jetzt ein Nachbar das ganze Heavy Lifting übernimmt, teilt sich der gesamte Cluster gleichmäßig die Arbeit, die Daten auf die neue Maschine zu streamen. Consistent Hashing und Virtual Nodes entkoppeln das Data Placement von der reinen Anzahl an physischen Servern. Das erlaubt es einem Cluster, reibungslos zu skalieren und berechenbar zu arbeiten, ohne dass ein zentraler Master diktiert, wo die Daten landen sollen. Das war's für diese Folge. Bis zum nächsten Mal!
3

Query-Driven Data Modeling

3m 14s

Vergessen Sie alles, was Sie über relationale Datenbanken wissen. Erfahren Sie, wie die abfragegesteuerte Modellierung von Cassandra Denormalisierung erfordert und was der entscheidende Unterschied zwischen Partition Keys und Clustering Keys ist.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 3 von 12. In einer relationalen Datenbank baust du zuerst deine Tabellen, definierst deine Beziehungen und schreibst dann deine Queries. Bei Cassandra wird deine Datenbank scheitern, wenn du deine genauen Queries nicht schon kennst, bevor du loslegst. Das ist das Kernprinzip von Query Driven Data Modeling. Viele Entwickler kommen mit starken relationalen Gewohnheiten zu Cassandra. Du suchst natürlich nach Wegen, deine Daten zu normalisieren, Foreign Keys einzurichten und Duplikate zu vermeiden. Diese Denkweise musst du komplett ablegen. Cassandra unterstützt keine Joins. Wenn du versuchst, deine Daten über mehrere Tabellen hinweg zu normalisieren, machst du am Ende Joins in deinem Application Code, was die Performance-Vorteile zerstört, wegen derer du dich überhaupt erst für Cassandra entschieden hast. Cassandra erfordert Query Driven Data Modeling. Du fängst damit an, die genauen Fragen abzubilden, die deine Application an die Datenbank stellen muss. In diesem Modell entspricht eine Query typischerweise einer Tabelle. Wenn du auf drei verschiedene Arten auf dieselben Daten zugreifen musst, erstellst du drei verschiedene Tabellen, die dieselben Daten enthalten. Das bringt uns zur Denormalisierung. Daten zu duplizieren ist hier kein Fehler, es ist die grundlegende Strategie. Speicherplatz ist billig, aber verteilte Reads über ein Netzwerk sind teuer. Indem du die Daten genau in der Form deiner Read Query zusammen schreibst, kann Cassandra sie in einer einzigen Operation abrufen, ohne den gesamten Cluster durchsuchen zu müssen. Damit das funktioniert, musst du den Primary Key verstehen. Er ist nicht nur ein Unique Identifier. Er steuert genau, wo und wie deine Daten auf der Disk gespeichert werden. Der Primary Key hat zwei verschiedene Teile: den Partition Key und den Clustering Key. Der Partition Key legt fest, welcher physische Node in deinem Cluster die Daten hält. Alle Rows, die denselben Partition Key teilen, werden zusammen auf demselben Node gespeichert. Der Clustering Key bestimmt die Sortierreihenfolge dieser Rows auf der Disk innerhalb dieser spezifischen Partition. Nimm das Magazin-Publikations-Szenario aus der Documentation. Angenommen, deine Application muss alle Magazine eines bestimmten Verlags abrufen. Dein Partition Key muss der Name des Verlags sein. Wenn die Query reinkommt, hasht Cassandra den Verlagsnamen, identifiziert den exakten Node, der die Daten dieses Verlags hält, und geht direkt dorthin. Um die Ergebnisse natürlich zu ordnen, könntest du das Publikationsdatum als deinen Clustering Key verwenden. Jetzt sind nicht nur alle Magazine für diesen Verlag auf einem Node gruppiert, sondern sie sind auch physisch in chronologischer Reihenfolge gespeichert. Die Datenbank streamt die vorsortierten Daten einfach zurück. Hier ist der entscheidende Punkt. Du tauschst Write-Komplexität gegen massive Read-Geschwindigkeit. Du schreibst dieselben Daten in mehrere Tabellen, um verschiedene Application Views zu bedienen, aber wenn ein User nach diesen Daten fragt, kommen sie in Millisekunden zurück, weil die Datenbank null Rechenaufwand betreiben muss, um sie zusammenzustellen. Danke fürs Zuhören. Macht's gut, Leute.
4

Verbindung mit Python herstellen

4m 06s

Der Einstieg in den DataStax Python Driver. Lernen Sie, wie man einen Cluster instanziiert, sich mit einer Session verbindet und die Kommunikation mit Ihren Cassandra-Knoten herstellt.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 4 von 12. Wenn du dich mit einer traditionellen Datenbank verbindest, richtest du deine Application auf eine einzelne Host-Adresse. Verbindest du dich aber mit einer verteilten Datenbank, denkst du vielleicht, du müsstest dutzende Server-Adressen manuell in deinen Configuration Files tracken. Musst du aber nicht, denn dein Database Driver fungiert eigentlich als smarter Router. Heute schauen wir uns das Connecting mit Python an. Stell dir einen Python-Microservice vor, der gerade bootet. Er muss eine Verbindung zu einem lokalen Cassandra-Cluster mit drei Nodes herstellen. Zu Beginn importierst du die Cluster-Klasse aus dem cassandra dot cluster Modul. Du initialisierst diese Klasse, indem du ihr eine Liste von IP-Adressen übergibst, die als Contact Points bekannt sind. Falls deine Nodes einen Non-Standard-Port verwenden, kannst du hier auch ein Port-Argument angeben; andernfalls ist der Default 9042. Developer verwechseln diesen Schritt oft mit dem Bauen eines Standard-Single-DSN Connection Strings, bei dem du explizit auflisten musst, womit genau du kommunizieren willst. Bei Cassandra musst du nicht jeden einzelnen Node in deiner Infrastructure auflisten. Wenn du ein riesiges Cluster mit dreißig Nodes hast, ist es völlig in Ordnung, nur zwei oder drei IP-Adressen als Contact Points zu übergeben. Hier ist der entscheidende Punkt: Wenn der Python Driver startet, verbindet er sich mit einem dieser Contact Points, um sich selbst zu bootstrappen. Er fragt System Tables ab, um die aktuelle Cluster Topology herunterzuladen. Dadurch entdeckt er automatisch die IP-Adressen der restlichen Nodes. Der Driver pflegt diese Network Map dynamisch im Hintergrund. Wenn du später skalierst und Nodes hinzufügst, erkennt der Driver die Änderung und passt sein Routing automatisch an, ohne dass ein Application Restart nötig ist. Sobald du dein Cluster-Objekt mit diesen initialen Contact Points instanziiert hast, rufst du seine connect-Methode auf. Das gibt ein Session-Objekt zurück. Die Session übernimmt das eigentliche Connection Pooling zu den Nodes, die sie gerade entdeckt hat. Beim Aufruf von connect kannst du optional einen Keyspace-Namen übergeben. Ein Keyspace fungiert als Namespace für deine Daten. Wenn du ihn angibst, setzt der Driver ihn als Default für alle zukünftigen Operations auf dieser Session. Weil die Session unter der Haube komplexe Connection Pools managt, ist sie so designt, dass sie long-lived und thread-safe ist. Normalerweise erstellst du beim Application Startup eine Session und verwendest sie wieder. Der zweite Teil davon ist nun das Verbinden mit einem Managed Cloud Service wie DataStax Astra. Astra funktioniert anders und gibt keine rohen IP-Adressen für Contact Points preis. Stattdessen lädst du ein Secure Connect Bundle herunter. Das ist ein Zip-File, das die benötigten Certificates und die Details für die Mutual TLS Connection enthält. In deinem Python-Code überspringst du die Liste der IP-Adressen. Stattdessen übergibst du dem Cluster-Objekt ein Cloud Configuration Dictionary. Dieses Dictionary enthält einen Key namens secure connect bundle, der auf den lokalen File Path deines Zip-Files zeigt. Du kombinierst das mit einem Plaintext Authentication Provider Objekt, das mit deiner Client ID und deinem Secret konfiguriert ist. Der Aufruf von connect liefert dann ein Standard-Session-Objekt, das genau wie das lokale Cluster Setup funktioniert. Das wichtigste Takeaway ist: Egal, ob du ein paar lokale IP-Adressen oder ein Cloud Secure Bundle übergibst, der Python Driver nimmt deinen initialen Entry Point, mappt das Distributed Database Network und abstrahiert die Routing Logic komplett von deinem Application Code. Das war's für diese Folge. Danke fürs Zuhören und keep building!
5

Execution Profiles

4m 14s

Verwalten Sie komplexe Workloads nahtlos durch die Verwendung von Execution Profiles. Erfahren Sie, wie Sie Load Balancing, Timeouts und Consistency Levels pro Abfrage konfigurieren, ohne Ihr Cluster-Setup zu verunreinigen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 5 von 12. Wenn deine Application wächst, wird ein One-Size-Fits-All Timeout oder Consistency Level für all deine Datenbank-Queries zu einem massiven operationalen Flaschenhals. Am Ende brechen deine Background Jobs vorzeitig ab oder dein User Interface blockiert, während es auf einen Heavy Read wartet. Execution Profiles sind der Mechanismus, der dieses Problem löst. Viele Entwickler verwechseln die Execution Configuration mit dem Legacy Cluster-Level Setup. In älteren Paradigmen hast du globale Parameter direkt auf dem Cluster-Objekt definiert, was bedeutete, dass jede Query exakt dasselbe Timeout hatte. Execution Profiles ersetzen dieses starre Muster. Sie erlauben es dir, mehrere unterschiedliche Konfigurationen gleichzeitig innerhalb einer einzigen aktiven Session zu verwalten. Stell dir eine Multi-Tenant Web Application vor. Dein Frontend Interface braucht ein striktes Timeout von einer Sekunde, um sicherzustellen, dass die Webseiten snappy bleiben. Gleichzeitig brauchen deine Background Reporting Tasks dreißig Sekunden, um große Partitions sicher zu aggregieren. Ein Execution Profile ist ein eigenständiges, benanntes Bundle von Request Settings, das präzise auf diese unterschiedlichen Workloads zugeschnitten ist. Um das zu bauen, erstellst du zunächst Instanzen eines Execution Profile Objekts. Für den Reporting Task instanziierst du ein Profil und setzt den Request Timeout Parameter auf dreißig Sekunden. Du kannst noch weiter gehen und eine spezifische Load Balancing Policy an dieses Objekt hängen, um diese Heavy Analytical Reads vielleicht exklusiv an ein dediziertes Analytics Data Center zu routen. Danach erstellst du ein zweites, separates Profil-Objekt für dein User Interface und weist ihm ein Timeout von einer Sekunde und eine lokale Load Balancing Policy zu. Du kannst auch verschiedene Retry Policies oder Consistency Levels in diese Profile bundeln, je nachdem, was die Query verlangt. Hier ist der entscheidende Punkt. Du registrierst diese Profile einmalig während deines initialen Cluster Setups, anstatt sie während der Query Execution selbst zu bauen. Bei der Instanziierung des Clusters übergibst du ein Dictionary an das Execution Profiles Argument. Dieses Dictionary mappt einfache String-Namen auf die Profil-Objekte, die du gerade erstellt hast. Der Driver managt diese Konfigurationen im Hintergrund. Es gibt immer ein eingebautes Fallback-Profil, das du überschreiben kannst, indem du eine Konfiguration auf eine spezifische Konstante namens Execution Profile Default mappst. Wenn du eine Query ausführst, ohne explizit ein Profil zu nennen, wendet der Driver automatisch diese Default Settings an. Wenn du dann tatsächlich eine Query ausführen musst, nutzt du die Standard-Methoden Session Execute oder Execute Async. Zusammen mit deinem Query String oder Prepared Statement übergibst du ein Execution Profile Argument mit dem einfachen String-Namen, den du zuvor registriert hast. Der Driver fängt diesen Namen ab, holt sich die damit verknüpften gebündelten Settings und wendet sie auf diesen spezifischen Request an. Deine User Interface Query wird strikt bei einer Sekunde gekappt, und der Background Job läuft bequem für dreißig Sekunden. Beide Queries laufen parallel, gemultiplext über exakt dieselbe Session und exakt denselben Connection Pool. Wenn du deine Konfiguration in Execution Profiles auslagerst, entkoppelt das dein Query-Verhalten von deiner physischen Datenbankverbindung. Das erlaubt es einer einzelnen Application, ihren Datenbank-Traffic dynamisch an die spezifischen Bedürfnisse jeder Funktion anzupassen, ohne jemals separate Sessions aufbauen zu müssen. Danke fürs Dabeisein. Ich hoffe, du hast etwas Neues gelernt.
6

Prepared Statements

3m 18s

Lernen Sie, wie man CQL-Befehle aus Python heraus ausführt. Wir behandeln Simple Statements und die entscheidenden Performance-Vorteile bei der Verwendung von Prepared Statements für häufige Abfragen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 6 von 12. Wenn du für deine High-Throughput-Queries einfache String-Formatierung verwendest, zwingst du deine Datenbank dazu, wertvolle CPU-Zyklen zu verbrennen, weil sie exakt dieselbe Struktur tausende Male pro Sekunde neu parsen muss. Der Weg, um diese Verschwendung zu stoppen und die Performance deiner Anwendung massiv zu verbessern, ist die Nutzung von Prepared Statements. Wenn du dich mit Cassandra verbindest, ist der direkteste Weg, mit der Datenbank zu interagieren, einen String an die session dot execute Methode zu übergeben. Du übergibst ihr eine Query, und sie gibt ein Result Set zurück. Standardmäßig kommt jede Row in diesem Ergebnis als Python namedtuple zurück. Das bedeutet, du kannst auf deine Column-Werte mit einfacher Dot-Notation zugreifen, wie row dot name oder row dot age. Das ist sauber und funktioniert gut für einmalige Operationen. Aber einen Raw String zu senden, ist für Queries, die du ständig ausführst, extrem ineffizient. Du denkst vielleicht, dass du schon alles richtig machst, wenn du Positional Parameters verwendest. Wenn du einen Query String mit Prozent-S-Markern zusammen mit einer Sequenz von Werten übergibst, formatiert der Python Driver diese Query sicher. Das verhindert Injection-Attacken, aber architektonisch ändert es nichts an der Performance. Du sendest immer noch jedes einzelne Mal den kompletten Query String über das Netzwerk an Cassandra. Cassandra muss immer noch den Text empfangen, die Syntax parsen und den Query Plan von Grund auf neu berechnen. Hier ist die entscheidende Erkenntnis: Du musst dieselbe Struktur nicht zweimal parsen. Hier kommt die session dot prepare Methode ins Spiel. Anstatt die Query sofort auszuführen, übergibst du deinen Query String an die prepare Methode. In diesem String ersetzt du die dynamischen Werte durch Fragezeichen. Der Driver sendet dieses Template an Cassandra. Cassandra parst es, validiert es, berechnet den effizientesten Execution Plan und generiert dann einen Unique Identifier für dieses spezifische Statement. Sie sendet diese ID zurück an deine Python-Anwendung. Von diesem Moment an sendet deine Anwendung keinen String mehr, wann immer du diese Query ausführen musst. Sie bindet deine spezifischen Variablen an das Prepared Statement Objekt und sendet nur die Unique ID zusammen mit den Raw Bytes der Werte. Denk an einen High-Traffic Authentication Service. Du musst beim Login einen User anhand seiner ID nachschlagen. Die Query ist select star from users where user id equals question mark. Wenn dein Service zehntausend Logins pro Sekunde verarbeitet, verschwendet das zehntausendfache Senden des kompletten Query Strings Netzwerk-Bandbreite und Datenbank-CPU. Indem du das Statement einmalig beim Start deiner Anwendung vorbereitest, reduzierst du den Network Payload signifikant. Cassandra sieht die ID, ruft sofort den vorberechneten Execution Plan ab und holt die Daten umgehend. Prepared Statements verlagern das Heavy Lifting des Query-Parsings von einer wiederkehrenden Per-Request-Steuer zu einem einmaligen Setup-Aufwand. Das war's für diese Folge. Bis zum nächsten Mal!
7

Paging von großen Abfragen

3m 37s

Bringen Sie Ihre App niemals zum Absturz, indem Sie einen riesigen Datensatz in den Arbeitsspeicher laden. Entdecken Sie, wie der Python Driver große Abfrageergebnisse automatisch paginiert und wie Sie Fetch Sizes verwalten.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 7 von 12. Du führst eine einfache Select Query auf einer riesigen Tabelle aus, und plötzlich stürzt deine Application mit einem Out-of-Memory Error ab. Zumindest würde das passieren, wenn dein Database Driver versuchen würde, alles auf einmal zu laden. Stattdessen kümmert sich der Driver elegant im Hintergrund darum. Heute geht es um das Paging großer Queries. Wenn du eine Query mit dem Cassandra Python Driver ausführst, versucht dieser nicht, Millionen von Rows in den Memory deiner Application zu laden. Standardmäßig paginiert der Driver die Results automatisch und lädt jeweils genau 5000 Rows auf einmal. Das zurückgegebene Result Set verhält sich wie ein Standard Python Iterator. Während du durch die Rows loopst, greift der Driver transparent auf die Datenbank zu, um den nächsten Batch zu fetchen, kurz bevor dir die Daten ausgehen. Dein Code sieht aus wie ein ganz normaler Loop, aber unter der Haube garantiert der Driver Memory Safety, indem er zu jedem Zeitpunkt immer nur eine einzige Page an Daten im Memory hält. Du bist nicht an den Default von 5000 Rows gebunden. Du kannst das steuern, indem du die Fetch Size Property deines Statement Objects setzt, bevor du es an die Execute Methode übergibst. Wenn du die Fetch Size auf 100 reduzierst, hält der Driver weniger Daten im Memory, macht dafür aber häufigere Network Round Trips zur Datenbank. Verwechsle diesen Mechanismus nicht mit traditioneller SQL Pagination über Limit und Offset Commands. SQL Offset Pagination zwingt die Datenbank, Rows zu scannen und zu verwerfen, bevor sie deine Daten zurückgibt. Das wird drastisch langsamer, je tiefer du pagest. Cassandra nutzt einen Cursor-basierten Ansatz. Der Driver verwendet einen internen Marker, um die genaue physische Location in der Datenbank zu tracken, an der der letzte Read beendet wurde. Automatisches Paging ist perfekt für Background Data Processing, funktioniert aber nicht, wenn du stateless Web Applications baust. Stell dir einen Web Endpoint vor, der eine kontinuierlich scrollende Liste mit Tausenden von Audit Logs an ein User Interface liefert. Du kannst nicht einfach eine Database Connection und einen aktiven Iterator auf deinem Server offen halten, während du darauf wartest, dass der User scrollt. Du brauchst einen Weg, die Query zu stoppen, den Request zu schließen und später fortzusetzen. Hier ist der entscheidende Punkt: Der Driver bietet eine Property auf dem Result Set, den sogenannten Paging State. Das ist ein opaque Byte String, der die genaue Cursor Position deiner Query repräsentiert. Um eine stateless API zu bauen, führst du eine Query aus, schnappst dir eine einzelne Page an Audit Logs und rufst diesen Paging State ab. Du konvertierst die Bytes in einen einfachen Hex String und sendest ihn zusammen mit den Daten an dein Frontend. Wenn der User ans Ende des Interfaces scrollt, sendet das Frontend genau diesen Hex String an deinen Server zurück. Dein Backend decodiert den String und übergibt ihn als Paging State Parameter an die Execute Methode. Cassandra setzt die Query sofort genau an der Stelle fort, an der sie aufgehört hat. Durch die Nutzung des Paging States kannst du die Memory Lifespan deiner Application von der massiven Größe deiner Database Tables entkoppeln. Das ermöglicht es dir, unendlich Daten an Clients zu streamen, während du nur eine strikt begrenzte Menge an Server RAM nutzt. Das war's für diese Folge. Danke fürs Zuhören und keep building!
8

Async-Abfragen mit hohem Durchsatz

4m 06s

Maximieren Sie den Durchsatz Ihrer Anwendung. Lernen Sie, wie Sie execute_async, ResponseFutures und Callbacks verwenden, um nebenläufige Anfragen an Cassandra zu stellen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 8 von 12. Auf eine Database Response zu warten, bevor du deinen nächsten Request sendest, ist der einfachste Weg, deine eigene Application zu drosseln. Wenn dein Python-Skript während Netzwerk-Roundtrips im Leerlauf ist, verschenkst du massive Write Performance. Um das zu beheben, brauchst du High Throughput Async Queries. Wenn du die Standard-execute-Methode einer Cassandra Session verwendest, blockiert dein Code. Er sendet die Query, wartet darauf, dass die Datenbank sie verarbeitet, und wartet dann darauf, dass das Netzwerk die Response zurückbringt. Für eine Data Ingestion Pipeline ist diese Idle Time fatal für deinen gesamten Throughput. Um echte Geschwindigkeit freizuschalten, bietet der DataStax Python Driver die execute async Methode. Zuerst müssen wir ein häufiges Missverständnis ausräumen. Wenn du das Wort async in Python hörst, denkst du wahrscheinlich an das Standard Library Modul asyncio und die async await Keywords. Darum geht es hier nicht. Der Cassandra Driver verlässt sich auf seine eigene, schlanke Event Loop, die in einem Background Thread läuft. Wenn du execute async aufrufst, nutzt du den Custom-Mechanismus des Drivers und nicht die eingebauten asynchronen Features von Python. Wenn du eine Query an execute async übergibst, wartet sie nicht auf eine Database Response. Sie gibt die Kontrolle sofort an dein Programm zurück. Was du zurückbekommst, ist ein Objekt namens ResponseFuture. Dieses Objekt ist ein Promise. Es repräsentiert eine Datenbankoperation, die an den Cluster gesendet, aber noch nicht abgeschlossen wurde. Da dein Main Thread nicht mehr wartet, brauchst du einen Weg, um zu wissen, wann die Query tatsächlich abgeschlossen ist oder ob sie fehlschlägt. Das erreichst du, indem du Callback-Funktionen direkt an das ResponseFuture anhängst. Zuerst definierst du eine Success-Funktion, die das Result Set als Argument nimmt. Dann definierst du eine Error-Funktion, die eine Exception als Argument nimmt. Schließlich verknüpfst du beide Funktionen über eine add callbacks Methode mit dem Future. Wenn die Datenbank antwortet, empfängt der Background Thread das Netzwerkpaket und triggert automatisch die richtige Funktion. Hier ist die wichtigste Erkenntnis. Dieser Mechanismus erlaubt es dir, Hunderte von Operationen gleichzeitig in einer Pipeline zu verarbeiten. Stell dir eine IoT Pipeline vor, die Hunderte von Temperaturmesswerten pro Sekunde empfängt. Mit der synchronen Methode verarbeitest du einen Messwert, wartest auf die Datenbank und verarbeitest dann den nächsten. Mit execute async loopst du ohne anzuhalten durch deine eingehenden Messwerte. Für jeden Messwert feuerst du eine Insert Query ab, schnappst dir das ResponseFuture, hängst deine Success und Error Callbacks an und gehst sofort zum nächsten Messwert über. Du pushst Hunderte von Requests in Sekundenbruchteilen ins Netzwerk. Der Driver multiplext diese Queries über deine bestehenden Datenbankverbindungen. Der Cassandra Cluster verarbeitet sie parallel und streamt die Results zurück. Deine Success und Error Callbacks feuern, sobald die Responses eintreffen, völlig unabhängig von der Reihenfolge, in der du sie gesendet hast. Dieser Ansatz erhöht deinen Throughput drastisch, da er die Netzwerkwartezeit für all diese Queries überlappt. Du bist nur durch deine Netzwerkbandbreite und die Datenbankkapazität begrenzt, anstatt durch Thread Blocking limitiert zu sein. Du musst zwar im Auge behalten, wie viele Requests du in flight hast, damit du die Driver Queue nicht überlastest, aber das Grundprinzip ist, die Network Pipeline voll zu halten. Das wichtigste Takeaway hier ist, dass es beim Database Throughput darum geht, Idle Time zu minimieren. Und indem du execute async mit angehängten Callbacks intensiv nutzt, zwingst du deine Application, ihre Zeit damit zu verbringen, Daten zu pushen, anstatt auf das Netzwerk zu warten. Wenn du das nützlich fandest und die Show unterstützen möchtest, kannst du auf Patreon nach DevStoriesEU suchen. Das war's für diese Folge. Danke fürs Zuhören und keep building!
9

Lightweight Transactions

3m 40s

Implementieren Sie Compare-and-Set-Operationen sicher. Erfahren Sie, wie Lightweight Transactions (LWTs) in Cassandra funktionieren und wie Sie die spezielle applied-Spalte in Ihren Python-Ergebnissen untersuchen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 9 von 12. In einem verteilten System ohne globale Locks versuchen zwei User, sich in genau derselben Millisekunde mit exakt demselben Usernamen zu registrieren. Wie stellst du sicher, dass nur einer von beiden ihn auch wirklich bekommt? Der Mechanismus, der das löst, heißt Lightweight Transaction. Bevor wir uns anschauen, wie du sie implementierst, müssen wir kurz den Namen klären. Eine Lightweight Transaction in Cassandra ist keine traditionelle Multi-Table ACID Transaction. Du kannst nicht einfach einen Transaction Block öffnen, in drei verschiedene Tabellen schreiben und einen Rollback machen, wenn ein Schritt fehlschlägt. Eine Lightweight Transaction ist strikt auf eine einzige Partition beschränkt. Es ist eine Conditional Operation, im Grunde ein verteiltes Compare and Set. Um dir einen eindeutigen Usernamen ohne Race Conditions zu sichern, schreibst du eine Standard Insert Query, aber hängst am Ende die spezifische Clause IF NOT EXISTS an. Cassandra prüft dann im Cluster, ob dieser Partition Key bereits existiert. Ist er nicht vorhanden, geht der Write durch. Für eine Update Operation nutzt du die IF Clause, gefolgt von einem Column-Namen und einem erwarteten Wert. Du kannst die Datenbank anweisen, einen Account Status nur dann upzudaten, wenn der aktuelle Status einem bestimmten String entspricht. Wenn du diese Queries aus Python heraus ausführst, musst du die Response anders handhaben als bei einem normalen Write. Ein Standard Write in Cassandra ist entweder stillschweigend erfolgreich oder wirft einen Timeout Error. Aber wenn du eine IF Clause anhängst, muss die Datenbank deiner Application mitteilen, ob die Condition tatsächlich erfüllt wurde. Der Python Driver löst das, indem er ein spezielles Result Set zurückgibt. Wenn du eine Lightweight Transaction ausführst, enthält die erste Row der zurückgegebenen Daten eine spezielle Boolean System Column. Der Driver stellt diese Column unter dem Namen applied in eckigen Klammern bereit. Du führst deine Insert Query aus und holst dir die erste Row aus dem Result. Dann wertest du diese Klammer applied Klammer Column aus. Wenn du dir vom Driver Dictionary Rows zurückgeben lässt, greifst du auf den Key als String zu. Wenn der Wert true ergibt, wurde die Condition erfüllt und dein neuer User hat sich den Usernamen erfolgreich gesichert. Die Operation ist abgeschlossen. Hier ist die entscheidende Erkenntnis. Du musst genau verstehen, was passiert, wenn diese Klammer applied Klammer Column false ergibt. Wenn der Insert fehlschlägt, weil der Username bereits vergeben ist, gibt Cassandra nicht einfach nur ein simples Rejection Flag zurück. Der Driver befüllt die Result Row mit den tatsächlichen Daten, die dafür gesorgt haben, dass deine Condition fehlgeschlagen ist. Weil deine Condition abgelehnt wurde, liest die Datenbank die existierende Row und gibt sie in exakt derselben Response an deine Python Application zurück. Du erhältst das false applied Flag und parallel dazu den aktuellen State des konfliktbehafteten Records. Wenn du versucht hast, eine Balance basierend auf einer erwarteten vorherigen Balance upzudaten, bekommst du sofort die tatsächliche aktuelle Balance zurück. Dein Python-Code weiß genau, welche Daten die Transaction blockiert haben. Das eliminiert komplett die Notwendigkeit, eine nachfolgende Select Query auszuführen, um herauszufinden, warum der Write rejected wurde. Lightweight Transactions geben dir strikte Concurrency Control auf Partition-Ebene, und der Python Driver macht das extrem effizient, indem er dir den Blocking State kostenlos mitliefert, wann immer eine Condition fehlschlägt. Danke fürs Zuhören. Macht's gut zusammen.
10

Die Object Mapper Modelle

4m 04s

Vermeiden Sie rohe CQL-Strings und modellieren Sie Ihre Daten mit Python-Klassen. Erfahren Sie, wie Sie cqlengine verwenden, um Tabellen zu definieren, Primary Keys festzulegen und Ihr Schema zu synchronisieren.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 10 von 12. Das Schreiben von rohen CQL-Strings direkt in deinem Python-Application-Code kann schnell zu einem unwartbaren Chaos werden. Am Ende hast du Multi-Line-Strings voller Variablen-Interpolation, was Tippfehler begünstigt und Schema-Refactoring schmerzhaft macht. Du brauchst einen Weg, deine Datenbanktabellen als native Python-Objekte darzustellen. Genau das bieten die Object Mapper Models. Der Datastax Python-Treiber enthält einen Object Mapper namens cqlengine. Damit kannst du Cassandra-Tabellen über Standard-Python-Klassen definieren. Wenn du schon mal Django ORM oder SQLAlchemy benutzt hast, wird dir die Syntax sehr vertraut vorkommen. Aber es gibt einen großen Unterschied, den wir gleich vorweg klären sollten. In diesen relationalen Mappern deklarierst du Foreign Keys, um Tabellen miteinander zu verknüpfen. Cassandra ist keine relationale Datenbank, daher existieren relationale Bindings hier einfach nicht. Ein Model in cqlengine mappt exakt auf eine eigenständige Cassandra-Tabelle. Bauen wir mal ein Comment-Model für eine Foto-App. Wir wollen alle Kommentare für ein bestimmtes Foto gruppieren und sie chronologisch sortieren. Zuerst erstellst du eine Python-Klasse namens Comment, die von der cqlengine Model-Basisklasse erbt. Innerhalb dieser Klasse definierst du deine Columns als Klassenattribute. Wir starten mit dem Attribut photo underscore id. Du weist es einem UUID-Column-Type zu und übergibst das Argument primary underscore key equals True. Weil das der allererste Primary Key ist, den du in der Klasse deklarierst, weist cqlengine ihn automatisch als Partition Key zu. Als Nächstes brauchen wir einen Weg, jeden Kommentar innerhalb dieser Foto-Partition eindeutig zu identifizieren und zu sortieren. Du definierst ein zweites Attribut namens comment underscore id. Du weist das einem TimeUUID-Column-Type zu und übergibst ebenfalls primary underscore key equals True. Hier wird es interessant. In cqlengine wird jeder Primary Key, der nach dem Partition Key definiert wird, automatisch zu einem Clustering Key. Du brauchst keinen speziellen Clustering-Konfigurationsblock. Die buchstäbliche Reihenfolge von oben nach unten, in der du die Column-Attribute in deiner Python-Klasse definierst, diktiert die Primary-Key-Struktur in Cassandra. Nachdem die Primary Keys gesetzt sind, fügst du die eigentlichen Data-Columns hinzu. Du definierst ein body-Attribut und weist ihm einen Text-Column-Type zu. Es sind einfach nur reguläre Daten, also werden keine Primary-Key-Argumente benötigt. Jetzt hast du eine deklarative Python-Klasse, die dein Tabellenschema beschreibt. Aber die Tabelle existiert noch nicht in deiner Datenbank. Um dieses Schema nach Cassandra zu pushen, benutzt du eine Funktion namens sync underscore table. Du übergibst deine Comment-Model-Klasse direkt in diese Funktion. Der Mapper liest deine Klassenstruktur, übersetzt sie in das korrekte rohe CQL-Statement und führt es aus. Wenn die Tabelle nicht existiert, erstellt sync underscore table sie. Wenn die Tabelle bereits existiert, prüft sie, ob du deiner Python-Klasse neue Columns hinzugefügt hast, und passt die Tabelle entsprechend an. Es ist wichtig zu wissen, dass sync underscore table niemals Daten droppt oder bestehende Primary Keys verändert, wodurch deine Kern-Datenstruktur bei Updates sicher bleibt. Die wahre Stärke, Models auf diese Weise zu definieren, liegt nicht nur darin, die Datenbank-Syntax zu verbergen, sondern deine Schema-Definition direkt im Application Layer zu verankern, wo die Business Logic lebt. Das war's für diese Folge. Danke fürs Zuhören und keep building!
11

Abfragen mit cqlengine erstellen

4m 21s

Rufen Sie Daten fließend ab und filtern Sie sie mithilfe von QuerySet-Objekten im cqlengine Object Mapper. Wir behandeln Filteroperatoren, Immutability und Einschränkungen bei der Sortierung.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 11 von 12. Das Filtern von Database Records mit einem Object Mapper fühlt sich normalerweise mühelos an und lässt dich nach jedem beliebigen Feld suchen. Aber wenn du in Cassandra versuchst, nach einer Column zu filtern, die nicht explizit indiziert oder Teil eines Primary Keys ist, wird die Datenbank sich schlichtweg weigern, deine Query auszuführen. Die Lösung liegt darin zu verstehen, wie man valide Requests baut, was uns zum Thema Making Queries mit cqlengine bringt. Wenn du in cqlengine Daten von einem Model abrufen willst, interagierst du mit einem QuerySet. Wenn du ein Model hast, das eine Datenbanktabelle repräsentiert, kannst du auf Records zugreifen, indem du das objects Attribut gefolgt von der all Methode aufrufst. Das gibt ein QuerySet zurück, das jede Row in dieser Tabelle repräsentiert. Jede Row abzurufen, ist in einer verteilten Datenbank selten das, was du willst, also brauchst du einen Weg, die Ergebnisse einzugrenzen. Um die zurückgegebenen Daten einzuschränken, benutzt du die filter Methode. Ein häufiger Verwirrungspunkt hierbei ist, wie dieses Filtern eigentlich passiert. Developer, die von anderen Frameworks kommen, nehmen manchmal an, dass der Object Mapper alle Daten in den Python Client zieht und die Liste in memory filtert. Das ist komplett falsch. Die filter Methode mappt direkt auf eine strikte CQL WHERE Clause. Das bedeutet, dass die Columns, die du an die filter Methode übergibst, den Cassandra Query Regeln entsprechen müssen. Du kannst nur nach Partition Keys, Clustering Columns oder Columns mit einem Secondary Index filtern. Wenn du versuchst, nach einem unindizierten Standard-Textfeld zu filtern, wird cqlengine den Error nicht verstecken oder lokal verarbeiten. Es wird die Query direkt an Cassandra weiterleiten, und Cassandra wird sie ablehnen. Schauen wir uns ein konkretes Szenario an. Du hast ein Automobile Model und willst alle Autos von Tesla finden, die nach dem Jahr 2012 hergestellt wurden. Du fängst an, indem du objects dot filter aufrufst. Du übergibst das manufacturer Keyword Argument, gesetzt auf den String Tesla. Um die year Condition zu handhaben, bietet cqlengine spezielle Filtering Operators. Du wendest diese an, indem du einen doppelten Unterstrich und eine Operator-Abkürzung direkt an den Column-Namen anhängst. Für strikt größer als benutzt du doppelter Unterstrich g t. Also fügst du deinem filter Call ein zweites Keyword Argument hinzu: year doppelter Unterstrich g t gleich 2012. Der Mapper übersetzt das reibungslos in eine valide CQL Query. Es gibt noch einige andere Operators für verschiedene Conditions. Wenn du nach bestimmten Automodellen statt nach einem Jahr suchen wolltest, könntest du den doppelter Unterstrich in Operator benutzen. Du würdest model doppelter Unterstrich in übergeben, gesetzt auf eine Python List, die die Namen Model S und Model 3 enthält. Die Datenbank wird Records zurückgeben, die mit einem beliebigen Wert in dieser List matchen. Hier ist die wichtigste Erkenntnis. QuerySets sind komplett immutable. Wenn du die filter Methode auf einem existierenden QuerySet aufrufst, modifiziert es dieses Object nicht in place. Stattdessen gibt es ein brandneues QuerySet mit den zusätzlich angewendeten Filtern zurück. Du kannst ein Base QuerySet erstellen, das nur nach dem manufacturer Tesla filtert, und es einer Variable zuweisen. Dann kannst du diese einzelne Variable nutzen, um mehrere verschiedene gefilterte QuerySets für verschiedene Jahre oder Modelle zu generieren, indem du einfach wieder filter auf der Base Variable aufrufst. Die ursprüngliche Base Query bleibt komplett unverändert. Weil QuerySets immutable sind, kannst du programmatisch hochspezifische, komplexe Queries Schritt für Schritt konstruieren und Base Conditions sicher in deiner gesamten Application wiederverwenden, bevor jemals ein Network Call gemacht wird. Danke fürs Dabeisein. Ich hoffe, du hast etwas Neues gelernt.
12

Vector Search für KI

4m 10s

Machen Sie Ihre Fähigkeiten mit der Vector Search von Cassandra 5.0 zukunftssicher. Entdecken Sie, wie Sie hochdimensionale Vektoren speichern und abfragen können, um moderne KI- und Machine-Learning-Anwendungen anzutreiben.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Apache Cassandra mit Python, Folge 12 von 12. Large Language Models verändern, wie wir Anwendungen bauen, aber sie bringen eine große Storage-Herausforderung mit sich. Wenn ein AI-Modell Kontext braucht, scheitern traditionelle Datenbank-Queries, weil sie nach exakten Character-Matches suchen und die eigentliche Intention hinter einem Prompt völlig verfehlen. Moderne AI-Workloads erfordern eine grundlegend andere Art, Daten abzufragen. Hier kommt Vector Search ins Spiel, die in Cassandra 5.0 nativ eingeführt wurde. Man verwechselt Vector Search leicht mit einer einfachen lexikalischen Full-Text Search. Ein Standard-Full-Text-Index wie Lucene ist strikt Keyword-basiert. Wenn ein User in deiner Datenbank nach dem Begriff Database Backup sucht, scannt eine lexikalische Suche nach genau diesen Strings. Vector Search funktioniert anders. Statt wörtlicher Keywords erfassen Vektoren die zugrundeliegende semantische Bedeutung der Daten. Eine Vector Search versteht, dass das Speichern eines Daten-Snapshots oder das Archivieren von Tabellen genau demselben Konzept entsprechen wie ein Database Backup, selbst wenn die Wörter keinen einzigen gemeinsamen Buchstaben haben. Damit das funktioniert, setzt Cassandra auf Vector Embeddings. Ein Embedding ist ein Array von Floating-Point Numbers, das von einem Machine-Learning-Modell generiert wird. Diese Arrays fungieren als mathematische Koordinaten, die die tiefere Bedeutung deines Textes repräsentieren. Du speicherst diese Arrays direkt in Cassandra, zusammen mit deinen normalen Application-Daten. Wenn du relevante Inhalte in riesigen Dokumentensammlungen finden musst, führst du eine Vector Search durch. Die Datenbank vergleicht den Vektor der eingehenden Query mit den Vektoren, die in deinen Tabellen gespeichert sind. Sie berechnet die mathematische Distanz zwischen ihnen. Kürzere Distanzen bedeuten eine stärkere semantische Ähnlichkeit. Stell dir vor, du baust einen internen Chatbot für ein großes Engineering-Team. Du hast tausende Seiten technischer Dokumentation. Ein Engineer tippt eine Frage dazu ein, wie man einen Staging-Cluster decommissioned. Zuerst übergibt deine Application diese Frage an ein Embedding-Modell, das den Satz in ein Array von Floats übersetzt. Als Nächstes sendest du dieses numerische Array als Vector Search Query an Cassandra. Cassandra scannt sofort den mehrdimensionalen Raum und ruft die internen Dokumente ab, deren Embeddings der Frage am nächsten liegen. Sie liefert das richtige Handbuch für das Retiring von Testing Environments zurück, weil die semantische Bedeutung perfekt übereinstimmt, unabhängig von der unterschiedlichen Terminologie. Dieses Feature wurde explizit für AI-Applications gebaut. Die meisten dieser Applications sind darauf angewiesen, hochrelevanten Kontext abzurufen, um ihn in das Language Model einzuspeisen, bevor es eine Response generiert. Indem Vector Search direkt in Cassandra 5.0 integriert wurde, entfällt die Notwendigkeit, eine separate, eigenständige Vector Database zu betreiben. Du behältst deine primären operativen Records und ihre semantischen Embeddings in exakt derselben verteilten Architektur und verlässt dich auf die High Availability und das Scaling, das Cassandra bietet. Da dies unsere Serie zu Apache Cassandra abschließt, ermutige ich dich, die offizielle Dokumentation zu erkunden und hands-on auszuprobieren, Embeddings für deine eigenen Daten zu generieren. Wenn du Vorschläge hast, welche Technologien wir als Nächstes behandeln sollen, besuche devstories dot eu und lass es uns wissen. Vector Search schließt die Lücke zwischen Sprache und Storage und verwandelt komplexe menschliche Intentionen in ein Geometrie-Problem, das Cassandra at scale lösen kann. Das war's für diese Folge. Danke fürs Zuhören und keep building!