当你有很多数据要处理的时候,能够有效地使用所有的计算资源是非常重要的。不管是台个人电脑,还是有数百台服务器,你都想让Kettle能尽可能的使用所有可用的计算资源,并在可接受的时间范围内获取执行结果。
在这一章节,我们将解开kettle的转换和作业在垂直扩展和水平扩展方面的秘密。垂直扩展是尽可能的使用单台服务器上的多CPU核。水平扩展是使用多台机器资源,使他们并行计算。这两种方法都是ETL子系统的一部分(#31,并行/流水线系统)。
章节的第一部分先谈谈转换内部的并行机制和多种使用其进行垂直扩展的方法。然后我们讲解怎样在子服务器集群环境下进行水平扩展转换。
最后我们讲讲kettle分区的一些具体细节,利用分区进一步提升并行计算的性能。
东西有点多,还是先在这里列一下讨论的主题,分别是:
一、多线程
二、多线程的后果
三、用Carte作为子服务器
四、集群转换
五、分区
一、多线程
在章节2中,我们已经了解了转换的基本组成部分是步骤,而且每个步骤是并行执行的。现在我们将更深入这一话题,解释kettle的多线程能力怎样使你更充分利用机器所有的计算资源,垂直扩展一个转换。
默认情况下,转换中的每一个步骤都是在单一隔离的线程里面并行的执行。但可以为任何单一的步骤增加线程的数目,也可叫做复制。在15章里我们也解释过,这种办法能够提高那些CPU时间消耗量大的转换步骤的性能。[*1]
让我们看一个简单的例子,如图16-1,其中所有数据的记录都被一个User Defined Java Class步骤处理
图16-1:一个简单的转换
你可以右键这个User Defined Java Class步骤,选择菜单中的“改变开始复制的数量”,如果你指定4份,你将看到转换的图形表示如下,见图16-2
图16-2:在多个复制下运行一个步骤
这个“4x”的符号指示了4个复制将在运行的时候被启动。
注意:所有步骤复制只维护一份步骤的描述,[*2]
为了理解接下来的章节,这儿定义几个专业术语:
- Step: 描叙需要做的某项工作的定义或元数据
- Step copy: 在步骤里定义的执行某项工作的一个并行工作线程
换句话说,一个step仅仅是任务的定义,而一个step copy则表示一个实际执行的任务。
记录行分发
在这个例子里,你使得一个步骤复制发送记录给4个步骤复制,所以这些记录是怎样分发给目标步骤复制的呢?默认情况下,分发工作在一个循环的方式下执行。也就是说如果有N份复制,第一份复制获取第一条记录,第二份复制获取第二条记录,第N份复制接受第N条记录。记录N+1又分发给第一份复制,依此类推,直到没有记录分发为止。
这里还有另外一个比较少用的功能,使用它可以将所有的记录发送给所有的复制,你可以在步骤的上下文菜单中启用这个“复制数据到所有的步骤”选项。这个选项会发送这些记录到多个目标的步骤,例如同时往数据库表和文件里面写入数据。 在例子中,会得到一个警告对话框,见图:16-3,询问你选哪个选项
图16-3:一个警告对话框
选择Copy,可拷贝所有的数据记录给数据库和文本文件,这个转换结果看起来像下面这个例子,见图16-4[*3]
图16-4: 拷贝数据到多个目标步骤
这应该是个例外,通常情况是处理每一条记录仅仅一次(而不是处理多次),余下的章节中的例子使用的是记录的分发,而非复制。[*4]
记录行合并
记录合并发生在几个步骤或者步骤复制发送多条记录给单个步骤复制时。图16-5显示了2个这样的例子。
如果站在步骤“Text file output” 和 “Add sequence”的角度考虑,记录集从每个源步骤复制里面不是一次性读取(而是一行一行的读取),当一个步骤复制正在以缓慢的步伐发送少量的数据记录,而另外一个步骤复制正在以迅速的步伐产生记录集,而此时从源步骤复制里批次读取数据行,那可能导致严重的性能问题,。[*5]
警告:从前一步骤读取记录行的顺序是决不保证的!
图16-5:合并数据的记录行
记录行再分发
在记录行再分发里,你有X个步骤复制发送记录集给Y个目标步骤复制,想想图16-6的这个例子:
图16-6 记录行再分发
同样的规则适用于之前的记录集分发:在这个实例中,User Defined Java Class的3个源步骤复制每一个都分发记录集给2个目标步骤复制。这个结果等同于图16-7里面显示的转换。
这个再分发算法的主要优势是记录集被平等的分发给这些骤复制,防止了转换里面某个步骤复制有很多工作,而其他仅仅有一点工作干的情形。
正如你在图16-7里面看到的,有X乘Y行缓冲区被分配在UDJC和Formula步骤之间。在我们的例子中,有6个缓冲区(箭头)被分配给3个源步骤和2个目标步骤。在设计转换的时候得记住这一点哦,特别是在你的转换末端有很慢的步骤时,这些缓存能够被填满到达它们的最大值“Row set size” ,那反过来会增加你的转换的内存消耗。例如,看看图16-8里面的一个例子:
图16-7:记录行再分发展开
图16-8:再分发会分配若干缓冲区
尽管你仅仅看到一个单箭头在转换里面,其实这里你有5个来源步骤和4个目标步骤复制,而且有20个缓冲区被分配了。默认情况下最大记录行设置为10000, 所以内存中能保存的记录行总数是200000。
数据流水线
数据流水线是再分发的一个特例,它的来源和目标步骤复制是一样的(X==Y)。这种情况下,记录集绝不是通过所有的步骤复制被再分发的,相反,由源步骤复制1产生的记录集被发送到具有相同编号的目标步骤复制,图16-9提供了一个这样的转换例子:
图16-9:数据流水线
在技术上,它等同于图16-10表示的转换
图16-10:数据流水线展开
分发和合并记录行的过程中有一点但是可衡量的开销,通常情况下,最好让连续的步骤复制数目保持一样,用来减少这个开销
这种减少步骤复制之间数据通讯的开销的过程,也可形象的比喻为将数据放进游泳池通道(彼此之间可不受干扰)。
二、多线程的后果
在先前的部分,我们学习到了一个转换是多线程的,并且所有的步骤都并行运行。接下来我们会告诉你此执行模式可能带来的后果,以及如何处理那些后果。
数据库连接
在多线程软件下处理数据库连接,最推荐的方法是在转换执行的过程中为每个线程创建单一的连接。因此,每个步骤复制都打开它们自己单独的事务或者事务集。
这将导致一个潜在的后果,就是你在使用同一个数据库资源的场景下,例如一张数据表或者视图,条件竞争在同一个转换中可能而且会经常发生。
一个常见产生错误的场景,就是当你往一个关系数据表里面写入数据,在随后的步骤里面读回。因为这两个步骤运行在不同的数据库连接下,而且拥有不同的事务上下文,你不能确保这个被第一个步骤写入的数据将可见于其他正在执行读操作的步骤。
一个常见,且简单的解决这个问题的方案就是将这个转换分成2个不同的转换,然后保存数据在临时表或者文件中。
另外一个方案是强制使所有的步骤使用单一数据库连接(仅一个事务),启用转换设置对话框中的“Make the transformation database transactional”选项即可,见图16-11
图16-11 设置一个转换事务
这个选项意味着Kettle将在每个命名的数据库中,仅仅使用单一连接,直到转换执行完毕之后才执行事务的提交或者回滚。一个事务在执行过程中完全没有错误才提交,有任何错误就回滚。请注意被步骤错误处理的任何错误都不会导致事务的回滚。(这个其实跟java里面的事务处理机制一样)。
使用这个选项的缺点就是会降低转换的性能,这里有很多的原因,可以是现在所有的数据库通讯都交给了一个同步连接,也可以是往往只有一个单一服务器端进程处理请求[*6]
执行的顺序
由于所有步骤并行的执行,所以转换中的步骤没有特定的执行顺序,但是在数据集成过程中仍然有些东西需要按某种顺序执行。在大多数情况下,解决这个问题的方案是创建一个作业,使得任务按特定的顺序执行。
在kettle的转换中,也有些步骤强制按某种顺序执行,几个小技巧如下.[*7]
执行脚本步骤
如果你想在转换中,执行一个优先于所有步骤的SQL,可以使用执行脚本步骤。在正常操作模式下,这个步骤将在步骤的初始化阶段执行SQL,也就意味着它将优先于其他步骤执行。
你还可以启用“Execute for each row?”选项来操作这个步骤,见图16-12。(也就是说可以执行多个SQL在这个步骤里面)
图16-12:执行SQL语句的对话框
Blocking 步骤
另一个常见的用例是当你想在所有的记录行到达某个步骤时执行一个操作。要做到这一点,你可以使用Blocking 步骤,见图16-13
图16-13:Blocking步骤
Blocking步骤在默认配置下是简单的吃掉所有的记录行。当所有的记录行被吃掉后,它才将最后一条记录行传递给下一个步骤。这条记录行将触发随后的步骤执行一个操作,这样你就能确信所有其他的记录行已经处理完了。
在上图显示的例子里,SQL语句在所有的记录行写入了数据表后才开始执行。
作业中的并行执行
作业中的作业项是按顺序陆续执行的。这是默认的行为,通常情况下你必须等待一个作业项执行完成之后才开始执行另外一个。然而,我们在第2章中提到过,在一个作业里面并行执行作业项也是有可能的。在并行执行作业项的用例下,作业项之后的多个作业项都是并行执行,而且是由不同的线程启动的。
例如,如果你想并行的更新多张维表,你可以这样做,见图16-14。
图16-14:并行更新多张维表
三、用Carte作为子服务器
子服务器是在远程服务器上执行转换和作业的一个方便的组成模块。Carte是一个轻量级的服务器进程,可以远程监控和开启转换集群的能力,这将在这一章节的下一部分讲到。
子服务器是集群的最小组成模块。它是一个小型的HTTP服务器,用来接收远程客户端的命令,这些命令控制了子服务器上的作业和转换的部署、管理和监控。
正如第3章描叙的,Carte程序可用于执行子服务器的功能,Carte也可以执行远程的转换和作业。[*8]
启动一台子服务器最简单的方式,就是通过指定要运行(转换和作业)的主机名或者IP地址,以及Web服务器的端口。例如,下面的命令将启动一台子服务器,在服务器server1的端口8181上
sh carte.sh server1 8181
配置文件
在kettle的早期版本里,是通过命令行指定配置选项。随着配置选项数目的增加,kettle最近的版本依赖于子服务器上XML格式的配置文件,如果你有一个配置文件,你也能执行子服务器像这样:
sh carte.sh slave-simple.xml
我们例子中的配置文件slave-simple.xml是些XML标签块,描叙了一台子服务器的所有属性,这里是一个简单的例子:
<slaveserver>标签描叙了子服务器的主机名和子服务器应该监听的端口,还可以可以配置子服务器的各个方面,一般情况下,这些选项可以优化服务器进程(如:Carte)的内存使用。
max_log_lines:设置这个选项,可以配置子服务器上的日志系统保存在内存中的最大日志行。要了解更多日志系统信息可参看14章。
max_log_timeout_minutes:这个参数描叙了日志行保存在内存中的最大时间(分钟)。对于存活时间很长的转换和作业,为了防止子服务器内存溢出,这是一个尤其重要的选项。要了解更多可参看18章。
Object_timeout_minutes:默认情况下,在子服务器的状态报告中,所有转换和作业都是无期限保持可见的,这个参数可以自动的从状态列表中清除老的作业。
定义子服务器
在转换和作业中定义一个子服务器,你可以简单的进入Spoon左边的视图部分。右击“Slave server”树形项目,选择New. 然后填入一些子服务的具体信息,如图16-15的例子.
图16-15:定义子服务器
远程执行
在Spoon中可以通过对话框“Execute a transformation”:指定要运行转换和作业的子服务器。当子服务器被一个作业调用,它可通过在作业或者转换作业项对话框中配置一个远程子服务器,此时作业或者转换作业项就可以远程的执行了。[*9]
监视子服务器
这里有几种不同的方式远程监控子服务器:
1、 Spoon: 在Spoon树形菜单中右击子服务器,选择Monitor选项。这将在单独的标签中展现一个监控界面,包括了所有运行在子服务器上的转换和作业的列表。
2、 Web浏览器: 打开一个浏览器窗口,输入子服务器的地址,例如可以是http://server1:8181/.浏览器将显示一个最基本但实用的子服务器菜单给你,使得你可以控制和监控子服务器
3、 PDI企业控制台:它是Pentaho数据集成企业版的一部分,企业控制台提供了监控和控制子服务器的能力。
4、 你的定制应用:每一个服务都被子服务器以XML格式的数据暴露。这些简单的web服务可以让你以方便且标准的方式与子服务器通信。如果你使用了Kettle的Java库,还可以利用其解析XML的工具类。
Carte安全
默认情况Carte是使用简单的HTTP认证,在文件pwd/kettle.pwd中定义了用户名和密码。Kettle默认附带的用户名/密码都是cluster.
文件中的密码可以利用kettle自带的Encr工具来混淆。要生成一个Carte密码文件,使用-carte选项,像这个例子:
sh encr.sh –carte Password4Carte
OBF:1324324u432oj4324j3l2kj432j432lj43l2j43l2j43k24jc
使用文本编辑器,将返回的字符串追加到密码文件中用户名的后面
Someuser : OBF : 1324324u432oj4324j3l2kj432j432lj43l2j43l2j43k24jc
OBF:前缀告诉Carte这个字符串是被混淆了的,如果你不想混淆这个文件中的密码,你可以清楚的指定密码像这样:
Someuser:Password4Carte
需要注意的是:密码是被混淆了,而不是被加密了。这个算法仅仅是用来让密码识别起来更难,但绝对不是不可能。如果一个软件有读取这个密码的能力,你必须假设别人也能读取它[*10] ,因此,你应该总是给这个密码文件添加一些合适的权限。如果你阻止了对这个文件的未授权的访问,就首要的减少了某人能够破解这个密码的风险。
它也可以使用JAAS(Java Authentication and Authorization Service的简称)来配置Carte的安全。在这种情况下,你不得不定义2个系统配置(在文件kettle.properties中的例子):
- loginmodulename: 登陆模块使用的名字。
- java.security.auth.login.config:这指向了需要被使用的这个JAAS配置文件。
这个JAAS用户的名字是Kettle. 配置JAAS的具体细节超过了本书的范围。更多的信息可以到JAAS的home page里面可以找到http://java.sun.com/products/jaas/.
服务
子服务器给外部世界提供了一系列服务。 表格16-1列出了它定义的服务。 /kettle/ URI下的服务都驻留在嵌入的web服务器里面[*11] 。 在我们的示例服务器里面,就是http://server:8181/kettle/. 所有的服务都接受xml=Y选项,使得它返回的XML能够被Kettle java类解析,使用的类(包 org.pentaho.di.www)也在表格16-1中提到了。
表格16-1:子服务器服务
服务名称 | 描叙 | 参数 | JAVA类 |
状态 | 返回一个包含所有转换和作业的摘要状态 | SlaveServerStatus | |
转换状态 | 检索单个转换的状态并且列出所有步骤的状态 | Name(转换的名称);From line(启动增量日志记录行[*12] ) | SlaveServerTransStatus |
准备执行 | 为执行准备一个转换,执行所有步骤的初始化 | Name(转换的名称) | WebResult |
开始执行 | 开始执行步骤 | Name(转换的名称) | WebResult |
启动转换 | 转换的初始化和执行一次性开始。虽然方便,但是不适用在集群执行环境下,因为初始化需要在集群上同时执行[*13] | Name(转换的名称) | WebResult |
暂停转换 | 暂停或者恢复一个转换 | Name(转换的名称) | WebResult |
停止转换 | 终止一个转换的执行 | Name(转换的名称) | WebResult |
添加转换 | 往子服务器中添加一个转换,这需要一个客户端提交XML形式的转换给Carte | TransConfigurationWebResult | |
分配套接字 | 在子服务器上分配一个服务器套接字。请在本章阅读“集群转换”后续部分获取更多信息 | ||
嗅探步骤 | 获取经过一个正在运行转换步骤的记录行 | Trans(转换的名称);Step(步骤的名称);Copy(步骤的复制数目);Lines(获取的行数);Type(一个步骤输入或输出跳) | <step-sniff> XML包含了一个RowMeta对象以及序列化的记录行数据 |
启动作业 | 开始执行作业 | Name(作业的名称) | WebResult |
停止作业 | 终止执行作业 | Name(作业的名称) | WebResult |
添加作业 | 往子服务器中添加一个作业。这需要客户端提交XML的作业给Carte | JobConfigurationWebResult | |
作业状态 | 获取单个作业的转换并列出所有作业项的状态 | Name(作业的名称);From(启动增量日志记录行)[*14] | |
注册子服务器 | 注册一个子服务器到主服务器上(参看“集群转换”部分)。这需要客户端提交子服务器的XML给子服务器[*15] | SlaveServerDetectionWebResult(reply) | |
获取子服务器 | 给一个所有子服务器的返回列表,为主子服务器知道的 | <SlaveServerDetections> XML标签块包括了SlaveServerDetection项目 | |
添加导出 | 这个方法使得你可以以.zip归档格式传输一个可导出的作业活转换通过子服务器。它在临时文件中结束。这个客户端提交zip文件的内容给Carte服务器。这个方法总是返回XML,因为它没有使用任何其他身份。 | WebResult包含创建临时文件的URL |
四、集群转换
集群技术可以用来水平扩展转换,使得他们能够同时运行在多台服务器上。它将转换的工作量均分到不同的服务器上。这一部分,我们将介绍怎样配置和执行一个转换,让其运行在多台机器上。
一个集群schema由一台主服务器,和一些子服务器组成,主服务器作为一个集群的控制器。简单的说,我们提到的Carte控制服务器就是主服务器,其他的Carte服务器就是子服务器[*16] 。
一个集群schema也包含元数据,记录主服务器和子服务器之间怎样来回传递的数据。在Carte服务器之间传递数据是通过TCP/IP套接字。数据交换之所以选择TCP/IP,是因为通过Web services比较慢,而且会引带来不必要的开销。
注意:在处理集群schema的时候,理解主服务器和子服务器的概念非常重要。要想使得一台子服务器变成主服务器,可简单的在子服务器的复选框里勾选上“Is the master?”。你不需要传递任何特别的选项给Carte.[*17]
定义一个集群Schema
在你定义一个集群schema之前,你需要定义一些子服务器。(参看本章先前的部分:定义一个子服务器。)一旦做到了这一点,你可以右击“Kettle集群schemas”树形项目,然后选择“新建”选项,如图16-16显示的。
你可以指定所有的细节给你的集群schema。确保至少选择一台主服务器控制这个集群和一台或更多子服务器(见图16-17).
图16-16:创建一个新的集群schema
图16-17:“集群schema”对话框
这里是几个重要的选项:
- 端口:最小的TCP/IP socket端口被用来传输数据从一台子服务器到另一台。它仅仅是一个起始的端口。如果你的集群转换需要50个端口,就是端口号到端口号+50之间的所有端口都会被使用。
- Sockets缓存大小:缓存大小用来缓解子服务器之间通信。不要将这个值设的太高,否则可能会引起数据传输处理的不良振荡。
- Sockets刷新间隔(rows): 当数据记录行到达这个值后,转换引擎会在数据sockets上执行一个刷新,强制将数据推送到远程子服务器, 设置这个参数值产生的性能影响,很大程度上依赖子服务器之间的网络的速度和延迟。[*18]
- Sokets数据是否压缩?:决定子服务器之前传输的数据是否压缩。在面对网络相对慢时(例如10Mbps)这个非常好, 设成“Yes”将会导致集群转换变慢,因为压缩和解压数据流需要附加的cpu时间。因此,通常情况下,在网络不是瓶颈时,最好不启用这个选项。
- Dynamic cluster: 当启用这个选项,将会使Kettle在主服务器上动态搜寻,来决定集群schema的子服务器的列表。参看17章,可以获取更多关于动态集群的信息。
设计集群转换
要设计一个集群转换,得先建立一个标准的转换,然后再将其变成集群类型的。像先前那样创建一个集群schema,然后选择你想要在子服务器上执行的步骤。右击这个步骤,选择你想要执行这个步骤的集群。
例如, 你可能想从一个存储在共享网络驱动的大文件里面读取数据,排序数据,然后将数据写入另外一个文件。如果你想在你的3个子服务器上并行的读取和排序数据,图16-18描叙了你怎么样来开始设计:
图16-18:一个规则的转换
下一步就是选取你想要在子服务器上执行的步骤,“CSV file input”和“Sort rows”步骤。选择集群…从这个步骤的上下文菜单里面,选择这个步骤要运行的集群schema之后,你的转换将变成如图16-19显示:
图16-19:一个集群转换
当你执行这个转换,所有的被定义成集群运行(在图16-19中那些有C×3)的步骤都将运行在这个子服务器上,而那些没有集群标识的步骤将运行在主服务器上。
注意: 在图16-19中,记录行是使用3个不同的子服务器的“Sort rows”步骤进行并行排序的,相同排序记录的分组号的结果被送回给主服务器[*19] 。 由于Kettle读取记录行是从先前的步骤里面,所以你不得不采取措施使得这些记录有序,这个任务是由Sorted Merge步骤来执行的,它从所有的输入步骤里面一行一行的读取记录然后使得他们有序。 没有这个步骤,并行排序将不会产生正确的结果。
转换中至少要有一个步骤被指派运行在一个集群上,这个转换才认为是一个集群转换。为了调试和开发,集群转换可以使用Spoon中的执行对话框以非集群的方法执行。
注意:在任何单独的转换里面仅仅只能使用一个集群,这点非常重要!
执行和监控
为了运行一个集群转换,你可以有2个选择。 一个选择是通过在Spoon里面选择“Execute clustered”选项执行(如图16-20):
图16-20:从对话框“Execute a transformation”里面执行一个集群转换
为了调试的目的,你可以使用下面几个集群选项:
- 提交转换:提交生成的转换给子服务器和主服务器。
- 准备执行:执行在子服务器和主服务器上生成的转换的初始化工作
- 开始执行:当这个选项启用,这个集群转换将在主服务器和字服务器上启动。
- 显示转换:在Spoon中打开主服务器和子服务器上的转换,使得你可以看到生成的转换。下一部分会提供更多子服务器和主服务器转换信息。
请注意要完全的运行一个转换,前三个选项必须启用。第四个选项非必须,仅仅使你能够看到这个生成的转换.
另外一个运行集群转换的方法就是让它作为一个作业的转换作业项运行。在那个作业项里面,你可以启用“Run this transformation in a clustered mode?”选项,使得这个转换运行在一个集群上(如图16-21)
图16-21:通过一个作业项来执行集群转换
元数据转换
在主服务器和子服务器上仅仅运行同样的转换是不够的,对于并行的数据处理需求,。那样通常不是一个正确的方法。[*20] 主服务器和子服务器上执行的转换是由一个叫做元数据转换的翻译流程产生的。 原始转换的ETL元数据(在Spoon中设计的)被切分成片,重组,通过额外的信息加工,然后发送给目标子服务器。
对于元数据转换,这里有3种转换类型:
- 原始转换:用户在spoon中设计的集群转换。
- 子服务器转换:它源自原始转换,运行在一个特定子服务器上的转换,集群里的每个子服务器都会有一个子服务器转换。
- 主服务器转换:它源自原始转换,运行在主服务器上的转换。
在图16-19这个集群例子里面,3个子服务器转换和一个主服务器转换将被生成,图16-22说明了主服务器转换在我们的例子里面是什么样的:
图16-22:一个主服务器转换
图16-23说明了子服务器转换是什么样的:
图16-23:一个子服务器转换
这个转换浅灰色编号的区域指示了拥有远程输入或输出连接的那些步骤(远程步骤)。在我们的例子里,有3个子服务器,每个子服务器发送数据从“Sort rows”到Sorted Merge步骤。这意味着3个“Sort rows”步骤都有一个远程输出步骤,并且Sorted Merge步骤有3个远程输入步骤。如果将鼠标悬置到这个浅灰色的矩形内,你将会获取更多关于这个远程步骤的信息,还有分配的端口号,如图16-24:
图16-24:远程步骤上的提示信息
规则
你可以想象,当你操作这些元数据转换时,这里有很多可能性值得考虑。让我们看看几个普通在Kettle用来生成转换时,确保逻辑操作正确的规则,[*21]
- 如果一个步骤被配置成集群运行,它会被复制到一个子服务器转换。
- 如果一个步骤没有被配置成集群运行,它会被复制到一个主服务器转换。
- 远程输出步骤(发送数据通过TCP/IP sockets)被定义给那些发送数据给一个集群步骤的步骤。[*22]
- 远程输入步骤(接受数据通过TCP/IP sockets)被定义给那些从一个集群步骤接受数据的步骤。
接下来的规则更加复杂,因为他们处理一些更加复杂的集群方面:
- 在多份复制情况下,集群支持运行的步骤。[*23] 在这个例子里,远程输入和输出步骤是通过复制的编号进行分发的。对于这些远程步骤投入更多的复制毫无意义。
- 一般情况,为了使得生成的转换更可预测,Kettle集群要求转换尽量简单。
- 当一个步骤从特定的步骤里面读取数据(info-steps),Socket Reader和Socket Writer步骤被引进做这个转换工作,图16-25这个转换正是这样:
图16-25:提供数据给集群步骤
图16-26:带一个reader的子服务器转换
图16-27:主服务器分发数据给子服务器
仔细的人应该会发现,“Table input”步骤正在分发记录行通过不同的socket writers传输数据给子服务器,这不是我们真正想看到的。在这种情形下,要确保拷贝数据到运行在远程服务器上的多个复制(见图16-28)[*24]
图16-28:拷贝数据到子服务器
简单地在子服务器上读取数据三次是比较明智的,如图16-29显示。
图16-29:在子服务器上获取数据
数据流水线
记得在本章前面提到数据流水线或数据游泳通道:在Carte服务器之间交换数据越多 ,转换就会越慢。理想情况下是,按照你能够从头到尾并行(执行)所有东西的方式组织你的数据。那样的话,处理100个XML文件会比处理一个单一的大文件更容易,因为多份文件情况下数据能够被并行读取。
作为一个一般的规则,要使你的集群转换获取好的性能:尽量让转换简单,在同一子服务器上,尽可能在游泳通道里面做更多的事情,以减少服务器之间的数据传输。
五、分区
分区是一个非常笼统的术语,广义的讲是简单拆分成多个部分。在数据集成和数据库方面,分区指拆分数据表或者整个数据库(分片)。表可以划分成分区表,整个数据库划分成碎片
除此之外,使得文本或XML文件分区也是完全有可能的,例如(按)每家商店或区域(分)。由于数据集成工具需要支持各种技术,所以kettle中的分区被设计成与源数据和目标数据无关。
定义一个分区schema
分区是kettle转换引擎的核心,每当分发记录行通过若干目标步骤时,这就是在分割数据,这种情形下的分割规则犹如一个循环赛。实际上,这个规则并不比随机分发好,它通常不是我们要提到的一个分区方法。
当我们谈到Kettle中的分区,是指kettle可根据一个分区规则引导数据记录行到某一个步骤复制的能力。在Kettle中,一组给定的分区集叫做分区schema,规则本身叫做分区方法。分区schema要么包含一命名的分区列表,要么简单的包含数个分区。分区方法不是分区schema的一部分。
图16-30提供了一个简单的例子,定义了一个包含2个分区(A和B)的分区schema
图16-30:“分区schema”对话框
一旦这个分区schema定义,在转换里,你可以根据一个分区方法应用它到一个步骤。 当你在这个步骤菜单上选择分区选项时,会弹出一个对话框让你选择使用哪个分区方法(如图16-31),分区方法可以是下面的一种:
- None: 不使用分区,标准的“Distribute rows”或“Copy rows”规则被应用了[*25]
- Mirror to all partitions: 在“数据库分区”部分,我们再进行描叙这个特例。
- Remainder of division:这个是kettle标准的分区方法。Kettle通过分区编号除以分区数目(一个整数或另外一种数据类型的校验)[*26] ,产生的余数被用来决定记录行将发往哪个分区。例如在一个记录行里,如果你是有 “73” 标识的用户身份,而且有3个分区定义,这样这个记录行属于分区1,编号30属于分区0, 编号14属于分区2.
- 通过插件实现分区方法:这个选项从分区方法对话框里是不提供的。参看23章的一个分区插件例子,里面有告诉更多关于写插件的信息。
然后你需要指明使用哪个分区schema。例如你可选择AB,如图16-32.
在这一点上,一个详细的对话框显示,允许你为这个分区方法指定参数。在我们的例子里,我们需要指定基于它分区的字段(见图16-33)。
图16-31:选择分区方法
图16-32:选择分区schema
图16-33:指定基于它分区的字段
分区的目标
使用分区的目标是为了提高转换的并行度,大多数情况下,这根本不能达到,因为这(仅仅通过分摊负载到多个复制或服务器上)不是并行的。
拿Group By步骤举例;为了简单起见,我们使用Memory Group By步骤。如果你要利用标准的转换记录行分发,执行这个步骤的多份复制,几乎可以肯定最终得不到正确的结果,因为属于某一个组的记录可能在任意步骤复制里结束。 汇总和会不正确,因为步骤可能看到的不是所有的记录行,仅仅是一个组的一部分。
让我们思考一个简单的例子,有一个包含客户数据的文本文件,你想计算每个国际的邮政编码数量(见图16-34)
图16-34:一个分区例子
文件读取并且分区方法被应用到这个国家字段上。使用这种分区方法,可确保你总是发送数据记录行对于同样的国家到达同一步骤复制。这实际上使你在多份复制情况下,运行Memory Group By步骤并计算出正确的结果,此外这不是不可能的[*27]
另外一个分区的原因应该是你想并行的运行Database Lookup和Dimension Lookup/Update步骤。如果你在这些步骤上应用分区,有可能提高它的命中率。因为你保证了一拥有同样键的数据记录行在同样的步骤复制里面结束,并且增加了值在内存中的可能性。
实施分区
在kettle里面实施分区很简单:对于每一个定义的分区,kettle会根据一个定义的分区方法启动多个步骤复制。[*28] 也就是说如果定义5个分区,就会有5个步骤复制工作。分区步骤的前一步(图16-34中的“Csv file input”步骤)是做重新分区。 当数据没有被分区,并且要将它发送给一个分区步骤的时候,重新分区才执行。[*29] 使用一个分区schema分割数据并且在一跳上将其发送给使用另一个不同的分区schema,此时重新分区也会执行[*30] 。
内部变量
为了使已经以分区格式存在的数据处理更加便捷,kettle定义了一些内部变量可帮助你:
- ${Internal.Step.Partition.ID}: 这个变量描叙了步骤复制所属分区的ID或名称, 在一个分区格式里面,可以用来读取或写入外部数据到Kettle.
- ${Internal.Step.Partition.Number}:这个变量描叙了分区的编号从0到分区的数目减一。
例如,如果在N个文本文件中,数据已经被分区(文件-0到文件N,N是分区数目减一),你可以创建一个“Csv file input”步骤从文件名 file-${Internal.Step.Partition.Number}.csv中读取数据,每一个步骤会仅仅读取属于它的分区数据。[*31]
数据库分区
在Kettle的数据库连接对话框中,可定义数据库分区或碎片。当配置一个数据库连接的时候,在Clustering标签那可以定义,Kettle假定所有的分区都是同一数据库和连接类型[*32] (见图16-35)
图16-35:定义数据库分区
定义分区的目的是为了从某一个分区甚至某一个物理数据库读取和写入数据[*33] , 一旦在数据库连接里面定义了数据库分区,你就基于这个信息创建了一个分区schema,你可以在“分区schema”对话框里面使用“导入分区”按钮(使用这个分区schema).
现在你可以在任何步骤里面应用这个分区schema(就是说使用这个分区的数据库连接)。Kettle将为每个数据库分区产生一个步骤复制,并且它将连接物理数据库(数据库分区和分区这个步骤的名字一样)[*34] 。
图16-36是在2个不同数据库分区上并行执行一个查询的例子,数据被流水到接下来的2个步骤复制计算某些东西
图16-36:读取数据库分区
同样的道理应用到所有数据库步骤,可以保持数种数数据库并行(处理)。这个“Mirror to all partitions”分区方法被特别设计成可并行的将同样的数据写入多种数据库分区。对于查找数据表(需要在多个数据库分区上复制,不需要定义多个数据库连接)[*35] 非常有用。
在集群转换中分区
在定义很多分区的情况下,步骤复制的数目会在转换过程中急剧上升,解决这个问题则牵涉到在集群转换过程中将分区扩散到一系列的子服务器
在转换执行期间,可用分区被平等的分配在可用的子服务器中间。如果你使用静态的分区列表定义了一个分区schema,在运行时,那些分区将会被划分到子服务器转换的数量里面[*36] 。Kettle这里的限制是分区的数量等于或大于子服务器的数量,并且通常是均匀分布于子服务器(slaves×2,slaves×3)。一个解决这个问题的简单方式就是指明你要每台子服务器动态配置的分区。[*37] 同先前的图16-30一样。
记住如果你在集群转换里使用分区步骤,数据通过这些子服务器需要重新分区,,这会导致相当多的数据通讯。例如,如果你有10台子服务器带有10个步骤A的复制,并且接下来的步骤B运行在每台具有3个分区的子服务器上,10×30个数据路径需要创建,与图16-7中的例子相似。 这些数据流向路径中的10×30-30=270个由远程步骤组成,会引起一些网络阻塞,以及CPU和内存的消耗,在设计集群和分区转换的时候,请考虑这个影响。
总结
这一章,你看到了转换中的多线程,集群和分区,这里有写重点回顾:
- 你学会了一个转换怎样并行的执行步骤,当步骤带有多个步骤复制执行时,记录行是怎样被分发的,我们描叙了数据是怎样被分发和合并到一起,并且介绍了几个可能发生的经典问题。
- 我们向您展示了在远程服务器上,怎样部署成可执行、管理和监控转换和作业的子服务器[*38]
- 深入的探讨了多台子服务器如何形成一个集群,转换怎样利用这些子服务器资源。
- 最后,你学到了在操作分组数据时,kettle分区是怎样帮助你并行(执行)这些步骤,怎样提高命中率的, 你也可以看到分区是怎样应用到文本文件,怎样使用分区变量和隔离的数据库schema进行数据库分区。
2010年12月26日星期日
翻译词汇:
parallelizing 并行
pipelining流水线
row 记录行
rows 记录集
slave 子服务器
master 主服务器