Mehr denn je zielen neue Produkte darauf ab, auf globaler Ebene Wirkung zu erzielen, und das Benutzererlebnis entwickelt sich rasant zum entscheidenden Faktor für ihren Erfolg. Diese Eigenschaften Ihrer Anwendung können das Benutzererlebnis maßgeblich beeinflussen
- Performance & geringe Latenz
- Die Anwendung tut, was Sie erwarten
- Sicherheit
- Funktionen und Benutzeroberfläche
Beginnen wir unsere Suche nach dem perfekten Benutzererlebnis!
1) Performance & geringe Latenz
Andere haben es bereits gesagt: Performance ist User Experience ( 1, 2 ). Wenn Sie die Aufmerksamkeit potenzieller Besucher gewonnen haben, kann eine geringe Erhöhung der Latenz dazu führen, dass Sie diese Aufmerksamkeit wieder verlieren.
2) Die Anwendung tut, was Sie erwarten
Was bedeutet "tut, was Sie erwarten" überhaupt? Es bedeutet, dass wenn ich meinen Namen in meiner Anwendung in "Robert" ändere und die Anwendung neu lade, mein Name Robert und nicht Brecht sein wird. Es scheint wichtig zu sein, dass eine Anwendung diese Garantien liefert, oder?
Ob die Anwendung diese Garantien liefern kann, hängt von der Datenbank ab. Bei der Verfolgung von geringer Latenz und hoher Performance geraten wir in den Bereich verteilter Datenbanken, in denen nur wenige der neueren Datenbanken diese Garantien liefern. Im Bereich verteilter Datenbanken kann es Drachen geben, es sei denn, wir wählen eine stark (vs. schließlich) konsistente Datenbank. In dieser Serie werden wir detailliert darauf eingehen, was das bedeutet, welche Datenbanken diese Funktion namens starke Konsistenz bieten und wie sie Ihnen helfen können, fantastisch schnelle Apps mit minimalem Aufwand zu erstellen.
3) Sicherheit
Sicherheit scheint auf den ersten Blick nicht immer das Benutzererlebnis zu beeinträchtigen. Sobald die Benutzer jedoch Sicherheitslücken bemerken, können Beziehungen irreparabel beschädigt werden.
4) Funktionen und Benutzeroberfläche
Beeindruckende Funktionen und eine großartige Benutzeroberfläche haben einen großen Einfluss auf das bewusste und unbewusste Denken. Oftmals wünschen sich Menschen ein bestimmtes Produkt erst, nachdem sie erlebt haben, wie es aussieht und sich anfühlt.
Wenn eine Datenbank Zeit bei Einrichtung und Konfiguration spart, können sich unsere übrigen Bemühungen auf die Bereitstellung beeindruckender Funktionen und eine großartige Benutzeroberfläche konzentrieren. Gute Nachrichten für Sie: Heutzutage gibt es Datenbanken, die all das oben Genannte liefern, keine Konfiguration oder Serverbereitstellung erfordern und einfach zu bedienende APIs wie GraphQL aus der Box bieten.
Was ist so anders an dieser neuen Art von Datenbanken? Treten wir einen Schritt zurück und zeigen, wie die ständige Suche nach geringerer Latenz und besserer UX in Kombination mit Fortschritten in der Datenbankforschung schließlich zu einer neuen Art von Datenbanken geführt hat, die die idealen Bausteine für moderne Anwendungen sind.
Die Suche nach Verteilung
I. Content Delivery Networks
Wie bereits erwähnt, hat Performance einen erheblichen Einfluss auf die UX. Es gibt mehrere Möglichkeiten, die Latenz zu verbessern, und die offensichtlichste ist die Optimierung Ihres Anwendungscodes. Sobald Ihr Anwendungscode ziemlich optimal ist, bleiben Netzwerk-Latenz und Lese-/Schreib-Performance der Datenbank oft die Flaschenhälse. Um unsere Anforderung an geringe Latenz zu erfüllen, müssen wir sicherstellen, dass unsere Daten so nah wie möglich am Client sind, indem wir die Daten global verteilen. Die zweite Anforderung (Schreib-/Lese-Performance) können wir erfüllen, indem wir mehrere Maschinen zusammenarbeiten lassen, oder anders ausgedrückt, indem wir Daten replizieren.
Verteilung führt zu besserer Performance und damit zu guter Benutzererfahrung. Wir haben bereits gesehen, dass die Jamstack-Community eine Verbreitungslösung zur Beschleunigung der Bereitstellung statischer Daten intensiv nutzt: das Content Delivery Network (CDN). CDNs werden von der Jamstack-Community hoch geschätzt, um die Latenz ihrer Anwendungen zu reduzieren. Sie verwenden typischerweise Frameworks und Tools wie Next.js/Now, Gatsby und Netlify, um Frontend-Code für React/Angular/Vue in statische Websites zu kompilieren, damit sie diese von einem CDN ausliefern können.

Leider sind CDNs nicht für jeden Anwendungsfall ausreichend, da wir uns nicht für alle Anwendungen auf statisch generierte HTML-Seiten verlassen können. Es gibt viele Arten von hochdynamischen Anwendungen, bei denen Sie nicht alles statisch generieren können. Zum Beispiel:
- Anwendungen, die Echtzeit-Updates für sofortige Kommunikation zwischen Benutzern erfordern (z. B. Chat-Anwendungen, kollaboratives Zeichnen oder Schreiben, Spiele).
- Anwendungen, die Daten in vielen verschiedenen Formen präsentieren, indem sie Daten filtern, aggregieren, sortieren und anderweitig so manipulieren, dass Sie nicht alles im Voraus generieren können.
II. Verteilte Datenbanken
Im Allgemeinen erfordert eine hochdynamische Anwendung eine verteilte Datenbank zur Leistungssteigerung. Ähnlich wie ein CDN strebt eine verteilte Datenbank danach, ein globales Netzwerk statt eines einzelnen Knotens zu werden. Im Wesentlichen wollen wir von einem Szenario mit einem einzelnen Datenbankknoten ...

... zu einem Szenario wechseln, in dem die Datenbank zu einem Netzwerk wird. Wenn sich ein Benutzer von einem bestimmten Kontinent aus verbindet, wird er automatisch zum nächstgelegenen Datenbankknoten weitergeleitet. Dies führt zu geringerer Latenz und zufriedeneren Endbenutzern.

Wenn Datenbanken Mitarbeiter wären, die am Telefon warten, würde Ihnen der Datenbankmitarbeiter mitteilen, dass ein Mitarbeiter in der Nähe ist und den Anruf weiterleiten. Glücklicherweise leiten verteilte Datenbanken uns automatisch zum nächstgelegenen Datenbankmitarbeiter weiter, sodass wir uns nie um den Datenbankmitarbeiter auf dem anderen Kontinent kümmern müssen.

Verteilte Datenbanken sind multiregional, und Sie werden immer zum nächstgelegenen Knoten weitergeleitet.
Neben der Latenz bieten verteilte Datenbanken noch einen zweiten und dritten Vorteil. Der zweite ist die Redundanz, was bedeutet, dass selbst wenn einer der Datenbankstandorte im Netzwerk durch einen Godzilla-Angriff vollständig zerstört würde, Ihre Daten nicht verloren gehen, da andere Knoten noch Duplikate Ihrer Daten haben.


Last but not least ist der dritte Vorteil der Verwendung einer verteilten Datenbank die Skalierbarkeit. Eine Datenbank, die auf einem Server läuft, kann schnell zum Flaschenhals Ihrer Anwendung werden. Im Gegensatz dazu replizieren verteilte Datenbanken Daten auf mehreren Servern und können sich je nach Bedarf der Anwendungen automatisch hoch- und runterskalieren. Bei einigen fortschrittlichen verteilten Datenbanken wird dieser Aspekt vollständig für Sie übernommen. Diese Datenbanken werden als "serverlos" bezeichnet, was bedeutet, dass Sie nicht einmal konfigurieren müssen, wann die Datenbank hoch- und runterskaliert werden soll, und Sie zahlen nur für die Nutzung Ihrer Anwendung, nichts mehr.
Die Verteilung dynamischer Daten führt uns in den Bereich verteilter Datenbanken. Wie bereits erwähnt, kann es dort Drachen geben. Im Gegensatz zu CDNs sind die Daten hochdynamisch; die Daten können sich schnell ändern und gefiltert und sortiert werden, was zusätzliche Komplexität mit sich bringt. Die Datenbankwelt untersuchte verschiedene Ansätze, um dies zu erreichen. Frühe Ansätze mussten Kompromisse eingehen, um die gewünschte Leistung und Skalierbarkeit zu erzielen. Sehen wir, wie sich die Suche nach Verteilung entwickelt hat.

Der Ansatz traditioneller Datenbanken zur Verteilung
Eine logische Wahl war es, auf traditionellen Datenbanken (MySQL, PostgreSQL, SQL Server) aufzubauen, da bereits so viel Aufwand in sie investiert wurde. Traditionelle Datenbanken wurden jedoch nicht für die Verteilung entwickelt und wählten daher einen eher einfachen Ansatz für die Verteilung. Der typische Ansatz zur Skalierung von Lesevorgängen war die Verwendung von Read-Replicas. Ein Read-Replica ist nur eine Kopie Ihrer Daten, von der Sie lesen, aber nicht schreiben können. Eine solche Kopie (oder ein Replikat) entlastet den Knoten, der die Originaldaten enthält, von Abfragen. Dieser Mechanismus ist sehr einfach, da die Daten inkrementell zu den Replikaten kopiert werden, sobald sie eintreffen.
Aufgrund dieses relativ einfachen Ansatzes sind die Daten eines Replikats immer älter als die Originaldaten. Wenn Sie die Daten zu einem bestimmten Zeitpunkt von einem Replikationsknoten lesen, erhalten Sie möglicherweise einen älteren Wert als beim Lesen vom primären Knoten. Dies wird als "stale read" bezeichnet. Programmierer, die traditionelle Datenbanken verwenden, müssen sich dieser Möglichkeit bewusst sein und mit dieser Einschränkung im Hinterkopf programmieren. Denken Sie an das Beispiel, das wir eingangs gegeben haben, wo wir einen Wert schreiben und ihn erneut lesen? Bei der Arbeit mit traditionellen Datenbankreplikaten können Sie nicht erwarten, das zu lesen, was Sie schreiben.
Sie könnten das Benutzererlebnis leicht verbessern, indem Sie die Ergebnisse von Schreibvorgängen optimistisch im Frontend anwenden, bevor alle Replikate über die Schreibvorgänge informiert sind. Ein Neuladen der Webseite könnte jedoch die Benutzeroberfläche in einen früheren Zustand zurückversetzen, wenn die Aktualisierung das Replikat noch nicht erreicht hat. Der Benutzer würde dann denken, dass seine Änderungen nie gespeichert wurden.

Die erste Generation verteilter Datenbanken
Beim Replikationsansatz traditioneller Datenbanken ist der offensichtliche Flaschenhals, dass alle Schreibvorgänge an denselben Knoten gehen. Die Maschine kann skaliert werden, stößt aber zwangsläufig an eine Grenze. Wenn Ihre App an Popularität gewinnt und die Schreibvorgänge zunehmen, ist die Datenbank nicht mehr schnell genug, um neue Daten zu akzeptieren. Um horizontal für Lese- und Schreibvorgänge zu skalieren, wurden verteilte Datenbanken erfunden. Eine verteilte Datenbank enthält ebenfalls mehrere Kopien der Daten, aber Sie können jede dieser Kopien beschreiben. Da Sie Daten über jeden Knoten aktualisieren, müssen alle Knoten miteinander kommunizieren und andere über neue Daten informieren. Mit anderen Worten, es ist keine Einbahnstraße mehr wie im traditionellen System.

Diese Art von Datenbanken kann jedoch immer noch von den oben erwähnten "stale reads" betroffen sein und viele andere potenzielle Probleme im Zusammenhang mit Schreibvorgängen einführen. Ob sie von diesen Problemen betroffen sind, hängt von ihrer Entscheidung bezüglich Verfügbarkeit und Konsistenz ab.
Diese erste Generation verteilter Datenbanken wurde oft als "NoSQL-Bewegung" bezeichnet, ein Name, der von Datenbanken wie MongoDB und Neo4j beeinflusst wurde, die ebenfalls alternative Sprachen zu SQL und verschiedene Modellierungsstrategien (Dokumente oder Graphen anstelle von Tabellen) boten. NoSQL-Datenbanken fehlten oft typische traditionelle Datenbankfunktionen wie Constraints und Joins. Im Laufe der Zeit erwies sich dieser Name als schrecklicher Name, da viele Datenbanken, die als NoSQL galten, eine Form von SQL anboten. Es entstanden mehrere Interpretationen, die besagten, dass NoSQL-Datenbanken
- bieten keine SQL als Abfragesprache an.
- bieten nicht nur SQL an (NoSQL = Not Only SQL)
- bieten keine typischen traditionellen Funktionen wie Joins, Constraints, ACID-Garantien an.
- modellieren ihre Daten anders (Graph-, Dokumenten- oder temporales Modell)
Einige der neueren Datenbanken, die nicht relational waren, aber SQL anboten, wurden dann als "NewSQL" bezeichnet, um Verwechslungen zu vermeiden.
Falsche Interpretationen des CAP-Theorems
Die erste Generation von Datenbanken wurde stark vom CAP-Theorem inspiriert, das besagt, dass Sie bei einer Netzwerkpartition nicht sowohl Konsistenz als auch Verfügbarkeit haben können. Eine Netzwerkpartition ist im Wesentlichen, wenn etwas passiert, so dass zwei Knoten nicht mehr über neue Daten miteinander sprechen können, und kann aus vielen Gründen entstehen (z. B. manchmal knabbern Haie an Googles Kabeln). Konsistenz bedeutet, dass die Daten in Ihrer Datenbank immer korrekt sind, aber nicht unbedingt für Ihre Anwendung verfügbar sind. Verfügbarkeit bedeutet, dass Ihre Datenbank immer online ist und Ihre Anwendung immer auf diese Daten zugreifen kann, aber nicht garantiert, dass die Daten korrekt oder auf mehreren Knoten gleich sind. Wir sprechen im Allgemeinen von hoher Verfügbarkeit, da es keine 100%ige Verfügbarkeit gibt. Availability wird in Ziffern von 9 (z. B. 99,9999% Verfügbarkeit) angegeben, da es immer möglich ist, dass eine Reihe von Ereignissen zu Ausfallzeiten führt.

Aber was passiert, wenn es keine Netzwerkpartition gibt? Datenbankanbieter haben das CAP-Theorem etwas zu allgemein interpretiert und sich entweder für potenzielle Datenverluste oder für Verfügbarkeit entschieden, ob eine Netzwerkpartition vorliegt oder nicht. Während das CAP-Theorem ein guter Anfang war, betonte es nicht, dass es möglich ist, hoch verfügbar und konsistent zu sein, wenn keine Netzwerkpartition vorliegt. Meistens gibt es keine Netzwerkpartitionen, daher war es sinnvoll, diesen Fall zu beschreiben, indem das CAP-Theorem in das PACELC-Theorem erweitert wurde. Der Hauptunterschied sind die drei letzten Buchstaben (ELC), die für Else Latency Consistency stehen. Dieses Theorem besagt, dass die Datenbank bei fehlender Netzwerkpartition Latenz und Konsistenz ausbalancieren muss.

Einfach ausgedrückt: Wenn keine Netzwerkpartition vorliegt, steigt die Latenz, wenn die Konsistenzgarantien steigen. Wir werden jedoch sehen, dass die Realität noch subtiler ist als dies.
Wie hängt das mit dem Benutzererlebnis zusammen?
Betrachten wir ein Beispiel dafür, wie der Verzicht auf Konsistenz das Benutzererlebnis beeinträchtigen kann. Stellen Sie sich eine Anwendung vor, die Ihnen eine benutzerfreundliche Oberfläche zum Zusammenstellen von Teams bietet. Sie ziehen Personen per Drag-and-Drop in verschiedene Teams.

Sobald Sie eine Person in ein Team ziehen, wird eine Aktualisierung ausgelöst, um dieses Team zu aktualisieren. Wenn die Datenbank nicht garantiert, dass Ihre Anwendung das Ergebnis dieser Aktualisierung sofort lesen kann, muss die Benutzeroberfläche diese Änderungen optimistisch anwenden. In diesem Fall können schlimme Dinge passieren:
- Der Benutzer aktualisiert die Seite und sieht seine Aktualisierung nicht mehr und denkt, dass seine Aktualisierung verloren gegangen ist. Wenn er erneut aktualisiert, ist sie plötzlich wieder da.
- Die Datenbank hat die Aktualisierung aufgrund eines Konflikts mit einer anderen Aktualisierung nicht erfolgreich gespeichert. In diesem Fall kann die Aktualisierung abgebrochen werden und der Benutzer erfährt es nie. Möglicherweise bemerkt er erst, dass seine Änderungen verschwunden sind, wenn er das nächste Mal neu lädt.
Dieser Kompromiss zwischen Konsistenz und Latenz hat zu vielen hitzigen Diskussionen zwischen Frontend- und Backend-Entwicklern geführt. Die erste Gruppe wünschte sich eine großartige UX, bei der Benutzer Feedback erhalten, wenn sie Aktionen ausführen, und 100% sicher sein können, dass die Ergebnisse ihrer Aktionen konsistent gespeichert werden, sobald sie dieses Feedback erhalten und darauf reagieren. Die zweite Gruppe wollte ein skalierbares und performantes Backend aufbauen und sah keinen anderen Weg, als die oben genannten UX-Anforderungen zu opfern, um dies zu erreichen.
Beide Gruppen hatten berechtigte Punkte, aber es gab keine Allzwecklösung, um beide zufrieden zu stellen. Als die Transaktionen zunahmen und die Datenbank zum Flaschenhals wurde, war ihre einzige Option, entweder auf traditionelle Datenbankreplikation oder auf eine verteilte Datenbank zurückzugreifen, die starke Konsistenz gegen etwas namens "eventual consistency" opferte. Bei "eventual consistency" wird eine Aktualisierung der Datenbank irgendwann auf allen Maschinen angewendet, aber es gibt keine Garantie, dass die nächste Transaktion den aktualisierten Wert lesen kann. Anders ausgedrückt: Wenn ich meinen Namen in "Robert" ändere, gibt es keine Garantie, dass ich tatsächlich "Robert" erhalte, wenn ich meinen Namen unmittelbar nach der Aktualisierung abfrage.
Konsistenzsteuer
Um mit "eventual consistency" umzugehen, müssen Entwickler sich der Einschränkungen einer solchen Datenbank bewusst sein und viel zusätzliche Arbeit leisten. Programmierer greifen oft zu User-Experience-Hacks, um die Datenbankbeschränkungen zu verbergen, und Backends müssen viele zusätzliche Code-Layer schreiben, um verschiedene Fehlerszenarien zu bewältigen. Das Finden und Erstellen kreativer Lösungen für diese Einschränkungen hat die Art und Weise, wie sowohl Frontend- als auch Backend-Entwickler ihre Arbeit gemacht haben, tiefgreifend beeinflusst, die technische Komplexität erheblich erhöht und trotzdem keine ideale Benutzererfahrung geboten.
Wir können diese zusätzliche Arbeit, die erforderlich ist, um die Datenkorrektheit sicherzustellen, als "Steuer" betrachten, die ein Anwendungsentwickler zahlen muss, um gute Benutzererlebnisse zu liefern. Das ist die Steuer der Nutzung eines Softwaresystems, das keine Konsistenzgarantien bietet, die in heutigen Web-Scale-Umgebungen mit gleichzeitiger Nutzung bestehen. Wir nennen das die Konsistenzsteuer.
Glücklicherweise hat sich eine neue Generation von Datenbanken entwickelt, die Sie nicht zwingen, die Konsistenzsteuer zu zahlen, und die ohne Einbußen bei der Konsistenz skalieren können!
Die zweite Generation verteilter Datenbanken
Eine zweite Generation verteilter Datenbanken ist entstanden, um starke (statt eventual) Konsistenz zu bieten. Diese Datenbanken skalieren gut, verlieren keine Daten und geben keine veralteten Daten zurück. Mit anderen Worten, sie tun, was Sie erwarten, und es ist nicht mehr erforderlich, sich mit den Einschränkungen auseinanderzusetzen oder die Konsistenzsteuer zu zahlen. Wenn Sie einen Wert aktualisieren, spiegelt die nächste Lektüre dieses Werts immer den aktualisierten Wert wider, und verschiedene Aktualisierungen werden in derselben zeitlichen Reihenfolge angewendet, wie sie geschrieben wurden. FaunaDB, Spanner und FoundationDB sind zum Zeitpunkt der Erstellung die einzigen Datenbanken, die starke Konsistenz ohne Einschränkungen (auch Strict serializability genannt) bieten.
Das PACELC-Theorem revisited

Die zweite Generation verteilter Datenbanken hat etwas erreicht, das zuvor als unmöglich galt; sie bevorzugen Konsistenz und liefern dennoch geringe Latenzzeiten. Dies wurde durch intelligente Synchronisationsmechanismen wie Calvin, Spanner und Percolator ermöglicht, die wir im vierten Artikel dieser Serie ausführlich besprechen werden. Während ältere Datenbanken immer noch Schwierigkeiten haben, hohe Konsistenzgarantien bei geringeren Latenzzeiten zu liefern, leiden Datenbanken, die auf diesen neuen intelligenten Algorithmen basieren, nicht unter solchen Einschränkungen.
Datenbankdesigns beeinflussen die erreichbare Latenz bei hoher Konsistenz erheblich.
Da diese neuen Algorithmen es Datenbanken ermöglichen, sowohl starke Konsistenz als auch geringe Latenzzeiten zu bieten, gibt es normalerweise keinen guten Grund, auf Konsistenz zu verzichten (zumindest nicht in Abwesenheit einer Netzwerkpartition). Der einzige Zeitpunkt, an dem Sie dies tun würden, ist, wenn extrem geringe Schreiblatenz das Einzige ist, was wirklich zählt, und Sie bereit sind, Daten zu verlieren, um dies zu erreichen.

Sind diese Datenbanken immer noch NoSQL?
Es ist nicht mehr trivial, diese neue Generation verteilter Datenbanken zu kategorisieren. Es werden immer noch viele Anstrengungen unternommen (1, 2), um zu erklären, was NoSQL bedeutet, aber keine davon macht mehr wirklich Sinn, da sich NoSQL- und SQL-Datenbanken aufeinander zubewegen. Neue verteilte Datenbanken leihen sich von verschiedenen Datenmodellen (Dokument, Graph, Relational, Temporal), und einige von ihnen bieten ACID-Garantien oder unterstützen sogar SQL. Sie haben immer noch eines mit NoSQL gemeinsam: Sie sind darauf ausgelegt, die Einschränkungen traditioneller Datenbanken zu lösen. Ein Wort wird nie ausreichen, um zu beschreiben, wie eine Datenbank funktioniert. In Zukunft wird es sinnvoller sein, verteilte Datenbanken zu beschreiben, indem diese Fragen beantwortet werden:
- Ist sie stark konsistent?
- Basiert die Verteilung auf Read-Replicas oder ist sie wirklich verteilt?
- Von welchen Datenmodellen leiht sie sich Elemente?
- Wie ausdrucksstark ist die Abfragesprache und was sind ihre Einschränkungen?
Fazit
Wir haben erklärt, wie Anwendungen jetzt von einer neuen Generation global verteilter Datenbanken profitieren können, die dynamische Daten vom nächstgelegenen Standort im CDN-ähnlichen Stil bereitstellen können. Wir haben kurz die Geschichte verteilter Datenbanken durchlaufen und gesehen, dass es kein reibungsloser Weg war. Viele Datenbanken der ersten Generation wurden entwickelt, und ihre Konsistenzentscheidungen – die hauptsächlich vom CAP-Theorem angetrieben wurden – erforderten, dass wir mehr Code schreiben mussten, während die Benutzererfahrung dennoch beeinträchtigt wurde. Erst kürzlich hat die Datenbank-Community Algorithmen entwickelt, die es verteilten Datenbanken ermöglichen, geringe Latenzzeiten mit starker Konsistenz zu kombinieren. Eine neue Ära bricht an, eine Zeit, in der wir keine Kompromisse mehr zwischen Datenzugriff und Konsistenz eingehen müssen!
An dieser Stelle möchten Sie wahrscheinlich konkrete Beispiele für die potenziellen Fallstricke von Datenbanken mit "eventual consistency" sehen. Im nächsten Artikel dieser Serie werden wir genau das behandeln. Bleiben Sie dran für diese kommenden Artikel
Sehr aufschlussreich! Ich kann es kaum erwarten, den Rest der Artikel zu lesen!
Hey Gust, danke für das Feedback! Wir freuen uns, dass es Ihnen gefällt.
Die Beiträge werden wöchentlich veröffentlicht, daher sollte der nächste am 12. März eintreffen.
Wenn Sie Feedback oder Gedanken haben, lassen Sie es uns auf Twitter (tag @fauna) / Slack (http://community.fauna.com/) wissen.