Professional Documents
Culture Documents
257
CONTENTS
ö ö WHAT IS STREAM PROCESSING?
Understanding Stream öö
öö
WHEN TO USE STREAM
PROCESSING
Processing: öö
öö
TRANSFORMATIONS
WINDOWING
öö RUNNING JOBS
Fast Processing of Infinite and Big Data
öö FAULT TOLERANCE
• Overview of distributed stream processing engines • Real-time stats (monitoring, feeding the real-time dashboards)
• Hands-on examples based on Hazelcast Jet • Real-time ETL (extract, transform, load)
The goal of streaming systems is to process big data volumes and provide
CONTINUOUS DATA
useful insights into the data prior to saving it to long-term storage.
Batch processing forces you to split your data into isolated blocks. The
1
ULTRA FAST,
APPLICATION
EMBEDDABLE,
3RD GENERATION
STREAM PROCESSING
ENGINE
Data Distributed
Stream Fast Batch
Processing java.util.
Processing Processing
Microservices stream
information in the data that crosses the border of batches gets lost. To build a stream processing application, you must:
• Define the transformations
Example: You analyze the behavior of users browsing your website.
• Connect the streaming application to stream sources and sinks.
You run an analytic task on a daily basis, processing one-day
Stream processing platforms mostly provide a set of connectors;
batches. What if somebody keeps browsing your site around
you have to configure them properly
midnight? His or her behavior is divided between two batches and
• Define the dataflow of the application by wiring the sources to
the correlation is lost.
transformations and sinks
Streams, on the other hand, are unbounded by definition. As the data • Execute the stream processing application using the stream
stream is potentially infinite, as is the computation, your insight into processing engine. The engine then takes care of passing the
the data isn't limited by the underlying technical solution. records between the system components (sources, processors, and
sinks) and invoking them when the record arrives. The application
CONSISTENT RESOURCE CONSUMPTION
consumes and processes the stream until it is stopped
Also, processing data as it arrives spreads out workloads more
evenly over time. Stream processing should be used to make the This Refcard will guide you through the building blocks in detail
consumption of resources more consistent and predictable.
EXAMPLE
THE BUILDING BLOCKS Let's consider an application that processes a stream of system log
A stream is a sequence of records. Each record holds information events in order to power a dashboard giving immediate insight into
about an event that happened, such as a user's access to a web what's going on with the system. These are the steps it will take:
site, temperature update from an IoT sensor, or trade being
1. Read the raw data from log files in a watched directory
completed. The records are immutable, as they reflect something
2. Parse and filter it, transforming it into event objects
that had already happened — the user accessed the website, the
DZO N E .CO M/ RE FCA RDZ
3
UNDERSTANDING STREAM PROCESSING
The boxes and arrows form a graph, specifically a Directed stage groups events by key in an infinite stream and calculates
Acyclic Graph (DAG). This model is at the core of modern stream an aggregated value over a sliding window. You provide just the
processing engines. business logic such as the function to extract the grouping key, the
definition of the aggregate function, the definition of the sliding
Here's how you would describe the above DAG in Hazelcast Jet's
window, etc.
Pipeline API. It uses the paradigm of a "pipeline" that consists of
interconnected "stages."
BASIC TRANSFORMATIONS
Pipeline p = Pipeline.create(); We have already mentioned that a stream is a sequence of
isolated records. Many basic transformations process each record
// Read the logs, parse each line, keep only success responses
independently. Such a transformation is stateless.
StreamStage<LogEvent> events =
p.drawFrom(Sources.fileWatcher("log-directory"))
These are the main types of stateless transformation:
.map(LogEvent::parse)
.filter(line -> line.responseCode() >= 200 && line • Map transforms one record to one record, e.g.hange format of the
responseCode() < 400); record, enrich record with some data
// Enrich with machine data • Filter filters out the records that doesn't satisfy the predicate
StreamStage<Entry<Long, LogEvent>> enrichedEvents = events • FlatMap is the most general type of stateless transformation,
hashJoin(
outputting zero or more records for each input record, e.g.
p.drawFrom(Sources.<String, Machine>map("machines")),
joinMapEntries(LogEvent::machineID), tokenize a record containing a sentence into individual words
(e, m) -> entry(e.sequenceNumber(), e.withMachine(m)));
However, many types of computation involve more than one record.
// Save enriched events to HDFS In this case, the processor must maintain internal state across the
JobConf jobConfig = new JobConf(); records. When counting the records in the stream, for example, you
jobConfig.setOutputFormat(TextOutputFormat.class);
DZO N E .CO M/ RE FCA RDZ
4
UNDERSTANDING STREAM PROCESSING
KEYED OR NON-KEYED AGGREGATIONS and grouped together to a meaningful frame. Your transformation is
You often need to classify records by a grouping key, thereby executed just on the records contained in the window.
creating sub-streams containing just the records with the same
grouping key. Each record group is then processed separately. This HOW TO DEFINE WINDOWS
fact can be leveraged for easy parallelization by partitioning the A very simple example is a tumbling window. It divides the continuous
data stream on the grouping key and letting independent threads/ stream into discrete parts that don't overlap. The window is usually
processes/machines handle records with different keys. defined by a time duration or record count. The new window is
opened as soon as the time passes (for time-based windows) or as
EXAMPLES OF KEYED AGGREGATIONS soon as the count reaches the limit (count-based windows).
This example processes a stream of text snippets (tweets or
anything else) by first splitting them into individual words and Examples:
then performing a windowed group-and-aggregate operation. The • Time-based tumbling windows: Counting system usage stats,
aggregate function is simply counting the items in each group. e.g. a count of accesses in the last minute
This results in a live word frequency histogram that updates as • Count-based tumbling windows: Maximum score in a gaming
the window slides along the time axis. Although quite a simple system over last 1,000 results
operation, it gives a powerful insight into the contents of the stream.
The sliding window is also of a fixed size; however, consecutive
tweets.flatMap(tweet -> windows can overlap. It is defined by the size and sliding step.
traverseArray(tweet.toLowerCase().split("\\W+")))
.window(sliding(10_000, 100)) Example:
.groupingKey(wholeItem()) • Time-based sliding windows: Counting system usage stats. Number
.aggregate(counting(),
of accesses in the last minute with updates every ten seconds
(start, end, word, frequency) -> entry(word,
frequency)); A session is a burst of user activity followed by period of inactivity
DZO N E .CO M/ RE FCA RDZ
across all the machines in the cluster and all their CPU cores. one user forms one session. The session is considered closed after
some period of inactivity (let's say one hour). When the user starts
1 2 3
weatherStationReports
.window(sliding(HOURS.toMillis(1), MINUTES.toMillis(1))) Sliding
(size + step)
.aggregate(maxBy(comparing(WeatherStationReport::windSpeed)), 1
5
UNDERSTANDING STREAM PROCESSING
in the real world and has its own timestamp (called the event RUNNING JOBS
time), which can be quite different from the moment the record is The definition of the data processing pipeline (composed of sources,
processed (called the processing time). This can happen due to the sinks, and transformations wired together) is the equivalent of a
distributed nature of the system — the record could be delayed on program, but the environment in which you can execute it is not
its way from source to stream processing system, the link speed simply your local machine. It describes a program that will run
from various sources may vary, the originating device may be offline distributed in the stream processing cluster. Therefore, you must
when the event occurred (e.g. IoT sensor or mobile device in flight perform the additional step of getting a handle to the stream
mode), etc. The difference between processing time and event time processing engine and submitting your program to it.
is called event time skew.
Once you have submitted the pipeline, the SPE allocates the
Processing time semantics should be used when: cluster's resources (i.e. CPU, memory, disk) for it and runs it. Each
• The business use case emphasizes low latency. Results are vertex in the DAG model becomes one or more tasks executing in
computed as soon as possible, without waiting for stragglers. parallel, and each edge (i.e. arrow) becomes a data connection
• The business use case builds on the time when the stream between tasks: either a concurrent queue (if both tasks are on the
processing engine observed the event, ignoring when it same machine) or a network connection. The tasks implementing
originated. Sometimes, you simply don't trust the timestamp in the data source start pulling the data and sending it into the
the event coming from a third party. pipeline. The SPE coordinates the execution of the tasks, monitors
the data connections for congestion, and applies backpressure as
Event time semantics should be used when the timestamp of needed. It also monitors the whole cluster for topology changes (a
the event origin matters for the correctness of the computation. member leaving or joining the cluster) and compensates for them
When your use case is event time-sensitive, it requires more of by remapping the resources devoted to your processing job so that
your attention. If event time is ignored, records can be assigned to it can go on unaffected by these changes. If the job's data source is
DZO N E .CO M/ RE FCA RDZ
improper windows, resulting in incorrect computation results. unbounded, it will keep on running until the user explicitly stops it
(or a failure occurs within the processing logic).
The system has to be instructed where in the record the information
about event time is. Also, it has to be decided how long to wait Stream processing engines usually provide a Client (a programming
for late events. If you tolerate long delays, it is more probable API or a command line tool) that is used for submitting the Job
that you've captured all the events. Short waiting, on the other and its resources to a cluster. The library approach of Hazelcast Jet
hand, gives you faster responses (lower latency) and less resource allows you to follow the "embedded member" mode, where the JVM
consumption — there is less data to be buffered. containing application code participates in the Hazelcast Jet cluster
directly and can be used to submit the job.
In a distributed system, there is no "upper limit" on event time skew.
Embedded Client-Server
Imagine an extreme scenario where there is a game score from
Application
a mobile game. The player is on a plane, so the device is in flight Java API
11 14 12 33 22 35 2
(timestamps)
6
UNDERSTANDING STREAM PROCESSING
• OEM: SPE is embedded in your application it will deal with bounded (finite) or unbounded (infinite) data.
• Microservices
Bounded data is handled in batch jobs and there are fewer concerns
to deal with, as data boundaries are within the dataset itself. You
FAULT TOLERANCE
don't have to worry about windowing, late events, or event time
A major challenge of infinite stream processing is maintaining
skew. Examples of bounded, finite resources are plain files, HDFS,
state in the face of inevitable system failures. The data that was
or iterating through database query results.
already ingested but not yet emitted as final results is at risk of
disappearing forever if the processing system fails. To avoid loss, Unbounded data streams allow for continuous processing; however,
the original input items can be stored until the results of their you have to use windowing for operations that cannot effectively
processing have been emitted. Upon resuming after failure, these work on infinite input (such as sum, avg, or sort). In the unbounded
sitems can then be replayed to the system. The internal state of category, the most popular choice is Kafka. Some databases can be
the computation engine can also be persisted. However, in each turned into unbounded data sources by exposing the journal, the
case, there is an even greater challenge if there must be a strict stream of all data changes, as an API for third parties.
guarantee of correctness. That means that each individual item
must be accounted for and it must be known at each processing Pipeline p = Pipeline.create();
stage whether that particular item was processed. This is called the p.drawFrom(Sources.<Integer, Integer>mapJournal(MAP_NAME,
START_FROM_OLDEST));
exactly-once processing guarantee. A more relaxed variant is called
at-least-once and, in this case, the system may end up replaying an Hazelcast Jet reading the journal of an Imap, the distributed map
item that was already processed. provided by Hazelcast In-Memory Data Grid (unbounded data source).
Bounded data sources are mostly replayable (e.g. plain file, HDFS file).
Current stream processing frameworks do support exactly-
The replayability of infinite data sources is limited by the disk space
once processing. However, assess whether your use case really cannot
necessary to store the whole data stream — an Apache Kafka source
tolerate some duplicities in the case of fault, as exactly-once isn't free
is replayable with this limitation. On the other hand, some sources
in the sense of complexity, latency, throughput, and resources.
can be read only once (e.g. TCP socket source, JMS Queue source).
Example: In a system processing access logs and detecting fraud
It would be quite impractical if you could only replay a
patterns on top of millions of events per second, minor duplicities
data stream from the very beginning. This is why you need
could be tolerated. Duplicities just lead to possible false positives
in exchange for performance. On the other hand, in a billing system, checkpointing: the ability of the stream source to replay its data
consistency and exactly-once is an absolute must have. from the point (offset) you choose. Both Kafka and the Hazelcast
Event Journal support this.
7
UNDERSTANDING STREAM PROCESSING
can deliver your data to the location where the stream processing • Hazelcast Jet: Open-source, lightweight, and embeddable platform
application will consume and process it. For example, if your source for batch and stream processing; contains distributed in-memory
is HDFS, you should align the topologies of the Hadoop and SPE data structures to store operational data and publish results.
clusters so that each machine that hosts an HDFS member also hosts
• Kafka Streams: Open-source SPE integrated into the Apache
a node of the SPE cluster. Hazelcast Jet will automatically figure this
Kafka ecosystem. It's optimized for processing Kafka topics.
out and arrange for each member to consume only the slice of data
stored locally. • Spark Streaming: Open-source; utilizes Spark batch
DZone, Inc.
150 Preston Executive Dr. Cary, NC 27513
DZone communities deliver over 6 million pages each
888.678.0399 919.678.0300
month to more than 3.3 million software developers,
architects and decision makers. DZone offers something for
Copyright © 2018 DZone, Inc. All rights reserved. No part of this publication
everyone, including news, tutorials, cheat sheets, research may be reproduced, stored in a retrieval system, or transmitted, in any form
guides, feature articles, source code and more. "DZone is a or by means electronic, mechanical, photocopying, or otherwise, without
developer’s dream," says PC Magazine. prior written permission of the publisher.