storm记录--12- Storm Transaction 原理+实战

Storm实时计算框架核心原理与金融风控实战 分布式实时计算系统通过流式数据处理技术实现毫秒级响应,其核心原理在于持续计算模型和主从式架构设计。以Storm为代表的框架采用Spout-Bolt拓扑结构和ZooKeeper协调机制,支持高可用与灵活的计算逻辑组合。在金融风控等实时性要求高的场景中,Storm与Kafka、Redis等技术栈形成黄金组合,可显著提升欺诈交易识别效率。典型应用还包括物联网监控、电商推荐等需要低延迟处理的领域,通过规则引擎热加载和状态管理优化实现业务价值。 阅读详情

Storm guarantees data processing by providing an at least once processing guarantee. The most common question asked about Storm is "Given that tuples can be replayed, how do you do things like counting on top of Storm? Won't you overcount?"

Storm 0.7.0 introduces transactional topologies, which enable you to get exactly once messaging semantics for pretty much any computation. So you can do things like counting in a fully-accurate, scalable, and fault-tolerant way.

Storm默认的reliable特性支持at least once processing guarantee.      
这个在某些场景下明显是不够的, 比如计数, 不断的replay必然导致计数不准, 那么需要支持exactly once semantics.

Storm 0.7就提供transactional topology特性来支持, 其实这个和DRPC一样, Storm只是提供一种特殊的topology的封装, 当然transactional topology更复杂.

Design 

Design 1

这里说transactional topologies为了提供strong ordering, 这个要求是要强于之前说的exactly once semantics.

对于每个transaction有唯一的transaction id来标识, 对于第一种design, 每个transaction就是一个tuple      
拿计数作为例子, 每个tuple产生的number, 最终需要累加到数据库里面      
不使用transactional, 重复replay一个tuple, 必然会导致该tuple的number被反复累加到数据库

怎么处理? 其实想法很简单, 引入transaction的概念, 并在累加number到数据库的同时记下该transactioin id.     
这样如果replay该tuple, 只需要对比transaction id就知道该transaction已经累加过, 可以直接ignore

看到这里, 就知道保持strong ordering的重要性, 强顺序意味着, 如果当前的transaction失败, 会反复被replay, 直到成功才继续下一个transaction.     
这意味着, 在数据库我们只需要记录latest的transaction id, 而不是累加过的所有transaction id, 实现上会简单许多.

但是design1的问题是效率太低, 完全线性的处理tuple, 无法利用storm的并发能力, 而且数据库的负载很高, 每个tuple都需要去操作数据库

The core idea behind transactional topologies is to provide a strong ordering on the processing of data.     
The simplest manifestation of this, and the first design we'll look at, is processing the tuples one at a time and not moving on to the next tuple until the current tuple has been successfully processed by the topology.

Each tuple is associated with a transaction id. If the tuple fails and needs to be replayed, then it is emitted with the exact same transaction id. A transaction id is an integer that increments for every tuple, so the first tuple will have transaction id 1, the second id 2, and so on. 

There is a significant problem though with this design of processing one tuple at time. Having to wait for each tuple to be completely processed before moving on to the next one is horribly inefficient. It entails a huge amount of database calls (at least one per tuple), and this design makes very little use of the parallelization capabilities of Storm. So it isn't very scalable.  

Design 2

Design2的想法很简单, 用batch tuple来作为transaction的单位, 而不是一个tuple.     
这样带来的好处是, batch内部的tuple可以实现并行, 并且以batch为单位去更新数据库, 大大减少数据库负载.      
但本质上和Design1没有区别, batch之间仍然是串行的, 所以效率仍然比较低

Instead of processing one tuple at a time, a better approach is to process a batch of tuples for each transaction.    
So if you're doing a global count, you would increment the count by the number of tuples in the entire batch. If a batch fails, you replay the exact batch that failed.     
Instead of assigning a transaction id to each tuple, you assign a transaction id to each batch, and the processing of the batches is strongly ordered. Here's a diagram of this design:

image   

Design 3 (Storm's design)

这个设计体现出storm的创意, 将topology的过程分为processing和commit, processing就是进行局部的计算和统计, 只有commit时才会把计算的结果更新到全局数据集(数据库)     
那么对于processing阶段完全没有必要限制, 只要保证在commit的时候按照顺序一个个commit就ok.

比如对于计数, 不同的batch的局部计数过程没有任何限制, 可以完全并行的完成, 但是当需要将计数结果累加到数据库的时候, 就需要用transaction来保证只被累加一次

processing和commit阶段合称为transaction, 任何阶段的失败都会replay整个transaction

A key realization is that not all the work for processing batches of tuples needs to be strongly ordered. For example, when computing a global count, there's two parts to the computation:

  1. Computing the partial count for the batch 

  2. Updating the global count in the database with the partial count 

The computation of #2 needs to be strongly ordered across the batches, but there's no reason you shouldn't be able to pipeline the computation of the batches by computing #1 for many batches in parallel. So while batch 1 is working on updating the database, batches 2 through 10 can compute their partial counts.

Storm accomplishes this distinction by breaking the computation of a batch into two phases:

  1. The processing phase: this is the phase that can be done in parallel for many batches 

  2. The commit phase: The commit phases for batches are strongly ordered. So the commit for batch 2 is not done until the commit for batch 1 has been successful. 

The two phases together are called a "transaction".     
Many batches can be in the processing phase at a given moment, but only one batch can be in the commit phase.     
If there's any failure in the processing or commit phase for a batch, the entire transaction is replayed (both phases).  

Design details

为了实现上面的Design3, storm在transactional topologies里面默默的做了很多事     
管理状态, 通过Zookeeper去记录所有transaction相关的状态信息      
协调transactions, 决定应该执行那个transaction的那个阶段      
Fault检测, 使用storm acker机制来detect batch是否被成功执行, 并且storm在transactional topology上对acker机制做了比较大的优化, 用户不用自己去acking或anchoring, 方便许多      
提供batch bolt接口, 在bolt接口中提高对batch的支持, 比如提供finishbatch接口

最后, transactional topology要求source queue具有replay an exact batch的能力, 这儿说kafka是很好的选择     
不过我很好奇, 为什么要由source queue来提供batch replay的功能, 好的设计应该是batch对source queue透明, spout自身控制batch的划分和replay, 这样不可以吗?

When using transactional topologies, Storm does the following for you:

  1. Manages state: Storm stores in Zookeeper all the state necessary to do transactional topologies.       
    This includes the current transaction id as well as the metadata defining the parameters for each batch. 

  2. Coordinates the transactions: Storm will manage everything necessary to determine which transactions should be processing or committing at any point. 

  3. Fault detection: Storm leverages the acking framework to efficiently determine when a batch has successfully processed, successfully committed, or failed.   
    Storm will then replay batches appropriately. You don't have to do any acking or anchoring -- Storm manages all of this for you. 

  4. First class batch processing API: Storm layers an API on top of regular bolts to allow for batch processing of tuples.       
    Storm manages all the coordination for determining when a task has received all the tuples for that particular transaction.       
    Storm will also take care of cleaning up any accumulated state for each transaction (like the partial counts). 

Finally, another thing to note is that transactional topologies require a source queue that can replay an exact batch of messages. Technologies like Kestrel can't do this. Apache Kafka is a perfect fit for this kind of spout, and storm-kafka in storm-contrib contains a transactional spout implementation for Kafka. 

The basics through example

You build transactional topologies by using TransactionalTopologyBuilder. Here's the transactional topology definition for a topology that computes the global count of tuples from the input stream. This code comes from TransactionalGlobalCount in storm-starter.

MemoryTransactionalSpout spout = new MemoryTransactionalSpout(DATA, new Fields("word"), PARTITION_TAKE_PER_BATCH);TransactionalTopologyBuilder builder = new TransactionalTopologyBuilder("global-count", "spout", spout, 3);builder.setBolt("partial-count", new BatchCount(), 5)        .shuffleGrouping("spout");builder.setBolt("sum", new UpdateGlobalCount())        .globalGrouping("partial-count");

首先需要使用TransactionalSpout, MemoryTransactionalSpout被用来从一个内存变量里面读取数据(DATA), 第二个参数制定数据的fields, 第三个参数指定每个batch的最大tuple数量    
接着, 需要使用TransactionalTopologyBuilder, 其他和普通的topology看上去没有不同, storm的封装做的很好

下面通过processing和commit阶段的bolt来了解对batch和transaction的支持 

首先看看BatchCount, processing阶段的bolt, 用于统计局部的tuple数目

public static class BatchCount extends BaseBatchBolt {    Object _id;    BatchOutputCollector _collector;        int _count = 0;    @Override    public void prepare(Map conf, TopologyContext context, BatchOutputCollector collector, Object id) {        _collector = collector;        _id = id;       }    @Override    public void execute(Tuple tuple) {        _count++;    }    @Override    public void finishBatch() {        _collector.emit(new Values(_id, _count));    }    @Override    public void declareOutputFields(OutputFieldsDeclarer declarer) {        declarer.declare(new Fields("id", "count"));    }}

BatchCount继承自BaseBatchBolt, 表明其对batch的支持, 主要反应在finishBatch函数, 而普通的bolt的不同在于, 只有在finishBatch的时候才会去emit结果, 而不是每次execute都emit结果    
在prepare时, 多出个id, a 
TransactionAttempt object, 并且从output定义看出, 所有emit的tuple第一个参数必须是id(TransactionAttempt)

The TransactionAttempt contains two values: the "transaction id" and the "attempt id"(表示被replay次数).    
The "transaction id" is the unique id chosen for this batch and is the same no matter how many times the batch is replayed.     
The "attempt id" is a unique id for this particular batch of tuples and lets Storm distinguish tuples from different emissions of the same batch. Without the attempt id, Storm could confuse a replay of a batch with tuples from a prior time that batch was emitted.

All tuples emitted within a transactional topology must have the TransactionAttempt as the first field of the tuple. This lets Storm identify which tuples belong to which batches. So when you emit tuples you need to make sure to meet this requirement.

其实这里的BaseBatchBolt, 是通用的batch基类, 也可以用于其他的需要batch支持的场景, 比如DRPC, 只不过此处的id类型变为RPC id    
如果只是要support tansactional topology场景, 可以直接使用BaseTransactionalBolt

public abstract class BaseTransactionalBolt                            extends BaseBatchBolt<TransactionAttempt> {   }

继续看, commit阶段的bolt, UpdateGlobalCount, 将统计的结果累加到全局数据库中

UpdateGlobalCount之间继承自BaseTransactionalBolt, 所以此处prepare的参数直接是TransactionAttempt attempt(而不是object id)    
并且比较重要的是实现ICommitter接口, 表明这个bolt是个commiter, 意味着这个blot的finishBatch函数需要在commit阶段被调用

另一种把bolt标识为committer的方法是, 在topology build的时候使用setCommitterBolt来替代setBolt

First, notice that this bolt implements the ICommitter interface. This tells Storm that the finishBatch method of this bolt should be part of the commit phase of the transaction.   
So calls to finishBatch for this bolt will be strongly ordered by transaction id (calls to execute on the other hand can happen during either the processing or commit phases).   
An alternative way to mark a bolt as a committer is to use the setCommitterBolt method in TransactionalTopologyBuilder instead of setBolt.

public static class UpdateGlobalCount           extends BaseTransactionalBolt           implements ICommitter {    TransactionAttempt _attempt;    BatchOutputCollector _collector;     int _sum = 0;     @Override    public void prepare(Map conf,                        TopologyContext context,                        BatchOutputCollector collector,                        TransactionAttempt attempt) {        _collector = collector;        _attempt = attempt;    }     @Override    public void execute(Tuple tuple) {        _sum+=tuple.getInteger(1);    }     @Override    public void finishBatch() {        Value val = DATABASE.get(GLOBAL_COUNT_KEY);        Value newval;        if(val == null ||                !val.txid.equals(_attempt.getTransactionId())) {            newval = new Value();            newval.txid = _attempt.getTransactionId();            if(val==null) {                newval.count = _sum;            } else {                newval.count = _sum + val.count;            }            DATABASE.put(GLOBAL_COUNT_KEY, newval);        } else {            newval = val;        }        _collector.emit(new Values(_attempt, newval.count));    }     @Override    public void declareOutputFields(OutputFieldsDeclarer declarer) {        declarer.declare(new Fields("id", "sum"));    }}

storm会保证commiter里面的finishBatch被顺序执行, 并且在finishBatch里面, 需要check transaction id, 确保只有新的transaction的结果才被更新到全局数据库.

The code for finishBatch in UpdateGlobalCount gets the current value from the database and compares its transaction id to the transaction id for this batch. If they are the same, it does nothing. Otherwise, it increments the value in the database by the partial count for this batch.

A more involved transactional topology example that updates multiple databases idempotently can be found in storm-starter in the TransactionalWords class. 

Transactional Topology API

Bolts

There are three kinds of bolts possible in a transactional topology:

  1. BasicBolt: This bolt doesn't deal with batches of tuples and just emits tuples based on a single tuple of input. 

  2. BatchBolt: This bolt processes batches of tuples. execute is called for each tuple, and finishBatch is called when the batch is complete. 

  3. BatchBolt's that are marked as committers: The only difference between this bolt and a regular batch bolt is when finishBatch is called. A committer bolt has finishedBatch called during the commit phase. The commit phase is guaranteed to occur only after all prior batches have successfully committed, and it will be retried until all bolts in the topology succeed the commit for the batch. 

上面列出可能遇到的3种bolt, 下面的例子给出不同blot的区别,

image 

红线标出的都是commiter, 这里有两个commiter, 分别是B和D    
A的输出分别输出到B和C    
B可以先执行execute(processing), 但不能直接执行finishBatch, 因为需要等待storm调度, 必须等前面的batch commit完后, 才能进行commit    
所以C也无法立刻执行finishBatch, 因为需要等从B过来的tuple    
对于D, 原文说它会在commit阶段接收所有的batch tuple, 所以可以直接commit, 这个怎么保证? 

Notice that even though Bolt D is a committer, it doesn't have to wait for a second commit message when it receives the whole batch. Since it receives the whole batch during the commit phase, it goes ahead and completes the transaction.

Committer bolts act just like batch bolts during the commit phase.   
The only difference between committer bolts and batch bolts is that committer bolts will not call finishBatch during the processing phase of a transaction.

Acking

Notice that you don't have to do any acking or anchoring when working with transactional topologies. Storm manages all of that underneath the hood. The acking strategy is heavily optimized.

 

Failing a transaction

由于封装的比较好, 不需要用户去ack或fail tuple, 那么怎么去fail一个batch?     
抛出
FailedException, Storm捕获这个异常会replay Batch, 而不会crash    
When using regular bolts, you can call the fail method on OutputCollector to fail the tuple trees of which that tuple is a member.   
Since transactional topologies hide the acking framework from you, they provide a different mechanism to fail a batch (and cause the batch to be replayed).  
Just throw a FailedException. Unlike regular exceptions, this will only cause that particular batch to replay and will not crash the process. 

Transactional spout

Transactional spout和普通的spout完全不同的实现, 本身就是一个mini的topology, 分为coordinator spout和emitter bolt    
The TransactionalSpout interface is completely different from a regular Spout interface. A TransactionalSpout implementation emits batches of tuples and must ensure that the same batch of tuples is always emitted for the same transaction id.

A transactional spout looks like this while a topology is executing:

Storm cluster

The coordinator on the left is a regular Storm spout that emits a tuple whenever a batch should be emitted for a transaction. The emitters execute as a regular Storm bolt and are responsible for emitting the actual tuples for the batch. The emitters subscribe to the "batch emit" stream of the coordinator using an all grouping.

The need to be idempotent with respect to the tuples it emits requires a TransactionalSpout to store a small amount of state. The state is stored in Zookeeper. 

下面是transactional spout的工作流程,    
首先coordinator spout只会有一个task, 并会产生两种stream, batch stream和commit stream    
它会决定何时开始某transaction processing阶段, 此时就往batch stream里面发送包含TransactionAttempt的tuple    
它也决定何时开始某transaction commit阶段(当通过acker知道processing阶段已经完成的时候, 并且所有prior transaction都已经被commit), 此时就往commit steam里面发送一个包含TransactionAttempt的tuple作为通知, 所有commtting bolt都会预订(通过setBolt的all grouping方式)commit stream, 并根据收到的通知完成commit阶段.    
对于commit阶段和processing阶段一样, 通过acker来判断是成功还是fail, 前面说了transactional topology对acker机制做了较大的优化, 所以所有acking和anchoring都由storm自动完成了.

对于emitter bolt, 可以并发的, 并且以all grouping的方式订阅coordinator的batch stream, 即所有emitter都会得到一样的batch stream, 使用几个emitter取决于场景.    
对于topology而言, emitter bolt是真正产生数据的地方, 当coordinator开始某batch的processing过程, 并往batch steam放tuple数据时, emitter bolt就会从batch stream收到数据, 并转发给topology
 

Here's how transactional spout works:

  1. Transactional spout is a subtopology consisting of a coordinator spout and an emitter bolt 

  2. The coordinator is a regular spout with a parallelism of 1 

  3. The emitter is a bolt with a parallelism of P, connected to the coordinator's "batch" stream using an all grouping 

  4. When the coordinator determines it's time to enter the processing phase for a transaction, it emits a tuple containing the TransactionAttempt and the metadata for that transaction to the "batch" stream 

  5. Because of the all grouping, every single emitter task receives the notification that it's time to emit its portion of the tuples for that transaction attempt 

  6. Storm automatically manages the anchoring/acking necessary throughout the whole topology to determine when a transaction has completed the processing phase. The key here is that *the root tuple was created by the coordinator, so the coordinator will receive an "ack" if the processing phase succeeds, and a "fail" if it doesn't succeed for any reason (failure or timeout). 

  7. If the processing phase succeeds, and all prior transactions have successfully committed, the coordinator emits a tuple containing the TransactionAttempt to the "commit" stream. 

  8. All committing bolts subscribe to the commit stream using an all grouping, so that they will all receive a notification when the commit happens. 

  9. Like the processing phase, the coordinator uses the acking framework to determine whether the commit phase succeeded or not. If it receives an "ack", it marks that transaction as complete in zookeeper. 

从后面的讨论, 可以知道transactional spout的batch replay是依赖于source queue的    
比如, 对于kafka这种数据是分布在partition上的queue, 需要使用partitioned transactional spout, 用于封装对从不同partition读数据的过程
 

Partitioned Transactional Spout

A common kind of transactional spout is one that reads the batches from a set of partitions across many queue brokers. For example, this is how TransactionalKafkaSpout works. An IPartitionedTransactionalSpout automates the bookkeeping work of managing the state for each partition to ensure idempotent replayability.

对于Transactional spout, 并不会象普通tuple一样由spout缓存和负责replay, 只会记下该batch数据在source queue的位置(应该是zookeeper), 当需要replay的时候, Transactional spout会从新去source queue去读batch然后replay. 

这样的问题是过于依赖source queue, 而且会导致transaction batch无法被replay(比如由于某个partition fail) 

这个问题如何解决? 可以参考原文, 比较好的方法, 是fail当前和后续所有的transaction, 然后重新产生transaction的batch数据, 并跳过失败部分

个人决定这个设计不太好, 过于依赖source queue

为何不在spout缓存batch数据, 虽然这样对于比较大的batch可能有效率问题, 或者会限制同时处理的batch数目, 但重新从source queue读数据来replay也会有很多问题...


源自:http://www.51studyit.com/html/notes/20140329/48.html#


实时计算框架选型决策地图:Hadoop、Storm、Spark、Flink、Samza深度对比 实时计算是现代数据架构的核心能力,其本质是时间语义、状态管理与容错机制的协同设计。从批处理(Hadoop)到低延迟流式(Storm),再到统一引擎(Spark)和原生流处理(Flink),不同框架代表差异化的‘时间观’与工程权衡。Hadoop提供高吞吐存储与YARN资源调度基础;Storm以亚毫秒级响应适配事件驱动场景;Spark凭借SQL兼容性与批流双模降低开发门槛;Flink通过精确一次(exactly-once)状态一致性支撑金融级实时风控;Samza则深度绑定Kafka实现轻量状态恢复。技术选型不应 阅读详情

相关推荐

WebGIS核心服务协议全解析:WMS、WFS、WMTS、WPS实战选型指南

在WebGIS与空间数据服务领域,OGC标准协议构成了数据交互的通用语言。其核心原理在于定义了一套标准化的请求-响应契约,使客户端与服务器能高效地进行地理空间数据的传输与处理。从技术价值看,这些协议解决了地理信息在Web环境中可视化、查询、分析与分发的关键问题,是构建跨平台、可互操作地理应用的基础。具体到应用场景,动态地图渲染(WMS)适用于需要灵活样式的专题图展示;要素级数据交互(WFS)支撑着地图查询与编辑功能;预切瓦片服务(WMTS/TMS)则为高并发、高性能的地图浏览体验提供了保障;而地理处理服务(

weixin_33850015的博客 479

Storm Transaction 原理+实战

Storm guarantees data processing by providing an at least once processing guarantee. The most common question asked about Storm is "Given that tuples can be replayed, how do you do things like countin

zhangjianbo1989的专栏 1138

模型上线后48小时:MLOps实战中的稳定性、可观测性与防御性架构

机器学习模型部署不是开发终点,而是工程挑战的起点。从概念上讲,模型服务本质是嵌入业务链路的有状态组件;其核心原理在于保障输入一致性、输出可预测性与故障可兜底性;技术价值体现在将‘黑箱推理’转化为具备SLA承诺、熔断降级、全链路追踪能力的生产级服务。典型应用场景覆盖金融风控、保险核保、物流ETA等高可用要求领域,需应对特征漂移、竞态调用、重试污染、Schema演进等真实问题。本文聚焦模型上线初期的关键防御实践,涵盖元数据契约设计、五大集成故障防御、延迟业务语义化定义及漂移三级响应机制,直击‘为什么模型在测试集

wgyyh 319

Kafka系列之Stream核心原理(一)

Kafka Streams 是一个客户端库,用于处理和分析存储在 Kafka 中的数据。它建立在重要的流处理概念之上,例如正确区分事件时间和处理时间、窗口支持以及简单而高效的管理和应用程序状态的实时查询Kafka Streams入门门槛低:您可以在单机上快速编写和运行小规模的概念验证;并且您只需要在多台机器上运行应用程序的额外实例即可扩展到大批量生产工作负载。

算法小生 1339

Opencv全景图像处理实战:柱面与透视展开技术详解

本文详细解析了使用OpenCV实现全景图像处理的两种核心技术:柱面展开与透视展开。通过原理拆解与实战代码演示,指导开发者将360度环绕的鱼眼或球面图像转换为可用的平面视图,适用于街景展示、车载环视、室内测量等计算机视觉应用场景。

weixin_29081163的博客 582

保姆级教程:用YOLOv5s训练PCB缺陷检测模型(附北大公开数据集)

本文提供了一份基于YOLOv5s的PCB缺陷检测模型从零开始的完整实战教程。详细解析了如何使用北大公开数据集,涵盖环境搭建、数据处理、模型训练、性能评估及优化部署全流程,并针对工业场景中常见的类别不均衡问题给出了具体解决方案,旨在帮助开发者快速构建高精度的自动化质检系统。

weixin_28285943的博客 306

关于dhcp协议报文中的transaction ID问题

dhcp client端发送的dhcp协议报文中均携带transaction ID,dhcp server端回复client报文时,需要携带对应的transaction ID,否则将被client丢弃。

1万+

海光(hygon)CPU ESXI vSphere 紫屏问题修复记录

海光服务器ESXI 紫屏问题修复

edison202302的博客 3549

Kafka(十二)Streams

Kafka因其可靠的消息传递能力,被很多流式处理系统作为唯一可靠的数据来源。常见的流式处理系统有:从0.10.0版本开始,Kafka提供了一个强大的流式处理开发库:Kafka Streams。有了它,开发人员可以直接在程序中进行流式处理,无需再引入上述的外部处理框架。下面一起来进入Streams的世界。我们知道Kafka Streams是用来做流式处理的,那么首先要理解什么是流式处理。 首先,流式处理是一种编程范式,是指实时地处理一个或多个事件流/数据流。首先来比较以下三种常用的编程范式:那么事件流/数据流

yunyun1886358的专栏 2426

龙芯3A5000开发板PMON升级UEFI固件实战指南

固件是计算机硬件与操作系统之间的关键桥梁,负责初始化硬件并引导系统启动。其工作原理是在上电后执行自检、加载引导程序,最终将控制权移交操作系统。在国产化平台中,采用标准化的UEFI固件具有重要技术价值,它能提供图形化配置界面、统一硬件驱动模型,并支持安全启动等现代特性,从而显著提升硬件兼容性与系统管理效率。这一技术广泛应用于PC、服务器及嵌入式设备,尤其在需要运行银河麒麟等主流操作系统的龙芯开发板场景中,将传统PMON固件升级至UEFI,能实现更流畅的系统安装与更稳定的运行体验。本文基于固件升级与UEFI引导

weixin_42664597的博客 561

WorkBuddy 实战:从聊天窗口到 AI 工作台,打造个人自动化助理

大模型时代,对话式 AI 常被当作高级搜索框,难以沉淀为生产力。其根源在于上下文断裂——每次对话都从零开始。AI Agent 的核心原理是通过状态保持、工具调用与流程复用,将临时交互固化为可重复的协作机制。WorkBuddy 作为个人 AI 工作台,以 Agent + Skill + 工作流架构解决该问题:Skill 封装操作手册,工作区沉淀知识上下文,自定义指令约束输出风格。这种设计让周报生成、会议纪要、文档初稿、专利检索辅助等重复劳动实现流程化自动产出。掌握 WorkBuddy 怎么用,关键在于从自己重

weixin_33834910的博客 325

Storm记录--12- Storm Transaction 原理+实战

Stormguaranteesdataprocessingbyprovidinganatleastonceprocessingguarantee.ThemostcommonquestionaskedaboutStormis"Giventhattuplescanbereplayed,howdoyoudothingsl...

weixin_34162629的博客 141

避坑指南:你的VASP CI-NEB计算为什么不收敛?常见错误分析与解决思路

本文深入解析VASP CI-NEB计算不收敛的常见问题,提供从结构准备到参数设置的系统解决方案。针对过渡态计算中的能量曲线异常、中间图像偏离等典型问题,详细介绍了诊断方法和实用工具,帮助研究者高效解决CI-NEB收敛难题,提升计算效率。

weixin_29698641的博客 430

Storm入门教程 玩转大数据计算之Storm

Storm入门教程 玩转大数据计算之Storm 大数据分析工程师任职要求: 1.计算机、数学等相关专业,2年以上大数据分析工作经验,博士优先 2.有较强的机器学习算法理论知识,熟悉常用的一些机器学习算法,分类、回归等 3.具备良好的编程基础,至少会Python,R,等一种主流语言 4.熟悉Hadoop大数据框架及Hive、Hbase、storm等相关技术 岗位职责: 1.协助构建以工业物联网为中心...

fengliaoai的博客 1万+

详解大端模式和小端模式

详解大端模式和小端模式 一、大端模式和小端模式的起源         关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的《格利佛游记》:Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可以那时的皇帝的祖父由于小时侯吃鸡蛋,按这种方法把手指弄破了,因此他的父亲,就下令,命令

ce123的技术博客 19万+

基于 STM32 的智慧农业温室控制系统设计与实现

本文提出一种基于 STM32 微控制器的智慧农业温室控制系统设计方案,通过集成多类型环境传感器、执行机构及无线通信模块,实现对温室内温湿度、光照、土壤湿度等参数的实时监测与自动调控。文中详细阐述硬件选型、电路连接及软件实现流程,并附关键代码示例,为智慧农业领域提供低成本、高可靠性的温室控制解决方案。

weixin_42300449的博客 1923

Transaction Topology

Storm 可以­­­保证Tuple可以至少被处理一次,最常见的关于的Storm的问题是: 既然Storm可以被Replay, 那么它怎么能处理像计数统计这样的问题呢? 这样不会重复计数吗?在Storm0.7版本中提供了 transaction Topology这样的机制可以保证每个Tuple 精确的被处理一次。 本文主要阐述 transaction Topology基本概念和原理 使用tr

WakeHeart的专栏 623

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Storm - Transactional-topologies

Storm guarantees data processing by providing an at least once processing guarantee. The most common question asked about Storm is "Given that tuples can be replayed, how do you ...

weixin_34290000的博客 106

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Storm入门 第五章 一致性事务

第五章 一致性事务 Storm是一个分布式的流处理系统,利用anchor和ack机制保证所有tuple都被成功处理。如果tuple出错,则可以被重传,但是如何保证出错的tuple只被处理一次呢?Storm提供了一套事务性组件Transaction Topology,用来解决这个问题。...

chudajin2983的博客 184

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Storm 从入门到精通 第二十三讲 Storm 批处理事务 - 事务API

1. 事务APISpout (难点)ITransactionalSpout&lt;T&gt;,同BaseTransactionalSpout&lt;T&gt;,普通事务SpoutIPartitionedTransactionalSpout&lt;T&gt; --分区事务,增加消息队列吞吐量,同BasePartitionedTransactionalSpout&lt;T&gt;,分区事务SpoutI...

John,hao的专栏 799

Storm系列(十八)事务介绍

功能:将多个tuple组合成为一个批次,并保障每个批次的tuple被且仅被处理一次。 storm事务处理中,把一个批次的tuple的处理分为两个阶段processing和commit阶段。 processing阶段运行多个批次的tuple并行处理。 commit阶段各批次之间需强制按照顺序进行提交。 事务Topologies 在Transactional ...

weixin_30498807的博客 147

深入解析TI VPDMA中断寄存器:从原理到实战的嵌入式视频处理优化

在嵌入式系统开发中,直接内存访问(DMA)是提升数据传输效率、释放CPU负载的核心技术。其原理是通过专用控制器在内存与外设间直接搬运数据,无需CPU参与每个字节的传输。这项技术的核心价值在于实现高效、低延迟的并发处理,尤其对视频、音频等流式数据至关重要。在视频处理领域,DMA的应用场景广泛,例如高清视频采集、实时编解码和图像分析。本文将聚焦于德州仪器(TI)SoC平台中的视频端口DMA(VPDMA)模块,深入剖析其中断管理机制。通过详解中断状态(INT_STAT)与中断屏蔽(INT_MASK)寄存器的位域定

weixin_34184158的博客 291

大数据架构演进:从MPP到Lakehouse的技术选型指南

大数据架构是处理海量数据的核心技术框架,其核心原理是通过分布式计算和存储实现水平扩展。随着技术演进,从早期的MPP架构到如今的Lakehouse架构,大数据处理能力不断提升。MPP架构采用无共享设计,适合结构化数据分析;Lambda架构通过批流双管道保证数据一致性;Kappa架构则简化流程,主张单一流处理管道;而Lakehouse架构融合了数据湖的灵活性与数据仓库的管理能力。这些架构在金融风控、电商分析、IoT等场景中发挥着重要作用。合理选择架构可以显著提升数据处理效率,降低运维成本,例如某零售企业迁移到L

weixin_30323631的博客 425
上一篇: Java记录 -23- equals方法和双等号解析
下一篇: 在线工具
架构师的清醒
博客等级 码龄14年 291粉丝 397原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值