Strom 可定制任务调度策略(Pluggable Scheduler)

Twitter Storm的新利器Pluggable Scheduler

作者: xumingming | 可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明
网址: http://xumingming.sinaapp.com/854/twitter-storm-pluggable-scheduler/

 

最近把Twitter Storm的新特性:可插拔式的任务分配器(Pluggable Scheduler)实现了,将在0.8.0版本里面跟大家见面。这篇文章先给大家尝尝鲜,介绍下这个新特性。

在Pluggable Scheduler之前,Twitter Storm里面对于用户提交的每个Topology进行任务分配是由nimbus来做的,nimbus的任务分配算法可是非常牛逼的哦,主要特点如下

  • 在slot充沛的情况下,能够保证所有topology的task被均匀的分配到整个机器的所有机器上
  • 在slot不足的情况下,它会把topology的所有的task分配到仅有的slot上去,这时候其实不是理想状态,所以。。
    • 在nimbus发现有多余slot的时候,它会重新分配topology的task分配到空余的slot上去以达到理想状态。
  • 在没有slot的时候,它什么也不做

一般情况下,用这种默认的task分配机制就已经足够了。但是也会有一些应用场景是默认的task分配机制所搞定不了的,比如

  • 如果你想你的spout分配到固定的机器上去 — 比如你的数据就在那上面
  • 如果你有两个topology都很耗CPU,你不想他们运行在同一台机器上

这些情况下我们默认的task分配机制虽然强大,却是搞不定的,因为它根本就不考虑这些。所以我们设计了新的Pluggable Scheduler机制,使得用户可以编写自己的task分配算法 — Scheduler来实现自己特定的需求。下面我们就来亲自动手来看看怎么才能实现上面提到的默认Scheduler搞不定的第一个场景,为了后面叙述的方便,我们来细化一下这个需求:让我们的名为special-spout的组件分配到名为special-supervisor的supervisor上去

要实现一个Scheduler其实很简单,只要实现IScheduler

 
public interface IScheduler {
    /**
     * Set assignments for the topologies which needs scheduling. The new assignments is available
     * through <code>cluster.getAssignments()</code>
     *
     *@param topologies all the topologies in the cluster, some of them need schedule. Topologies object here
     *       only contain static information about topologies. Information like assignments, slots are all in
     *       the <code>cluster</code>object.
     *@param cluster the cluster these topologies are running in. <code>cluster</code> contains everything user
     *       need to develop a new scheduling logic. e.g. supervisors information, available slots, current
     *       assignments for all the topologies etc. User can set the new assignment for topologies using
     *       <code>cluster.setAssignmentById</code>
     */
    publicvoid schedule(Topologies topologies, Cluster cluster);
}

这个接口会提供两个参数,其中Topologies包含当前集群里面运行的所有Topology的信息:StormTopology对象,配置信息,以及从task到组件(bolt, spout)id的映射信息。Cluster对象则包含了当前集群的所有状态信息:对于系统所有Topology的task分配信息,所有的supervisor信息等等 — 已经足够我们实现上面的那个需求了,让我们动手吧

找出我们的目标Topology

首先我们要确定我们的topology是否已经提交到集群了,很简单,到topologies对象里面找找看,找到了的话就说明已经提交了。

 
// Gets the topology which we want to schedule
TopologyDetails topology = topologies.getByName( "special-topology" );

只要这个topology不为null的话就说明这个topology已经提交了。

目标Topology是否需要分配

紧接着我们要看看这个topology需不需要进行task分配 — 有可能之前分配过了。怎么弄呢?很简单,Cluster对象已经提供了api可以使用

 
boolean needsScheduling = cluster.needsScheduling(topology);

这里要说明的一点是,有关Scheduler编写的几乎所有api都是定义在Cluster类里面,大家只要把这个类搞熟悉,编写起Scheduler起来应该就得心应手了。如果这个topology需要进行task分配我们还要看下有那些task需要进行分配 — 因为可能有部分task已经被分配过了

 
// find out all the needs-scheduling components of this topology
Map<String, List<Integer>> componentToTasks = cluster.getNeedsSchedulingComponentToTasks(topology);
  

我们的目标spout是否需要分配?

因为我们的目标是让名为special-spout的组件运行在名为special-supervisor的supervisor上,所以我们要看看这些task里面有没有是属于special-spout的task,很简单,上面返回的componentToTasks就是从component-idtask-ids的一个映射。所以要找出special-spout就很简单了

 
List<Integer> tasks = componentToTasks.get( "special-spout" );

找出目标supervisor

找到我们要分配的task之后,我们还要把我们的special-supervisor找出来,Cluster同样提供了方便的方法:

// find out the our "special-supervisor" from the supervisor metadata
Collection<SupervisorDetails> supervisors = cluster.getSupervisors().values();
SupervisorDetails specialSupervisor =null;
for (SupervisorDetails supervisor : supervisors) {
    Map meta = (Map) supervisor.getSchedulerMeta();
  
    if(meta.get("name").equals("special-supervisor")) {
       specialSupervisor = supervisor;
       break;
    }
}

  

这里要特别说明一下Map meta = (Map) supervisor.getSchedulerMeta();, 我们前面说名为special-supervisor的supevisor,其实在storm里面supervisor是没有名字的,这里我们所谓的名字是从supervisor.getSchedulerMeta里面找出来的,这个schedulerMeta是supervisor上面配置的给scheduler使用的一些meta信息,你可以配置任意信息!比如在这个例子里面,我在storm.yaml里面配置了:


 
supervisor.scheduler.meta:
   name: "special-supervisor"

这样我们才能用meta.get("name").equals("special-supervisor")找到我们的special-supervisor到这里我们就找到了我们的special-supervisor,但是要记住一点的是,我们的集群里面有很多topology,这个supervisor的slot很可能已经被别的topology占用掉了。所以我们要检查下有没有slot了



List<WorkerSlot> availableSlots = cluster.getAvailableSlots(specialSupervisor);

判断上面的availableSlots是不是空就知道有没有空余的slot了,如果没有slot了怎么办?没别的topology占用掉了怎么办?很简单!把它赶走

 
// if there is no available slots on this supervisor, free some.
if (availableSlots.isEmpty() && !tasks.isEmpty()) {
     for (Integer task : specialSupervisor.getAllPorts()) {
         cluster.freeSlot( new WorkerSlot(specialSupervisor.getId(), task));
     }
}

最后一步:分配

到这里为止呢,我们要分配的tasks已经有了,要分配到的slot也搞定了,剩下的就分配下就好了(注意,这里因为为了保持例子简单,代码做了简化)

 
// re-get the aviableSlots
availableSlots = cluster.getAvailableSlots(specialSupervisor);
  
// since it is just a demo, to keep things simple, we assign all the
// tasks into one slot.
cluster.assign(availableSlots.get( 0 ), topology.getId(), tasks);

我们的目标实现了! 随着cluster.assign的调用,我们已经把我们的special-spout分配到special-supervisor上去了。不难吧:)

别的任务谁来分配?

不过有件事情别忘了,我们只给special-spout分配了task, 别的task谁来分配啊?你可能会说我不关心啊,没关系,把这个交给系统默认的分配器吧:我们已经把系统的默认分配器包装到backtype.storm.scheduler.EvenScheduler里面去了,所以你简单调用下就好了

 
new backtype.storm.scheduler.EvenScheduler().schedule(topologies, cluster);

让Storm知道我们的Scheduler

哦,有一件事情忘记说了,我们完成了我们的自定义Scheduler,怎么让storm知道并且使用我们的Scheduler呢?两件事情:

  • 把包含这个Scheduler的jar包放到$STORM_HOME/lib下面去
  • 在storm.yaml 里面作如下配置:
     
    storm.scheduler: "storm.DemoScheduler"

这样Storm在做任务分配的时候就会用你的storm.DemoScheduler, 而不会使用默认的系统Scheduler

这个例子的完整代码可以在这里看到。

转载于:https://my.oschina.net/u/2326085/blog/391240

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 将11g数据库还原到12c可通过以下步骤完成: 1. 首先,创建一个新的12c数据库,确保数据库版本与12c兼容,并确保已正确安装12c数据库软件。 2. 使用RMAN(恢复管理器)进行备份:在11g数据库中,使用RMAN执行完整备份以将数据库备份到外部介质(如磁盘、磁带等)。确保备份文件包含数据库的所有数据文件、控制文件和参数文件。 3. 将备份文件复制到12c数据库服务器。可以使用文件传输工具(如scp、ftp等)将备份文件转移到12c数据库服务器。 4. 在12c数据库服务器上使用RMAN恢复备份:启动12c数据库实例,然后连接到RMAN命令行界面,通过指定11g备份文件的位置和名称来恢复11g数据库。 5. 确保12c数据库实例正常运行,并且数据库文件正确还原。验证数据库文件是否完整,以及是否可以正常访问。 6. 针对每个需要还原的11g pluggable database,创建一个新的12c可插件数据库。使用Oracle Database Configuration Assistant(DBCA)工具创建新的12c pluggable database实例。 7. 在12c pluggable database的新实例上通过导入工具导入11g pluggable database的数据。使用Oracle Data Pump或其他适用的工具将11g pluggable database的数据导入到新的12c pluggable database中。 8. 验证还原和导入的数据:确保数据的完整性和一致性,验证所有表、视图和其他对象是否正确还原。 9. 执行必要的后续步骤:根据需要,执行必要的配置、设置和更新,以确保12c pluggable database与原始11g数据库一致。 请注意,以上步骤仅提供了一个基本的概述,实际操作可能会因数据库的特定要求而有所差异。在执行此过程时,请确保了解您的环境,并参考相关文档和指南。 ### 回答2: 将Oracle 11g还原到Oracle 12c可插拔数据库的过程相对比较简单,下面我会用300字中文来解释该过程。 首先,我们需要使用Oracle Database 12c的安装介质来安装一个12c的Oracle实例。你可以选择将该实例安装为容器数据库(CDB)或非容器数据库(非CDB),取决于你的需求。 接下来,使用RMAN(Oracle的备份恢复管理工具)来备份你的Oracle 11g数据库。确保备份包含了你想要恢复的所有文件,如数据文件、控制文件、归档日志等。 在12c数据库上创建一个新的容器数据库(CDB)。你可以使用创建数据库语句(CREATE DATABASE)或使用数据库配置助手(Database Configuration Assistant)来完成这个任务。 创建容器数据库后,创建一个新的可插拔数据库(PDB)。你可以使用“CREATE PLUGGABLE DATABASE”语句来创建一个空的PDB。 在创建PDB之后,使用RMAN来还原11g数据库。使用RMAN的RESTORE命令来还原数据文件、控制文件和归档日志等文件到指定的位置。 完成还原后,将还原的数据文件和控制文件复制到PDB的目录中。你可以使用操作系统的命令或者文件管理器来完成这个任务。 最后,通过ALTER PLUGGABLE DATABASE语句将PDB打开,使其可供访问。这样就完成了将11g还原到12c可插拔数据库的过程。 需要注意的是,在还原的过程中可能会遇到一些问题,比如版本不兼容或者数据不一致等。为了保证还原的成功,建议在还原之前先仔细阅读Oracle官方文档,确保你了解该过程的每一个步骤和相关的注意事项。 ### 回答3: 要将11g数据库还原到12c可插拔数据库,以下是操作步骤: 1. 首先,确保已经安装了12c数据库软件,并且已经创建了一个空的12c可插拔数据库实例。 2. 在11g数据库中执行数据泵导出操作,将数据和对象导出到一个数据泵文件中。可以使用expdp命令来执行导出操作。示例命令如下: ``` expdp system/password@source_db directory=data_pump_dir dumpfile=export.dmp logfile=export.log full=y ``` 这将导出整个11g数据库的内容到一个名为export.dmp的数据泵文件中。 3. 将导出的数据泵文件复制到12c数据库服务器上,并确保数据库服务器具有适当的读取权限。 4. 在12c数据库中执行数据泵导入操作,导入从11g数据库中导出的数据。可以使用impdp命令来执行导入操作。示例命令如下: ``` impdp system/password@target_db directory=data_pump_dir dumpfile=export.dmp logfile=import.log remap_schema=source_schema:target_schema ``` 这将从export.dmp文件中导入数据到12c数据库。`source_schema`是11g数据库中的架构名称,`target_schema`是12c数据库中的目标架构名称。使用remap_schema参数可以将导入的对象重定向到新的架构中。 5. 在导入完成后,可以验证数据是否成功导入到12c可插拔数据库中。可以查询表数据,检查是否与11g数据库中相同。 通过以上步骤,您可以将11g数据库还原到12c可插拔数据库中,并且可以在12c数据库中使用先前导出的数据和对象。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值