1、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,它主要提供了2个方面的好处:
(1)提供了更高层次的抽象,将常用的count,sum等封装成了方法,可以直接调用,不需要自己实现。
(2)提供了一次原语,如groupby等。
(3)提供了事务支持,可以保证数据均处理且只处理了一次。
2、trident每次处理消息均为batch为单位,即一次处理多个元组。
3、事务类型
关于事务类型,有2个比较容易混淆的概念:spout的事务类型以及事务状态。
它们都有3种类型,分别为:事务型、非事务型和透明事务型。
(1)spout
spout的类型指定了由于下游出现问题导致元组需要重放时,应该怎么发送元组。
事务型spout:重放时能保证同一个批次发送同一批元组。可以保证每一个元组都被发送且只发送一个,且同一个批次所发送的元组是一样的。
非事务型spout:没有任何保障,发完就算。
透明事务型spout:同一个批次发送的元组有可能不同的,它可以保证每一个元组都被发送且只发送一次,但不能保证重放时同一个批次的数据是一样的。这对于部分失效的情况尤其有用,假如以kafka作为spout,当一个topic的某个分区失效时,可以用其它分区的数据先形成一个批次发送出去,如果是事务型spout,则必须等待那个分区恢复后才能继续发送。
这三种类型可以分别通过实现ITransactionalSpout、ITridentSpout、IOpaquePartitionedTridentSpout接口来定义。
(2)state
state的类型指定了如果将storm的中间输出或者最终输出持久化到某个地方(如内存),当某个批次的数据重放时应该如果更新状态。state对于下游出现错误的情况尤其有用。
事务型状态:同一批次tuple提供的结果是相同的。
非事务型状态:没有回滚能力,更新操作是永久的。
透明事务型状态:更新操作基于先前的值,这样由于这批数据发生变化,对应的结果也会发生变化。透明事务型状态除了保存当前数据外,还要保存上一批数据,当数据重放时,可以基于上一批数据作更新。
4.trident的Demo
package com.stone.trident.filter; import org.apache.storm.trident.operation.BaseFilter; import org.apache.storm.trident.tuple.TridentTuple; /** * 过滤函数 * * @author fangyuanjie * @version 1.0.0 */ public class CheckEvenSumFilter extends BaseFilter { private static final long serialVersionUID = 1L; @Override public boolean isKeep(TridentTuple tuple) { Integer a = tuple.getInteger(0); Integer b = tuple.getInteger(1); int sum = a + b; System.out.println("CheckEvenSumFilter : " + sum); if (sum % 2 == 0) { return true; } return false; } } package com.stone.trident.function; import org.apache.storm.trident.operation.BaseFunction; import org.apache.storm.trident.operation.TridentCollector; import org.apache.storm.trident.tuple.TridentTuple; import org.apache.storm.tuple.Values; /** * 求和函数 * * @author fangyuanjie * @version 1.0.0 */ public class SumFunction extends BaseFunction { private static final long serialVersionUID = 1L; @Override public void execute(TridentTuple tuple, TridentCollector collector) { int sum = tuple.getInteger(0) + tuple.getInteger(1); System.out.println("SumFunction : " + sum); collector.emit(new Values(sum)); } } package com.stone.trident.topology; import com.google.common.collect.ImmutableList; import com.stone.trident.filter.CheckEvenSumFilter; import com.stone.trident.function.SumFunction; import org.apache.storm.Config; import org.apache.storm.LocalCluster; import org.apache.storm.trident.Stream; import org.apache.storm.trident.TridentTopology; import org.apache.storm.trident.testing.FeederBatchSpout; import org.apache.storm.tuple.Fields; import org.apache.storm.tuple.Values; import java.util.HashMap; import java.util.Map; /** * Trident Demo * * @author fangyuanjie * @version 1.0.0 */ public class TridentDemoTopology { public static void main(String[] args) throws Exception { TridentTopology top = new TridentTopology(); //创建spout FeederBatchSpout testSpout = new FeederBatchSpout( ImmutableList.of("a", "b", "c", "d")); Stream s = top.newStream("spout", testSpout); s.shuffle().each(new Fields("a", "b"), new CheckEvenSumFilter()) .each(new Fields("a", "b", "c", "d"), new SumFunction(), new Fields("sum")) .parallelismHint(2); Config config = new Config(); Map<String, String> map = new HashMap<>(); map.put("storm.zookeeper.servers", "127.0.0.1"); config.setEnvironment(map); LocalCluster cluster = new LocalCluster(); cluster.submitTopology("trident1", config, top.build()); //模拟发送数据 testSpout.feed(ImmutableList.of(new Values(1, 2, 3, 4))); testSpout.feed(ImmutableList.of(new Values(2, 2, 3, 4))); testSpout.feed(ImmutableList.of(new Values(2, 3, 4, 5))); testSpout.feed(ImmutableList.of(new Values(4, 4, 5, 6))); Thread.sleep(10000); cluster.shutdown(); } }