You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/backend/setup-storm.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,7 +19,7 @@ To use Bullet, you need to implement a way to read from your data source and con
19
19
1. You can implement a Spout that reads from your data source and emits Bullet Record. This spout must have a constructor that takes a List of Strings.
20
20
2. You can pipe your existing Storm topology directly into Bullet. In other words, you convert the data you wish to be query-able through Bullet into Bullet Records from a bolt in your topology.
21
21
22
-
Option 2 *directly* couples your topology to Bullet and as such, you would need to watch out for things like back-pressure etc.
22
+
Option 1 is the simplest to start with and should accommodate most scenarios. See [Pros and Cons](storm-architecture.md#data-processing).
23
23
24
24
You need a JVM based project that implements one of the two options above. You include the Bullet artifact and Storm dependencies in your pom.xml or other dependency management system. The artifacts are available through JCenter, so you will need to add the repository.
Copy file name to clipboardExpand all lines: docs/backend/storm-architecture.md
+12-8Lines changed: 12 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -30,30 +30,34 @@ The red colored lines are the path for the queries that come in through Storm DR
30
30
31
31
Bullet can accept arbitrary sources of data as long as they can be read from Storm. You can either:
32
32
33
-
1. Write a Storm spout that reads your data from where ever it is (Kafka, etc) and [converts it to Bullet Records](ingestion.md). See [Quick Start](../quick-start.md#storm-topology) for an example.
33
+
1. Write a Storm spout that reads your data from where ever it is (Kafka etc) and [converts it to Bullet Records](ingestion.md). See [Quick Start](../quick-start.md#storm-topology) for an example.
34
34
2. Hook up an existing topology that is doing something else directly to Bullet. You will still write and hook up a component that converts your data into Bullet Records in your existing topology.
35
35
36
-
Option 2 is nice if you do not want to introduce a persistence layer between your existing Streaming pipeline and Bullet. For example, if you just want periodically look at some data within your topology, you could filter them, convert them into Bullet Records and send it into Bullet. You could also sample data. The downside of Option 2 is that you will directly couple your topology with Bullet leaving your topology to be affected by Bullet through Storm features like back-pressure (if you are on Storm 1.0) etc. You could also go with Option 2 if you need something more complex than just a spout from Option 1. For example, you may want to process your data in some fashion before emitting to Bullet.
| Option 1 | Very simple to get started. Just implement a spout | Need a storage layer that your spout pulls or some system has to push to your spouts |
39
+
| Option 2 | Saves a persistence layer | Ties your topology to Bullet directly, making it affected by Storm Backpressure etc |
40
+
| Option 2 | You can add bolts to do more processing on your data before sending it to Bullet | Increases the complexity of the topology |
37
41
38
-
Your data is then emitted to the Filter bolt which promptly drops all Bullet Records and does absolutely nothing if you have no queries in your system. If there are queries in the Filter bolt, the record is checked against the [filters](../index.md#filters) in each query and if it matches, it is processed by the query. Each query can choose to emit matched records in micro-batches. For example, queries that collect raw records (a LIMIT operation) do not micro-batch at all. Every matched record (up to the maximum for the query) is emitted. Queries that aggregate, on the other hand, keep the query around till its duration is up and emit the local result.
42
+
Your data is then emitted to the Filter bolt. If you have no queries in your system, the Filter Bolt will promptly drop all Bullet Records and do absolutely nothing. If there are queries in the Filter bolt, the record is checked against the [filters](../index.md#filters) in each query and if it matches, it is processed by the query. Each query type can choose to emit matched records in micro-batches. By default, ```RAW``` or ```LIMIT``` queries do not micro-batch. Each matched record up to the maximum for the query is emitted at once at the Filter bolt. Queries that aggregate, on the other hand, keep the query around till its duration is up and emit the local result. This is because these queries *cannot* return till they see all the data in your time window anyway because some late arriving data may update an existing aggregate.
39
43
40
-
!!! note "To micro-batch or not to micro-batch?"
44
+
!!! note "Why support micro-batching?"
41
45
42
-
```RAW``` queries micro-batch by size 1, which makes Bullet really snappy when running those queries. As soon as your maximum record limit is reached, the query immediately returns. On the other hand, the other queries do not micro-batch at all. ```GROUP``` and other aggregate queries *cannot* return till they see all the data in your time window because some late arriving data may update an existing aggregate. So, these other queries have to wait for the entire query duration anyway. Once the queries have timed out, we have to rely on the ticks to get all the intermediate results over to the combiner to merge. Micro-batches are still useful here because we can still emit intermediate aggregations (and they are [additive](#combining)) and relieve memory pressure by periodically purging intermediate results. In practice though, Bullet queries are generally short-lived, so this isn't as needed as it may seem on first glance. Depends on whether others (you) find it necessary, we may decide to implement micro-batching for other queries besides ```RAW``` types.
46
+
```RAW``` queries do not micro-batch by default, which makes Bullet really snappy when running those queries. As soon as your maximum record limit is reached, the query immediately returns. You can use a setting in [bullet_defaults.yaml](https://github.com/yahoo/bullet-storm/blob/master/src/main/resources/bullet_defaults.yaml) to turn on batching if you like. At some point in the future, micro-batching will let Bullet provide incremental results - partial results arrive over the duration of the query. Bullet can emit intermediate aggregations as they are all [additive](#combining).
43
47
44
48
### Request processing
45
49
46
50
Storm DRPC handles receiving REST requests for the whole topology. The DRPC spouts fetch these requests (DRPC knows the request is for the Bullet topology using the unique function name set when launching the topology) and shuffle them to the Prepare Request bolts. The request also contains information about how to return the response back to the DRPC servers. The Prepare Request bolts generate unique identifiers for each request (a Bullet query) and broadcasts them to every Filter bolt. Since every Filter bolt has a copy of every query, the shuffled data from the source of data can be compared against the query no matter which particular Filter bolt it ends up at. Each Filter bolt has access to the unique query id and is able to key group by the id to the Join bolt with the intermediate results for the query.
47
51
48
-
The Prepare Request bolt also key groups the query and the return information to the Join bolts. This means that only *one* Join bolt ever gets one query.
52
+
The Prepare Request bolt also key groups the query and the return information to the Join bolts. This means that the query will be assigned to one and only one Join bolt.
49
53
50
54
### Combining
51
55
52
-
Since the data from the Prepare Request bolt (a query and a piece of return information for the query) and the data from all Filter bolts (intermediate results) is key grouped by the unique query id, only one particular Join bolt receives both the query and all the intermediate results for a particular query. The Join bolt can then combine all the intermediate results and produce a final result. This final result is joined (hence the name) with the return information for the query and is shuffled to the Return Results bolt. This bolt then uses the return information to send the results back to a DRPC server, who then returns it back to the requester.
56
+
Since the data from the Prepare Request bolt (a query and a piece of return information for the query) and the data from all Filter bolts (intermediate results) is key grouped by the unique query id, only one particular Join bolt receives both the query and all the intermediate results for a particular query. The Join bolt can then combine all the intermediate results and produce a final result. This final result is joined (hence the name) with the return information for the query and is shuffled to the Return Results bolt. This bolt then uses the return information to send the results back to a DRPC server, which then returns it back to the requester.
53
57
54
58
!!! note "Combining and operations"
55
59
56
-
In order to be able to combine intermediate results and process data in any order, all aggregations that Bullet does need to be associative and have an identity. In other words, they need to be [Monoids](https://en.wikipedia.org/wiki/Monoid). Luckily for us, the [DataSketches](http://datasketches.github.io) that we use are monoids (actually are commutative monoids). Sketches be unioned and thus all the aggregations we support - SUM, COUNT, MIN, MAX, AVG, COUNT DISTINCTS, DISTINCT - are monoidal. (AVG is monoidal if you store a SUM and a COUNT instead).
60
+
In order to be able to combine intermediate results and process data in any order, all aggregations that Bullet does need to be associative and have an identity. In other words, they need to be [Monoids](https://en.wikipedia.org/wiki/Monoid). Luckily for us, the [DataSketches](http://datasketches.github.io) that we use are monoids (actually are commutative monoids). Sketches can be unioned and thus all the aggregations we support - ```SUM```, ```COUNT```, ```MIN```, ```MAX```, ```AVG```, ```COUNT DISTINCT```, ```DISTINCT``` - are monoidal. (```AVG``` is monoidal if you store a ```SUM``` and a ```COUNT``` instead).
Copy file name to clipboardExpand all lines: docs/index.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,7 +12,7 @@
12
12
13
13
* Provides a **UI and Web Service** that are also pluggable for a full end-to-end solution to your querying needs
14
14
15
-
*Can be implemented on different Stream processing frameworks. Bullet on [Storm](http://storm.apache.org)is currently available
15
+
*Has an implementation on [Storm](http://storm.apache.org) currently. There are plans to implement it on other Stream Processors.
16
16
17
17
* Is **pluggable**. Any data source that can be read from Storm can be converted into a standard data container letting you query that data. Data is **typed**
18
18
@@ -32,15 +32,15 @@ This instance of Bullet also powers other use-cases such as letting analysts val
32
32
33
33
# Quick Start
34
34
35
-
See [Quick Start](quick-start.md) to set up Bullet on a local Storm topology. We will generate some fake streaming data that you can then query with Bullet.
35
+
See [Quick Start](quick-start.md) to set up Bullet on a local Storm topology. We will generate some synthetic streaming data that you can then query with Bullet.
36
36
37
37
# Setting up Bullet on your streaming data
38
38
39
39
To set up Bullet on a real data stream, you need:
40
40
41
-
1.The backend set up on a Stream processor:
41
+
1.To setup the Bullet backend on a stream processing framework. Currently, we support [Bullet on Storm](backend/setup-storm.md):
42
42
1. Plug in your source of data. See [Getting your data into Bullet](backend/ingestion.md) for details
43
-
2. Consume your data stream. Currently, we support [Bullet on Storm](backend/setup-storm.md)
43
+
2. Consume your data stream
44
44
2. The [Web Service](ws/setup.md) set up to convey queries and return results back from the backend
45
45
3. The optional [UI](ui/setup.md) set up to talk to your Web Service. You can skip the UI if all your access is programmatic
46
46
@@ -54,11 +54,11 @@ To set up Bullet on a real data stream, you need:
54
54
55
55
Bullet queries allow you to filter, project and aggregate data. It lets you fetch raw (the individual data records) as well as aggregated data.
56
56
57
-
See the [UI Usage section](ui/usage.md) for using the UI to build Bullet queries. This is the same UI you will build in the [Quick Start](quick-start.md)
57
+
*See the [UI Usage section](ui/usage.md) for using the UI to build Bullet queries. This is the same UI you will build in the [Quick Start](quick-start.md)
58
58
59
-
See the [API section](ws/api.md) for building Bullet API queries.
59
+
*See the [API section](ws/api.md) for building Bullet API queries
60
60
61
-
For examples using the API, see [Examples](ws/examples.md). These are actual albeit cleansed queries sourced from the instance at Yahoo.
61
+
*For examples using the API, see [Examples](ws/examples.md). These are actual albeit cleansed queries sourced from the instance at Yahoo.
62
62
63
63
## Termination conditions
64
64
@@ -134,7 +134,7 @@ Using Sketches, we have implemented ```COUNT DISTINCT``` and ```GROUP``` and are
134
134
The Bullet backend can be split into three main sub-systems:
135
135
136
136
1. Request Processor - receives queries, adds metadata and sends it to the rest of the system
137
-
2. Data Processor - converts the data from an stream and matches it against queries
137
+
2. Data Processor - reads data from a input stream, converts it to an unified data format and matches it against queries
138
138
3. Combiner - combines results for different queries, performs final aggregations and returns results
0 commit comments