trident原理及编程指南

Trident是Storm的高级抽象,提供高吞吐、状态ful的实时流处理和低延迟分布式查询。它包括批处理、事务支持,确保一致性和恰好一次的语义。本文介绍了Trident的理论概念,如事务类型、处理单位,以及编程指南,包括从Kafka读取数据和使用State进行状态管理。示例展示了如何实现WordCount统计,以及如何利用State保证数据的正确性。
摘要由CSDN通过智能技术生成

trident原理及编程指南

@(STORM)[storm, 大数据]

一、理论介绍

(一)trident是什么?

Trident is a high-level abstraction for doing realtime computing on top of Storm. It allows you to seamlessly intermix high throughput (millions of messages per second), stateful stream processing with low latency distributed querying. If you’re familiar with high level batch processing tools like Pig or Cascading, the concepts of Trident will be very familiar – Trident has joins, aggregations, grouping, functions, and filters. In addition to these, Trident adds primitives for doing stateful, incremental processing on top of any database or persistence store. Trident has consistent, exactly-once semantics, so it is easy to reason about Trident topologies.
简单的说,trident是storm的更高层次抽象,相对storm,它主要提供了3个方面的好处:
(1)提供了更高层次的抽象,将常用的count,sum等封装成了方法,可以直接调用,不需要自己实现。
(2)以批次代替单个元组,每次处理一个批次的数据。
(3)提供了事务支持,可以保证数据均处理且只处理了一次。

(二)trident处理单位

trident每次处理消息均为batch为单位,即一次处理多个元组。

(三)事务类型

关于事务类型,有2个比较容易混淆的概念:spout的事务类型以及事务状态。
它们都有3种类型,分别为:事务型、非事务型和透明事务型。

1、spout类型

spout的类型指定了由于下游出现问题(fail被调用,或者超时无回复)导致元组需要重放时,应该怎么发送元组。
事务型spout:重放时能保证同一个批次发送同一批元组。可以保证每一个元组都被发送且只发送一个,且同一个批次所发送的元组是一样的。
非事务型spout:没有任何保障,发完就算。
透明事务型spout:同一个批次发送的元组有可能不同的,它可以保证每一个元组都被发送且只发送一次,但不能保证重放时同一个批次的数据是一样的。这对于部分失效的情况尤其有用,假如以kafka作为spout,当一个topic的某个分区失效时,可以用其它分区的数据先形成一个批次发送出去,如果是事务型spout,则必须等待那个分区恢复后才能继续发送。
这三种类型可以分别通过实现ITransactionalSpout、ITridentSpout、IOpaquePartitionedTridentSpout接口来定义。

2、state类型

state的类型指定了如果将storm的中间输出或者最终输出持久化到某个地方(如内存),当某个批次的数据重放时应该如果更新状态。state对于下游出现错误的情况尤其有用。
事务型状态:同一批次tuple提供的结果是相同的。
非事务型状态:没有回滚能力,更新操作是永久的。
透明事务型状态:更新操作基于先前的值,这样由于这批数据发生变化,对应的结果也会发生变化。透明事务型状态除了保存当前数据外,还要保存上一批数据,当数据重放时,可以基于上一批数据作更新。
注意,此处的状态应该是原子性的,比如将状态写入hbase,则应该全部写入,或者全部没写入,不能说写入一半,另一半没写入,这连事务型也无法保证恰好一次了。比如说写入本地磁盘,就有可能导致这种情况,如果写到一半出错,则无法保证恰好一次了,因为磁盘没有类似于数据库的commit、rollback操作。

3、实现恰好一次的spout与state组合类型

image
由上表可以看出:
(1)当spout与state均为transcational或者均为opaque时,可以实现恰好一次。
(2)当spout为tansactional,state为opaque时,也可以实现恰好一次。
(3)但当spout为opaque,state为transactional时,不可以实现恰好一次。因此opaque spout重发时,它的内容可能与上一次不同,而state如果在上个批次已经更新过但这个批次最终fail了,则spout重发时,会在已经fail掉的批次上更新,而上一个批次是不应该计算在内的。如果state是transactional的,则它同时保存了上一次状态及当前状态,所以可以基于上一次的状态作更新,就不会有这个问题。

二、编程指南

代码如下

package org.ljh.tridentdemo;

import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.LocalDRPC;
import backtype.storm.StormSubmitter;
import backtype.storm.generated.StormTopology;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Values;
import storm.trident.TridentState;
import storm.trident.TridentTopology;
import storm.trident.operation.BaseFunction;
import storm.trident.operation.TridentCollector;
import storm.trident.operation.builtin.Count;
import storm.trident.operation.builtin.FilterNull;
import storm.trident.operation.builtin.MapGet;
import storm.trident.operation.builtin.Sum;
import storm.trident.testing.FixedBatchSpout;
import storm.trident.testing.MemoryMapState;
import storm.trident.tuple.TridentTuple;


public class TridentWordCount {
    public static class Split extends BaseFunction {
        @Override
        public void execute(TridentTuple tuple, TridentCollector collector) {
            String sentence = tuple.getString(0);
            for (String word : sentence.split(" ")) {
                collector.emit(new Values(word));
            }
        }
    }

    public static StormTopology buildTopology(LocalDRPC drpc) {
        FixedBatchSpout spout =
                new FixedBatchSpout(new Fields("sentence"), 3, new Values(
                        "the cow jumped over the moon"), new Values(
                        "the man went to the store and bought some candy"), new Values(
                        "four score and seven years ago"),
                        new Values("how many apples can you eat"), new Values(
                                "to be or not to be the person"));
        spout.setCycle(true);

        //创建拓扑对象
        TridentTopology topology = new TridentTopology();

        //这个流程用于统计单词数据,结果将被保存在wordCounts中
        TridentState wordCounts =
                topology.newStream("spout1", spout)
                        .parallelismHint(16)
                        .each(new Fields("sentence"), new Split(), new Fields("word"))
                        .groupBy(new Fields("word"))
                        .persistentAggregate(new MemoryMapState.Factory(), new Count(),
                                new Fields("count")).parallelismHint(16);
        //这个流程用于查询上面的统计结果
        topology.newDRPCStream("words", drpc)
                .each(new Fields("args"), new Split(), new Fields("word"))
                .g
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值