普通事务ITransactionalSpout实例

[size=large]1、普通事务Spout[/size]


/**
* 普通事务Spout
*/
public class MyTxSpout implements ITransactionalSpout<MyMata>{


private static final long serialVersionUID = 1L;


/**
* 数据源
*/
Map<Long, String> dbMap = null;
public MyTxSpout()
{
Random random = new Random();
dbMap = new HashMap<Long, String> ();
String[] hosts = { "www.taobao.com" };
String[] session_id = { "ABYH6Y4V4SCVXTG6DPB4VH9U123", "XXYH6YCGFJYERTT834R52FDXV9U34", "BBYH61456FGHHJ7JL89RG5VV9UYU7",
"CYYH6Y2345GHI899OFG4V9U567", "VVVYH6Y4V4SFXZ56JIPDPB4V678" };
String[] time = { "2014-01-07 08:40:50", "2014-01-07 08:40:51", "2014-01-07 08:40:52", "2014-01-07 08:40:53",
"2014-01-07 09:40:49", "2014-01-07 10:40:49", "2014-01-07 11:40:49", "2014-01-07 12:40:49" };

for (long i = 0; i < 100; i++) {
dbMap.put(i,hosts[0]+"\t"+session_id[random.nextInt(5)]+"\t"+time[random.nextInt(8)]);
}
}



public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("tx","log"));
}

public Map<String, Object> getComponentConfiguration() {
return null;
}

public org.apache.storm.transactional.ITransactionalSpout.Coordinator<MyMata> getCoordinator(Map conf,
TopologyContext context) {
/**
* 发射该metadata(事务tuple)到“batch emit”流
*/
return new MyCoordinator();
}

public org.apache.storm.transactional.ITransactionalSpout.Emitter<MyMata> getEmitter(Map conf,
TopologyContext context) {
/**
* 逐个发射实际batch的tuple
*/
return new MyEmitter(dbMap);
}

}


[size=large]2、事务Spout创建一个新的事务(元数据)metadata[/size]
[b]2、1元数据定义[/b]

public class MyMata implements Serializable{

/**
* metadata(元数据)中包含当前事务可以从哪个point进行重放数据,存放在zookeeper中的,spout可以通过Kryo从zookeeper中序列化和反序列化该元数据。
*/
private static final long serialVersionUID = 1L;

private long beginPoint ;//事务开始位置

private int num ;//batch 的tuple个数
@Override
public String toString() {
return getBeginPoint()+"----"+getNum();
}

public long getBeginPoint() {
return beginPoint;
}

public void setBeginPoint(long beginPoint) {
this.beginPoint = beginPoint;
}

public int getNum() {
return num;
}

public void setNum(int num) {
this.num = num;
}


}



[b]2、2 获得(元数据)metadata,逐个发射实际batch的tuple[/b]


public class MyEmitter implements ITransactionalSpout.Emitter<MyMata> {

Map<Long, String> dbMap = null;

public MyEmitter(Map<Long, String> dbMap) {
this.dbMap = dbMap;
}

//逐个发射实际batch的tuple
public void emitBatch(TransactionAttempt tx, MyMata coordinatorMeta, BatchOutputCollector collector) {

long beginPoint = coordinatorMeta.getBeginPoint();// 从上一个批次获得开始位置

int num = coordinatorMeta.getNum();// 从批次中获取批次数量

for (long i = beginPoint; i < num + beginPoint; i++) {
if (dbMap.get(i) == null) {
continue;
}
collector.emit(new Values(tx, dbMap.get(i)));
}

}

public void cleanupBefore(BigInteger txid) {

}

public void close() {

}

}


[size=x-large]3、事务Bolt,会从Emitter接收数据处理,处理完成,提交给finishBatch方法处理。[/size]


/**
* 事务Bolt
*/
public class MyTransactionBolt extends BaseTransactionalBolt {

private static final long serialVersionUID = 1L;

public void prepare(Map conf, TopologyContext context, BatchOutputCollector collector, TransactionAttempt id) {
this.collector = collector;
System.err.println("MyTransactionBolt prepare " + id.getTransactionId() + " attemptid" + id.getAttemptId());
}

Integer count = 0;
BatchOutputCollector collector;
TransactionAttempt tx;

// 会从Emitter接收数据处理,处理完成,提交给finishBatch方法处理。
public void execute(Tuple tuple) {
tx = (TransactionAttempt) tuple.getValue(0);
System.err.println(
"MyTransactionBolt TransactionAttempt " + tx.getTransactionId() + " attemptid" + tx.getAttemptId());
String log = tuple.getString(1);
if (log != null && log.length() > 0) {
count++;
}
}

// 批处理提交
public void finishBatch() {
System.err.println("finishBatch " + count);
collector.emit(new Values(tx, count));
}

public void declareOutputFields(OutputFieldsDeclarer declarer) {

declarer.declare(new Fields("tx", "count"));

}

}



[size=large]4、Icommitter,batch之间强制按照顺序进行提交[/size]


public class MyCommitter extends BaseTransactionalBolt implements ICommitter {

/**
* 接口Icommitter:标识IBatchBolt 或BaseTransactionalBolt是否是一个committer
*/
private static final long serialVersionUID = 1L;
public static final String GLOBAL_KEY = "GLOBAL_KEY";
public static Map<String, DbValue> dbMap = new HashMap<String, DbValue>();
int sum = 0;
TransactionAttempt id;
BatchOutputCollector collector;

public void execute(Tuple tuple) {
sum += tuple.getInteger(1);
}

public void finishBatch() {

DbValue value = dbMap.get(GLOBAL_KEY);
DbValue newValue;
if (value == null || !value.txid.equals(id.getTransactionId())) {
// 更新数据库
newValue = new DbValue();
newValue.txid = id.getTransactionId();
if (value == null) {
newValue.count = sum;
} else {
newValue.count = value.count + sum;
}
dbMap.put(GLOBAL_KEY, newValue);
} else {
newValue = value;
}
System.err.println("total==========================:" + dbMap.get(GLOBAL_KEY).count);
// collector.emit(tuple)
}

public void prepare(Map conf, TopologyContext context, BatchOutputCollector collector, TransactionAttempt id) {
this.id = id;
this.collector = collector;
}

public void declareOutputFields(OutputFieldsDeclarer declarer) {

}

public static class DbValue {
BigInteger txid;
int count = 0;
}

}


[size=large]5、topo类[/size]


public class MyTopo {

/**
* 事务topo
*/
public static void main(String[] args) {

TransactionalTopologyBuilder builder = new TransactionalTopologyBuilder("ttbId", "spoutid", new MyTxSpout(), 1);
builder.setBolt("bolt1", new MyTransactionBolt(), 3).shuffleGrouping("spoutid");
builder.setBolt("committer", new MyCommitter(), 1).shuffleGrouping("bolt1");

Config conf = new Config();
conf.setDebug(true);

if (args.length > 0) {
try {
StormSubmitter.submitTopology(args[0], conf, builder.buildTopology());
} catch (AlreadyAliveException e) {
e.printStackTrace();
} catch (InvalidTopologyException e) {
e.printStackTrace();
} catch (AuthorizationException e) {
e.printStackTrace();
}
} else {
LocalCluster localCluster = new LocalCluster();
localCluster.submitTopology("mytopology", conf, builder.buildTopology());
}

}

}



[size=large]6、测试结果[/size]
[quote]
启动一个事务:0----10
MyTransactionBolt prepare 1 attemptid3005464965348344518
MyTransactionBolt prepare 1 attemptid3005464965348344518
MyTransactionBolt TransactionAttempt 1 attemptid3005464965348344518
MyTransactionBolt prepare 1 attemptid3005464965348344518
MyTransactionBolt TransactionAttempt 1 attemptid3005464965348344518
MyTransactionBolt TransactionAttempt 1 attemptid3005464965348344518
MyTransactionBolt TransactionAttempt 1 attemptid3005464965348344518
MyTransactionBolt TransactionAttempt 1 attemptid3005464965348344518
MyTransactionBolt TransactionAttempt 1 attemptid3005464965348344518
finishBatch 3
MyTransactionBolt TransactionAttempt 1 attemptid3005464965348344518
MyTransactionBolt TransactionAttempt 1 attemptid3005464965348344518
MyTransactionBolt TransactionAttempt 1 attemptid3005464965348344518
MyTransactionBolt TransactionAttempt 1 attemptid3005464965348344518
finishBatch 4
finishBatch 3
total==========================:10
启动一个事务:10----10
MyTransactionBolt prepare 2 attemptid4420908201582652570
MyTransactionBolt prepare 2 attemptid4420908201582652570
MyTransactionBolt prepare 2 attemptid4420908201582652570
MyTransactionBolt TransactionAttempt 2 attemptid4420908201582652570
MyTransactionBolt TransactionAttempt 2 attemptid4420908201582652570
MyTransactionBolt TransactionAttempt 2 attemptid4420908201582652570
MyTransactionBolt TransactionAttempt 2 attemptid4420908201582652570
MyTransactionBolt TransactionAttempt 2 attemptid4420908201582652570
MyTransactionBolt TransactionAttempt 2 attemptid4420908201582652570
MyTransactionBolt TransactionAttempt 2 attemptid4420908201582652570
MyTransactionBolt TransactionAttempt 2 attemptid4420908201582652570
MyTransactionBolt TransactionAttempt 2 attemptid4420908201582652570
finishBatch 3
MyTransactionBolt TransactionAttempt 2 attemptid4420908201582652570
finishBatch 4
finishBatch 3
total==========================:20[/quote]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis事务在Java中的实例可以通过使用Jedis来实现。Jedis是一个流行的Java Redis客户端库,它提供了许多与Redis交互的方法和功能。在使用Jedis执行Redis事务时,我们可以按照以下步骤进行操作: 1. 首先,我们需要创建Jedis实例,连接到Redis服务器。 2. 使用Jedis的multi方法开始事务,该方法用于开启一个新的事务块。 3. 在事务块中,我们可以使用Jedis的各种命令,例如set、get、incr等,来执行我们需要的Redis操作。 4. 当我们完成所有的操作后,使用Jedis的exec方法来提交事务。 5. 如果在事务执行过程中出现了错误,事务会继续执行其他命令,而不会终止。因此,我们需要在执行事务后检查错误,并根据需要进行处理。 下面是一个简单的Java代码示例,演示了如何使用Jedis执行Redis事务: ```java import redis.clients.jedis.Jedis; import redis.clients.jedis.Response; import redis.clients.jedis.Transaction; public class RedisTransactionExample { public static void main(String[] args) { // 创建Jedis实例,连接到Redis服务器 Jedis jedis = new Jedis("localhost"); // 开始事务 Transaction transaction = jedis.multi(); // 在事务中执行Redis操作 transaction.set("key1", "value1"); transaction.set("key2", "value2"); transaction.incr("counter"); // 提交事务 transaction.exec(); // 获取事务执行后的结果 System.out.println(jedis.get("key1")); System.out.println(jedis.get("key2")); System.out.println(jedis.get("counter")); // 关闭Jedis连接 jedis.close(); } } ``` 在上面的示例中,我们使用Jedis的multi方法开始事务,然后分别执行了set、incr等Redis操作,最后使用exec方法提交事务。在提交事务后,我们可以通过get方法获取事务执行后的结果。请注意,事务的执行是原子的,要么全部成功,要么全部失败。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【Redis缓存机制】详解Java连接Redis_Jedis_事务](https://download.csdn.net/download/weixin_38548434/12789789)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Redis之Redis的事务](https://blog.csdn.net/weixin_32208021/article/details/114468607)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值