storm的容错机制

本文详细介绍了Storm的容错机制,包括Nimbus、Zookeeper、Supervisor和Worker的故障处理。在数据容错方面,重点阐述了Storm的Ack机制,用于确保消息的可靠消费。通过设置消息超时时间、最大待处理数以及关闭Ack机制的方法来控制数据流。此外,还提供了一个简单的Spout实现,展示如何使用Ack机制进行消息确认和重试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >





集群容错:




1.Nimbus挂掉


如果失去了Nimbus节点,Worker也会继续执行;如果workerye消亡,Supervisor会重启worker。
但是如果没有Nimbus,worker不会被安排到其他主机节点,客户端也无法提交新的任务。


2.zookeeper挂掉


zookeeper有主从结构,挂掉无影响。


3.Supervisor失败


真正执行进程的是worker,所以Supervisor失败不会影响但前运行的任务,且所有状态都保存在zookeeper或磁盘上,Nimbus及时通过zookeeper重启Supervisor即可


4.worker失败


worker是真正的执行节点,每个worker包含数个spout/bolt任务。supervisor负责监控这些任务,当Supervisor重启worker超过了一定的失败重启次数,无法发送心跳到Nimbus,Nimbus将在另一台主机上重新分配worker。


------------------------------------------------




数据容错:






容错机制 :


一般来说,分布式数据集的容错性有两种方式:数据检查点和记录数据的更新。


面向大规模数据分析,数据检查点操作成本很高,需要通过数据中心的网络连接在机器之间复制庞大的数据集,


而网络带宽往往比内存带宽低的多,同事还需要消耗更多的存储资源。








storm:数据检查




ack机制即,spout发送的每一条消息:


1)在规定时间内,spout收到acker的ack响应,即认为该tuple被后续bolt成功处理
2)在规定时间内,没有收到acker的ack响应tuple,就触发fail动作,即认为该tuple处理失败
3)收到acker发送的fail响应tuple,认为失败,触发fail动作


限流作用:为了避免spout发送数据太快,而bolt处理太慢 ,二选一即可


1)需要设置pending数,当spout有等于或超过peding数的tuple没有收到ack或fail响应时,跳过执行nextTuple,从而限制spout发送数据


2)设置最大超时时间
通过 Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS来指定




通过conf.put(Config.TOPOLOGY_MAX_SPOUT_PENDING, pending);设置spout pend数。




关闭Ack机制


1)spout发送数据时不带上msgid 
   collector.emit(new Values("value1","value2"), msgId); 


2)设置acker数等于0
   将参数Config.TOPOLOGY_ACKERS设置为0,通过此方法,当Spout发送一个消息的时候,它的ack方法将立刻被调用




------------------------------------
------------------------------------


ack应答机制可以帮助识别消息是否成功消费,but也仅仅是通过messageId标识,消费失败的数据需要我们自己来做缓存,然后在重新发射出去。


保证消息的可靠性前提: emit发射数据一定要发射messageId




代码实现概要思路:


1)成员变量定义一个ConcurrentHashMap (ConcurrentHashMap是线程安全的,分段锁,效率高),且该map只能初始化不能创建对象,创建对象会有运行异常,需要重写open初始化方法中创建对象


2)这个messageId可以是上游中获取的,也可以是在当前定义的


3)nextTuple() 中通过map缓存tuple与messageId,其中key=messageId,value=tuple;发射数据


4)处理成功,调用ack(messageId)。从缓存中删除该数据


5)处理失败,调用fail(messageId)。重新发射根据messageId从缓存中获取的tuple及messageId。




说明:
1)数据处理成功/失败,是指当前的spout/bolt。如果需要下游的数据处理成功上游才删除数据,那么需要缓存数据库缓存数据,内存集合不行。
2)storm是分布式多线程并发操作,跨jvm。此例中的map近对当前spout/bolt的当前线程起作用。横跨上下游的/集群的需要用缓存数据库操作。
3)框架不包含事物操作,更不包含对数据库的事务操作。比如入库操作,需要记录消息的入口状态,再次入库时查询状态判定是否给予执行。


样例代码:


public class MySpout extends BaseRichSpout {
    private static final long serialVersionUID = 5028304756439810609L;


    // key:messageId,Data
    private ConcurrentHashMap <String, String> waitAck;


    private SpoutOutputCollector collector;


    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("sentence"));
    }


    public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
        this.collector = collector;
        waitAck =new ConcurrentHashMap <String, String>();
    }


    public void nextTuple() {
        String sentence = "i am liu yang";
        String messageId = UUID.randomUUID().toString().replaceAll("-", "");
        waitAck.put(messageId, sentence);
        //指定messageId,开启ackfail机制
        collector.emit(new Values(sentence), messageId);
    }


    @Override
    public void ack(Object msgId) {
        System.out.println("消息处理成功:" + msgId);
        System.out.println("删除缓存中的数据...");
        waitAck.remove(msgId);
    }


    @Override
    public void fail(Object msgId) {
        System.out.println("消息处理失败:" + msgId);
        System.out.println("重新发送失败的信息...");
        //重发如果不开启ackfail机制,那么spout的map对象中的该数据不会被删除的。
        collector.emit(new Values(waitAck.get(msgId)),msgId);
    }
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值