3.
Process Control is the active changing of the process based on the results of process monitoring.
NIST/SEMATECH eHandbook of Statistical Methods 1
Einführung
Daten treiben die neue Welt der Industrie 4.0; die Menge der Daten nimmt dabei in nie vorher
dagewesenem Maße zu. Aus der Bündelung und Auswertung dieser Daten werden neue
Geschäftsideen insbesondere im Kontext von Dienstleistungen entstehen vor allem neue
Dienstleistungen. Mit Sensoren in der Industrie 4.0 können Produktionsdaten, die während der
Prozesse zur Beschaffung, Verteilung und Fertigung entstehen, genutzt werden. Produktion lässt sich
in allen Details transparent darstellen, Effizienz steigern, Overhead verringern. Im Industrial Internet
of Things werden Daten im großen Stil erfasst und intelligent ausgewertet; klassische
Datenbanksysteme sind damit häufig überfordert.
Der vorliegende erste Teil befasst sich mit der Speicherung von Daten in Cassandra, dem Clustering
und dem Zugriff aus Java; der zweite Teil befasst sich mit der Auswertung von Daten mittels Apache
Spark.
Zeitreihen allgemein
Eine Zeitreihe ist eine zeitabhängige
Folge von Datenpunkten, eine
Sequenz von ‘Beobachtungen’ über
den Zeitablauf. Zeitreihen
unterscheiden sich bspw. in
Datenformaten, Maßeinheiten,
fachlicher Domäne sowie in Aspekten
der Übertragungsqualität und
frequenz.
Zeitreihen werden häufig in der
Überwachung industrieller Prozesse
oder der Überwachng von
Geschäftsaktivitäten erhoben. Weitere
Beispiele sind Vorhersagen (Sales),
Analyse von Aktienkursen,
Qualitätsüberwachung der Produktion,
Prognosen hinsichtlich der Maschinenauslastung, ...
1
http://www.itl.nist.gov/div898/handbook/pmc/section4/pmc41.htm
Copyright and all intellectual property belongs to Brockhaus Group 3
4.
Beispiel einer Zeitreihe aus der Produktion eines unserer Kunden (nach Transformation in JSON):
{
"sensorDataList" : [ {
"sensorId" : "PT_DS1_316233.ED01_AB219_M04.AS.V2253",
"time" : "2015‐07‐07,02:07:54",
"datatype" : "FLOAT",
"value" : "60"
}, {
"sensorId" : "PT_DS1_316233.ED01_AB219_M04.AS.V2253",
"time" : "2015‐07‐07,03:10:17",
"datatype" : "FLOAT",
"value" : "60"
}, {
"sensorId" : "PT_DS1_316233.ED01_AB219_M04.AS.V2253",
"time" : "2015‐07‐07,04:12:41",
"datatype" : "FLOAT",
"value" : "60"
} ]
}
Die Analyse von Zeitreihen berücksichtigt, dass die Daten eine interne Struktur haben können. Diese
Strukturen können bspw. Trends, umweltabhängige Variationen oder Korrelationen sein. Für die
Analyse von Zeitreihen existieren eine Reihe von Verfahren, diese sind jedoch nicht Gegenstand dieses
Dokuments welches sich auf die Speicherung von Zeitreihen fokussiert.
Zeitreihen und Machine Learning
So if you want your program to predict, for example, traffic patterns at a
busy intersection (task T), you can run it through a machine learning
algorithm with data about past traffic patterns (experience E) and, if it
has successfully “learned”, it will then do better at predicting future
traffic patterns (performance measure P).
Tony Mitchell, Carnegie Mellon University
Die zentrale Fragestellung des maschinellen Lernens besteht darin, wie
man aus der Beobachtung von BeispielMessungen, auf neue Messungen generalisieren kann; m.a.W.
das Entwickeln von Algorithmen welche aus ‘Erfahrung’ sich kontinuierlich verbessern. Hierzu ist es
notwendig, ‘Gesetzmäßigkeiten’ in den Daten zu erkennen. Werden als Input Klassifikationen und
Daten geliefert, wird von überwachtem Lernen gesprochen; werden nur die Daten geliefert, wird von
unüberwachtem Lernen gesprochen.
Generell geht beim Machine Learning jedoch nicht darum, perfekte Schätzungen zu haben sondern
Schätzungen die gut genug sind, um etwas damit anfangen zu können. Wie haben ein Paper hierzu
geschrieben und eine gute und leicht verständliche Einführung findet sich hier.
Ein Beispiel wäre, aus den Produktionsbedingungen eine bestimmte Produktqualität herzuleiten; hat
man eine Verweildauer von n Minuten bei der Härtung von Lacken, dann kann daraus hergeleitet
werden, dass die Oberfläche entsprechend unempfindlich wird und weitere Prozesschritte eine
entsprechende Qualität aufweisen. Das kann man noch mit Viskosität des Lacks, ppm Verunreinigung
Copyright and all intellectual property belongs to Brockhaus Group 4
5.
in der Lackierkabine oder Temperatur der Reinigungsbäder usw. usw in Verbindung bringen.
Am Ende des Tages geht es darum, in Datenreihen Muster zu erkennen und zukünftiges Verhalten
einigermaßen zuverlässig herleiten zu können. Zu den entsprechenden Tools wird in Bälde ein
weiteres Paper erscheinen; für den Augenblick steht die Speicherung im Vordergrund.
Zeitreihen und Complex Event Processing2
Im Kontext des CEP (Complex Event
Processing) werden die Daten nicht aus der
Datenbank heraus sondern während ihres
Entstehens als Datenstrom analysiert. Hierbei
werden Events gefiltert und mit Events aus
anderen Strömen korreliert. Werden mehrere
Ströme in Korrelation gebracht, spricht man
von komplexen Events. Das Auswerten
geschieht im Hauptspeicher und die Daten
werden im Gegensatz zur SQL Abfrage
kontinuierlich ausgewertet. Über
Publish/SubscriberMechanismen kann man sich für bestimmte Events registrieren und entsprechend
auf diese reagieren. Für den Kontext der Speicherung von Zeitreihen kann man somit festhalten, dass
vor dem Speicher ggf. CEPAnsätze relevant sind, nach dem Speichern Ansätze aus dem Machine
Learning relevant sein können.
2
http://www.heise.de/ix/artikel/KontinuierlicheKontrolle905334.html
Copyright and all intellectual property belongs to Brockhaus Group 5
6.
Das Szenario
Für das Beispiel soll von einem Aufbau ausgegangen werden, welcher aus einer Taktfertigung Daten
aus einer Siematic S7 über einen entsprechenden OPC Server und/oder über entsprechende Sensoren
und einen Raspberry Pi erhält.
Dieses Beispiel wurde bewusst gewählt um die Nachvollziehbarkeit bei gleichzeitiger Realitätsnähe
sicherzustellen alle Technologien (Ausnahme: OPC Server) sind Open Source und die benötigte
Hardware kann für überschaubares Geld beschafft werden. Bezüglich der Kommunikation mit der PLC
über OPC DA existiert bereits ein entsprechender Artikel, gleiches gilt für die Kommunikation über
Raspberry Pi, Python, Java und MQTT.
Copyright and all intellectual property belongs to Brockhaus Group 6
7.
Zum Vergleich die Referenz Architektur für das IoT der IIS ; offensichtlich ist, dass die Speicherung 3
und Auswertung der Sensordaten im PlatformTier anzusiedeln ist.
3
http://www.sierramonitor.com/blog/referencearchitectureforiiot/
Copyright and all intellectual property belongs to Brockhaus Group 7
8.
Apache Cassandra
Allgemeines zu Cassandra
Cassandra ist die populärste spaltenorientierte NoSQLDatenbank.
Entstanden aus einem Projekt bei Facebook ist Cassandra heute ein
TopLevel Projekt der Apache Foundation. Herausragende Eigenschaften
sind die fast beliebige Skalierbarkeit bei hoher Performanz. Cassandra ist
zu 100% in Java geschrieben.
Eine Gegenüberstellung der Terminologie erleichtert den Einstieg:
Datenbankinstanz Clusternode
Datenbank Keyspace
Tabelle Tabelle / Column Family
Zeile Zeile
Spalte Spalte
Primärschlüssel Zeilenschlüssel (Row key)
Cassandra besitzt ein relativ einfaches Datenmodell, eine Mischung aus einem KeyValueStore und
einer spaltenorientierten Datenbank. Die Daten werden dabei in Column Families organisiert. Eine
Column Family besteht aus beliebig
vielen „Row Keys“, welchen wiederum
beliebig viele Schlüssel Werte Paare
zugeordnet werden können. Im
CassandraKontext werden die
Schlüssel dabei als „Column“
bezeichnet. Eine Column Family ist
also eine mehrdimensionale Map . 4
Super Columns gelten als deprecated
und werden nicht mehr unterstützt.
Cassandra bietet eine an SQL angelehnte Abfragesprache: die Cassandra Query Language (CQL);
dieses erlaubt einen schnellen Einstieg in die Technologie da eine große Schnittmenge zwischen der
‘herkömmlichen’ SQL und der spezifischen Abfragesprache existiert.
4
Vergl: http://de.slideshare.net/dominiqueronde/seaconcassandra
Copyright and all intellectual property belongs to Brockhaus Group 8
9.
Installation
Hierzu sollen nicht viele Worte verloren werden, es existiert eine entsprechende Dokumentation;
empfehlenswert für die Entwicklung ist die Installation des devcenters von datastax. Will man mehrere
Instanzen von Cassandra auf einem Rechner installieren, dann ist hier die entsprechende
Vorgehensweise zu finden.
Neben dem devcenter bringt Cassandra von Hause aus zwei Tools mit, mit deren Anwendung man sich
vertraut machen sollte: cassandracli und cqlsh. Obwohl cassandracli nicht mehr empfohlen wird, hat
es doch einige Features die sich als recht nützlich erwiesen haben.
Copyright and all intellectual property belongs to Brockhaus Group 9
10.
Einrichten von Keyspace und ColumnFamily
Der Keyspace
Der Keyspace lasst sich am ehesten mit einer Datenbankinstanz vergleichen, angelegt wird er mittels
folgendem Statement:
CREATE KEYSPACE sensors
WITH replication = {'class':'SimpleStrategy', 'replication_factor':3};
Zur Syntax und der Replikation kommen wir später noch detailliert. Das Nutzen des Keyspace erfolgt
über:
USE test;
Das Löschen eines Keyspace erfolgt entsprechend mittels:
DROP KEYSPACE test;
Die Column Family
Wichtig bei dem Design des Column Family (aka Tabellen) Schemas ist, die generellen Best Practices
zu berücksichtigen. Weiterhin sollte man wissen, dass man in Cassandra nur nach Schlüsseln und
Indices suchen kann. Jede Query nach anderen Daten führt zu einem Fehler. Dieses hat Konsequenzen
für das logische Design.
Weiterhin muss man das Konzept der Schlüssel in Cassandra berücksichtigen. Bei einem
zusammengesetzten Primärschlüssel nutzt Cassandra die erste Spalte stets als sogenannten
Partitionierungsschlüssel (partition key), über den die Daten redundant auf einzelne ClusterInstanzen
verteilt werden. Das zweite Element des Primärschlüssels ist der sogenannte ClusteringKey, mit dem
Cassandra Daten vorgruppiert, um diese effektiv mit einer Anfrage zu ermitteln . 5
Bei allen Versuchen, Analogien zwischen dem relationalen Paradigma und Cassandra herzustellen
muss man stets im Auge behalten, dass Cassandra fundamental anders ist.
DDL (die Erste):
CREATE TABLE sensor_data (
sensor_id text, ‐‐ the id of an individual sensor
datatype text, ‐‐ the datatype of the value [FLOAT, BOOLEAN, ...]
time timestamp, ‐‐ the time the value was send
value text, ‐‐ the value itself
PRIMARY KEY(sensor_id, time)
); 6
5
http://thelastpickle.com/blog/2013/01/11/primarykeysincql.html
6
es besteht zusätzlich die Möglichkeit über die CLUSTERING ORDER eine auf oder absteigende Sortierung
vorzunehmen, siehe hier.
Copyright and all intellectual property belongs to Brockhaus Group 10
11.
Fügen wir Daten ein:
INSERT INTO sensor_data(SENSOR_ID, DATATYPE, TIME, VALUE) VALUES('ABC‐123', 'FLOAT',
'2013‐04‐03 07:01:01','100');
INSERT INTO sensor_data(SENSOR_ID, DATATYPE, TIME, VALUE) VALUES('ABC‐123', 'FLOAT',
'2013‐04‐03 07:01:02','101');
INSERT INTO sensor_data(SENSOR_ID, DATATYPE, TIME, VALUE) VALUES('ABC‐123', 'FLOAT',
'2013‐04‐03 07:01:03','99');
Und lassen uns alle Daten mittels CQL anzeigen:
SELECT * FROM sensor_data;
sensor_id | time | datatype | value
‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐
ABC‐123 | 2013‐04‐03 07:01:01+0200 |FLOAT | 100
ABC‐123 | 2013‐04‐03 07:01:02+0200 |FLOAT | 101
ABC‐123 | 2013‐04‐03 07:01:03+0200 |FLOAT | 99
Unterstellen wir für den Augenblick, wir wollten alle Messwerte eines bestimmten Sensors innerhalb
eine bestimmten Zeitintervalls auswerten (bspw. MAX, MIN, AVG):
SELECT * FROM SENSOR_DATA WHERE SENSOR_ID = 'ABC‐123'
AND TIME > '2013‐04‐03 07:00:00'
AND TIME < '2013‐04‐03 09:00:00';
sensor_id | time | datatype | value
‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐
ABC‐123 | 2013‐04‐03 07:01:01+0200 |FLOAT | 100
ABC‐123 | 2013‐04‐03 07:01:02+0200 |FLOAT | 101
ABC‐123 | 2013‐04‐03 07:01:03+0200 |FLOAT |99
Nachteile des Ansatzes
Auf den ersten Blick sieht der Ansatz ganz zielführend aus, doch halten wir uns vor Augen, wie die
Daten in Cassandra verwaltet werden : 7
SortedMap<row_key, SortedMap<column_key, column_value>>
Hier wird ersichtlich, dass die gewählte logische Struktur nicht unbedingt optimal ist. Das cassandra.cli
tool zeigt die Daten genauso, wie sie gespeichert werden:
[default@unknown] use test;
Authenticated to keyspace: test
[default@test] list sensor_data;
Using default limit of 100
Using default cell limit of 100
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
RowKey: ABC‐123
=> (name=2013‐04‐03 07:01+0200:, value=, timestamp=1440817452694000)
7
Vergl. hierzu:
http://www.planetcassandra.org/blog/understandinghowcql3mapstocassandrasinternaldatastructure/
Copyright and all intellectual property belongs to Brockhaus Group 11
12.
=> (name=2013‐04‐03 07:01+0200:datatype, value=464c4f4154, timestamp=1440817452694000)
=> (name=2013‐04‐03 07:01+0200:value, value=313030, timestamp=1440817452694000)
=> (name=2013‐04‐03 07:01+0200:, value=, timestamp=1440817452696000)
=> (name=2013‐04‐03 07:01+0200:datatype, value=464c4f4154, timestamp=1440817452696000)
=> (name=2013‐04‐03 07:01+0200:value, value=313031, timestamp=1440817452696000)
=> (name=2013‐04‐03 07:01+0200:, value=, timestamp=1440817452697000)
=> (name=2013‐04‐03 07:01+0200:datatype, value=464c4f4154, timestamp=1440817452697000)
=> (name=2013‐04‐03 07:01+0200:value, value=3939, timestamp=1440817452697000)
1 Row Returned.
Das Problem liegt darin, dass alle Daten in lediglich einer Zeile gespeichert sind. Auch wenn Cassandra
bis zu 2 Mrd. Spalten pro Zeile verwalten kann ist das Ende dieses Ansatzes schnell erreicht: Wenn im
100 ms Intervall Sensorwerte ankommen (26.298.000 Werte pro Monat), dann ist das Ende der
Möglichkeiten schnell erreicht .
DDL (die Zweite)
Wenn der Rowkey über den ersten Teil des Primärschlüssels bestimmt wird dann ist es nur
konsequent, wenn man diesen anders organisiert; die zeitliche Komponente sollte Teil des RowKeys
sein. Dieser Ansatz zusammengesetzter Schlüssel (compound key) wird (auch) TimeBucket genannt.
CREATE TABLE sensor_data (
sensor_id text,
datatype text,
time timestamp, ‐‐ alternatively you might consider writetime 8
time_range timestamp,
time_scale text,
value text,
PRIMARY KEY((sensor_id, time_range), time)
);
Wie man anhand des CQL Statements sieht, ist der erste Teil des Schlüssels nunmehr aus der
Sensor_ID und einer zeitlichen Range zusammengesetzt.
Fügen wir Daten hinzu (beachte den letzten Insert mit dem geänderten timerange Wert):
INSERT INTO sensor_data(SENSOR_ID, DATATYPE, TIME, TIME_RANGE, TIME_SCALE, VALUE)
VALUES('ABC‐123', 'FLOAT', '2013‐04‐03 07:01:00', '2013‐04‐03 07:00:00', 'HOUR','100');
INSERT INTO sensor_data(SENSOR_ID, DATATYPE, TIME, TIME_RANGE, TIME_SCALE, VALUE)
VALUES('ABC‐123', 'FLOAT', '2013‐04‐03 07:02:00', '2013‐04‐03 07:00:00', 'HOUR', '100');
INSERT INTO sensor_data(SENSOR_ID, DATATYPE, TIME, TIME_RANGE, TIME_SCALE, VALUE)
VALUES('ABC‐123', 'FLOAT', '2013‐04‐03 07:03:00', '2013‐04‐03 07:00:00', 'HOUR', '100');
INSERT INTO sensor_data(SENSOR_ID, DATATYPE, TIME, TIME_RANGE, TIME_SCALE, VALUE)
VALUES('ABC‐123', 'FLOAT', '2013‐04‐03 07:04:00', '2013‐04‐03 07:00:00', 'HOUR', '100');
INSERT INTO sensor_data(SENSOR_ID, DATATYPE, TIME, TIME_RANGE, TIME_SCALE, VALUE)
VALUES('ABC‐123', 'FLOAT', '2013‐04‐03 07:04:00', '2013‐04‐03 07:00:00', 'HOUR', '101');
8
see: http://docs.datastax.com/en/cql/3.1/cql/cql_reference/select_r.html
Copyright and all intellectual property belongs to Brockhaus Group 12
13.
INSERT INTO sensor_data(SENSOR_ID, DATATYPE, TIME, TIME_RANGE, TIME_SCALE, VALUE)
VALUES('ABC‐123', 'FLOAT', '2013‐04‐03 08:01:00', '2013‐04‐03 08:00:00', 'HOUR', '100');
Lassen uns die Daten anzeigen:
RowKey: ABC‐123:2013‐04‐03 08:00+0200
=> (name=2013‐04‐03 08:01+0200:, value=, timestamp=1440819638161000)
=> (name=2013‐04‐03 08:01+0200:datatype, value=464c4f4154, timestamp=1440819638161000)
=> (name=2013‐04‐03 08:01+0200:time_scale, value=484f5552, timestamp=1440819638161000)
=> (name=2013‐04‐03 08:01+0200:value, value=313030, timestamp=1440819638161000)
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
RowKey: ABC‐123:2013‐04‐03 07:00+0200
=> (name=2013‐04‐03 07:01+0200:, value=, timestamp=1440819638148000)
=> (name=2013‐04‐03 07:01+0200:datatype, value=464c4f4154, timestamp=1440819638148000)
=> (name=2013‐04‐03 07:01+0200:time_scale, value=484f5552, timestamp=1440819638148000)
=> (name=2013‐04‐03 07:01+0200:value, value=313030, timestamp=1440819638148000)
=> (name=2013‐04‐03 07:02+0200:, value=, timestamp=1440819638153000)
=> (name=2013‐04‐03 07:02+0200:datatype, value=464c4f4154, timestamp=1440819638153000)
=> (name=2013‐04‐03 07:02+0200:time_scale, value=484f5552, timestamp=1440819638153000)
=> (name=2013‐04‐03 07:02+0200:value, value=313030, timestamp=1440819638153000)
=> (name=2013‐04‐03 07:03+0200:, value=, timestamp=1440819638155000)
=> (name=2013‐04‐03 07:03+0200:datatype, value=464c4f4154, timestamp=1440819638155000)
=> (name=2013‐04‐03 07:03+0200:time_scale, value=484f5552, timestamp=1440819638155000)
=> (name=2013‐04‐03 07:03+0200:value, value=313030, timestamp=1440819638155000)
=> (name=2013‐04‐03 07:04+0200:, value=, timestamp=1440819638159000)
=> (name=2013‐04‐03 07:04+0200:datatype, value=464c4f4154, timestamp=1440819638159000)
=> (name=2013‐04‐03 07:04+0200:time_scale, value=484f5552, timestamp=1440819638159000)
=> (name=2013‐04‐03 07:04+0200:value, value=313031, timestamp=1440819638159000)
2 Rows Returned.
Der Unterschied ist offensichtlich, jetzt werden pro Sensor und Stunde eine Zeile angelegt.
Wird nun die gleiche Query ausgeführt, führt diese allerdings zu einem Fehler:
InvalidRequest: code=2200 [Invalid query] message="Partition key part time_range must be
restricted since preceding part is"
Dieses resultiert aus der Tatsache, dass in Cassandra nur nach dem Primärschlüssel oder nach
indizierten Werten gesucht werden kann. Ach diese Query (ausschließlich über den Primäsrschlüssel)
führt zu einem Fehler:
SELECT * FROM SENSOR_DATA WHERE SENSOR_ID = 'ABC‐123'
AND TIME_RANGE > '2013‐04‐03 07:00:00'
AND TIME_RANGE < '2013‐04‐03 09:00:00';
InvalidRequest: code=2200[Invalidquery]message="OnlyEQandINrelationaresupportedonthe
partition key (unless you use the token() function)"
Ergo wird man nicht darum herumkommen, einen Index anzulegen:
CREATE INDEX sensor_id_index ON sensor_data (sensor_id);
Copyright and all intellectual property belongs to Brockhaus Group 13
14.
Die Query führt dann auch zum gewünschten Ergebnis:
SELECT * FROM SENSOR_DATA WHERE SENSOR_ID = 'ABC‐123'
... AND TIME > '2013‐04‐03 07:00:00'
... AND TIME < '2013‐04‐03 09:00:00'
... ALLOW FILTERING; 9
sensor_id | time_range | time | datatype | time_scale | value
‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐
‐‐
ABC‐123 | 2013‐04‐03 08:00:00+0200 | 2013‐04‐03 08:01:00+0200 | FLOAT | HOUR |
100
ABC‐123 | 2013‐04‐03 07:00:00+0200 | 2013‐04‐03 07:01:00+0200 | FLOAT | HOUR |
100
ABC‐123 | 2013‐04‐03 07:00:00+0200 | 2013‐04‐03 07:02:00+0200 | FLOAT | HOUR |
100
ABC‐123 | 2013‐04‐03 07:00:00+0200 | 2013‐04‐03 07:03:00+0200 | FLOAT | HOUR |
100
ABC‐123 | 2013‐04‐03 07:00:00+0200 | 2013‐04‐03 07:04:00+0200 | FLOAT | HOUR |
101
9
http://www.datastax.com/dev/blog/allowfilteringexplained2
Copyright and all intellectual property belongs to Brockhaus Group 14
15.
Weiterführende Themen in diesem Kontext
Definierte Time to Live (TTL)
Je nach Frequenz der eintreffenden Sensordaten kann die Datenmenge enorm werden und die
Rohdaten sind nicht unbeding würdig über lange Zeiträume aufgehoben zu werden.
CQL bietet die Möglichkeit, die Speicherungsdauer der Daten (in Millisekunden) bereits beim Insert zu
mittels ‘USING TTL’ definieren:
INSERT INTO sensor_data(SENSOR_ID, DATATYPE, TIME, TIME_RANGE, TIME_SCALE, VALUE)
VALUES('ABC‐123', 'FLOAT', '2013‐04‐03 07:01:00', '2013‐04‐03 07:00:00', 'HOUR','100') USING
TTL 200;
Die noch verbleibende Lebensdauer lässt sich mit folgendem Statement abfragen:
SELECT TTL(value) FROM sensor_data WHERE sensor_id = 'ABC‐123';
Cassandra im Cluster
Das Szenario: verschiedene Control Desk Areas
Eine der Anforderungen in einem unserer Projekte war es, die momentane Art der CSVDatei basierten
Datenhaltung für eine sog. ControlDesk Area (Produktionssegment) durch eine integrierte Lösung
über eine Datenbank zu realisieren. Hierbei waren Ausfallsicherheit und die Fähigkeit zu archivieren
wesentliche Anforderungen.
Copyright and all intellectual property belongs to Brockhaus Group 15
16.
Clusterdefinition
Cassandra arbeitet als PeertoPeer Cluster ohne
dezidierten Masterknoten.
In Cassandra werden die Zugehörigkeit einzelner
Knoten zu einem Cluster über sog. Snitches definiert.
Hierbei ‘informieren’ die Snitches Cassandra über die
aus Data Centern und Racks gebildete Topologie und
erlaubt so eine performante Replikation der Daten.
Cassandra verfügt über verschiedene Strategien,
transparent wird die definition eines Snitches am
Beispiel des PropertyFileSnitch, konfiguriert in der
Datei ‘cassandratopology.properties’:
# Cassandra Node IP=Data Center:Rack
192.168.1.100=DC1:RAC1
192.168.2.200=DC2:RAC2
Der/die/das genutzte Snitch wird in der zentralen Konfigurationsdatei ‘cassandra.yaml’ definiert:
endpoint_snitch: SimpleSnitch
Hier finden sich auch kurze Erläuterungen zu den anderen Snitches.
Replikation im Cluster
Cassandra ermöglicht auf einfache Art und Weise die Datenreplikation im Cluster; hierbei muss nur
festgelegt werden, wieviele Replikate man möchte. Dieses erfolgt bereits beim Anlegen des Keyspace
über den Replication Factor.
CREATE KEYSPACE sensors
WITH replication = {'class':'SimpleStrategy', 'replication_factor':2};
Die Zeilen einer ColumnFamily werden über die einzelnen Knoten des Clusters verteilt. Die Art und
Weise der Verteilung bestimmen die Partitioner, hierbei sollte eine möglichst gleiche Verteilung über
die Knoten angestrebt werden.
Für die Verteilung existieren zwei Strategien welche im Folgenden kurz angerissen werden.
1. Simple Strategy
Die SimpleStrategy kann nur innerhalb eines Datacenters genutzt werden. Auf Basis des
ersten Teils des Primärschlüssels dem PartitionKey werden mittels Partitioner der
entsprechende Knoten bestimmt, die Replikation erfolgt im Uhrzeigersinn entlang des Clusters
verteilt.
2. NetworkTopologyStrategy
Hier werden die Gegebenheiten des Netzwerkes berücksichtigt, die Replikate auch
verschiedene Racks verteilt
Copyright and all intellectual property belongs to Brockhaus Group 16
17.
Sollen die entsprechenden Replikationsstrategien in verteilten Umgebungen genutzt werden, muss das
create Statement entsprechend angepasst werden.
Cassandra und Java
Der vollständige SourceCode findet sich hier:
https://github.com/brockhausgruppe/cassandratimeseries
Die in den vorherigen Abschnitten dargestellten Sachverhalten wurden mittels Java und dem
entsprechenden Cassandra Treiber implementiert. Hierbei war der Leitfaden, sich am DAO Pattern zu
orientieren. Für das Besipiel sollte folgende Implementierung ausreichen, ein generisches DAO etc. ist
für die Zukunft denkbar.
Unterstellen wir weiterhin, dass die Sensordaten über Socket, als CSV Datei mittels FTP o.ä. seitens
des Shopfloors übermittelt werden, kann im Falle von CSV Dateien das NIO2 Package von Java
Copyright and all intellectual property belongs to Brockhaus Group 17