Donnerstag, 16. November 2017

Was bedeutet Big Data für die Software-Entwicklung?

In diesem Post möchte ich eine Definition von Big Data jenseits der üblichen V4-Definitionen versuchen und insbesondere auf die wichtigsten Herausforderungen aus Sicht der Software-Entwicklung eingehen.

Der Vollständigkeit halber, Big Data wird häufig über die folgenden Begriffe definiert:
  • Volume: die "übliche" Datenmenge wird heutzutage ungefähr im Terabyte-Bereich angesiedelt; nicht zu vergessen ist sicher auch eine große Menge von Benutzern, die bei der Systementwicklung zu ähnlichen Herausforderungen führen kann, wie eine große Datenmenge
  • Velocity: die anfallenden Daten müssen ausreichend schnell verarbeitet werden können, oftmals als Streams in quasi Echtzeit, weil sie nicht komplett gespeichert, geschweige denn sinnvoll wieder abgerufen werden können
  • Variety: vielfach fallen Daten aus unterschiedlichen Quellen an, die ggf. auch unterschiedlich gespeichert werden müssen
  • Veracity: in vielen Fällen (z.B. bei der Verarbeitung von Sensordaten o.ä.) kann nicht garantiert werden, dass diese Daten vollständig und korrekt sind
Aus betriebswirtschaftlicher Sicht kommt noch Value als fünftes V hinzu, schließlich möchte niemand Daten um ihrer Anmut Willen sammeln, sondern es sollte sich aus ihrer Analyse ein Wert für die Unternehmung generieren lassen. Die ziellose Installation eines Hadoop-Clusters, wie es zumindest in den Anfangsjahren des Big-Data-Hypes häufig in der Industrie zu beobachten war, dient diesem Ziel übrigens nicht.

Eine aus Entwicklersicht pragmatischere Definition für Big Data lautet, dass es sich um Datenmengen handelt, die nicht mehr auf einem Rechner gespeichert oder verarbeitet werden können. Dabei spielt  es zunächst einmal keine Rolle, ob es sich um einen handelsüblichen Laptop, einen ausgewachsenen Server oder einen Minicomputer wie einen Rapsberry Pi handelt. Sobald eine Parallelverarbeitung von Daten auf mehreren Rechnern notwendig ist, ändern sich die Spielregeln bzgl. der Verarbeitung und es tauchen neue Herausforderungen auf. Aus meiner Erfahrung bei der Entwicklung eines großen Informationssystems heraus insbesondere die vier im Folgenden beschriebenen:
  1. Zunächst ist natürlich die nachhaltige Skalierbarkeit eines Systems eine zentrale Schwierigkeit. Große Datenmengen haben nämlich oft die unangenehme Eigenschaft beständig weiter zu wachsen. Dieser Herausforderung versuchen wir über ein Skalieren unserer Hardware zu begegnen. Die traditionelle Skalierung über leistungsfähigere Prozessoren (sog. vertikale Skalierung) ist mit der Stagnation der Taktraten ins Stocken geraten. Heute üblich ist meist die sogenannte horizontale Skalierung, also das Hinzunehmen weiterer Rechner und damit die Verteilung der Aufgabenlast auf weitere "Schultern". Grundvoraussetzung, damit dies dauerhaft sinnvoll funktionieren kann, ist eine maximal lineare Komplexität (d.h. eine Komplexität kleiner oder gleich O(n)) der im System ausgeführten Algorithmen. Weißt ein Algorithmus eine höhere Komplexität auf, also beispielsweise O(n log n) oder gar O(n2), benötigen wir bei einer Verdopplung der zu verarbeitenden Datenmenge bei letzterem bereits eine Vervierfachung der Hardware, was auf Dauer offensichtlich nicht gelingen kann (vgl. z.B. auch diesen Blog-Eintrag).
  2. Die zweite zentrale Herausforderung liegt in der Parallelverarbeitung der Daten begründet. Hier führt nämlich spätestens das Persistieren von Daten nach klassischen Small-Data-Ansätzen zu den üblichen Wettlauf-Bedingungen, vor denen wir in Vorlesungen zur Parallelverarbeitung immer gewarnt wurden. Betrachten wir uns als Beispiel eine replizierte relationale Datenbank, die das gleiche Tupel auf mehreren Maschinen schreiben oder ändern muss: unter ACID-Garantien ist dieses Unterfangen meist mit einem größeren Locking-Aufwand verbunden, der beim Hinzunehmen von weiteren Servern natürlich nicht geringer wird. Das hat unter dem Eindruck des CAP-Theorems zur weiten Verbreitung des BASE-Prinzips geführt (dieses Thema werde ich bei passender Gelegenheit noch einmal vertiefen). Aber auch das in Hadoop zum Einsatz kommende Map-Reduce-Vorgehen ist vor allem der Notwendigkeit geschuldet, gleiche Einträge (bzw. Schlüssel) an eine Maschine im Cluster zu routen, um sie von dort ggf. lockfrei persistieren zu können. Dieses sogenannte Partitioning zieht sich wie ein roter Faden durch die Big-Data-Frameworks und NoSQL-Datenbanken, sobald Daten nicht mehr auf einer Maschine verarbeitet werden kann, müssen wir uns sehr genau überlegen, wie wir die Daten aufteilen wollen.
  3. Die dritte Herausforderung der sich Big-Data-Entwickler gegenüber sehen, ist das beständige Ausreizen der gegebenen Hardware, das häufig eine Umkehrung der Vorgehensweise bei der Systemmodellierung erfordert. Klassische objektorientierte Modellierung baut grob gesprochen die Welt in Software nach und vertraut ihre Persitenz einem O/R-Mapper und einer relationalen Datenbank an. Wie unter Punkt 2 angerissen, sind diese für große Datenmengen oft nicht ausreichend performant, was zunächst einmal der NoSQL-Bewegung Auftrieb gegeben hat. Aber schlimmer noch, selbst eine einzelne NoSQL-Datenbank ist selten in der alle Persistenzanforderungen eines Systems abzudecken. Aufwändige Performance-Tests zur Ermittlung einer ausreichend leistungsfähigen Kombination von Datenbanken und eine "polyglot persistence" sind die logische Folge. Ihre Synchronisation in Fehlersituationen ist unter dem Einfluss des CAP-Theorems ebenfalls kein triviales Problem.
  4. Ein vierter herausfordernder Punkt ist in der Komplexität (im Sinne von vielen verschiedenen Komponenten) der erstellten Systeme zu sehen. Auch die oben angesprochene horizontale Skalierung trägt ihr Scherflein dazu bei, dass Big-Data-Systeme immer mit Ausfällen und Problemen einzelner Komponenten rechnen müssen und damit umgehen können sollten (sog. Resilience). Eine weitere schmerzvolle Erfahrung, die wohl jeder Big-Data-Entwickler schon einmal gemacht hat, ist die, dass Skalierbarkeit noch lange nicht bedeutet, dass ein System in der Praxis auch tatsächlich skaliert. Oft sind es Kleinigkeiten, wie fehlende File Handles o.ä., die ein System bei steigender Last kapitulieren lassen. Nichtsdestotrotz müssen die Probleme natürlich behoben werden, so dass Last- und Perfomancetests bis an die Grenzen des Erwarteten und darüber hinaus ein unverzichtbarer Bestandteil der Systementwicklung werden. Dass es oft sehr teuer oder aus Kostengründen gar unmöglich ist, ein zum Produktivsystem identisches Testsystem vorzuhalten und passende Lastszenarien zu simulieren, liegt auf der Hand. Bei Netflix werden entsprechende Tests daher mittlerweile am Produktivsystem ausgeführt (vgl. hier).
Weiterführend habe ich mit einigen Kollegen einen Fachartikel zu dem Thema geschrieben, der hier (als kostenloser Preprint) gelesen werden kann: O. Hummel, H. Eichelberger, A. Giloj, D. Werle, K. Schmid: A Collection of Software Engineering Challenges for Big Data System Development, Euromicro SEAA, 2018.

Keine Kommentare:

Kommentar veröffentlichen