金融分布式数据库异步全局索引研究

2023-11-16 00:51金磐石李博涵秦小麟李晓栋
计算机与生活 2023年11期
关键词:事务全局分布式

金磐石,李博涵,秦小麟,邢 磊,李晓栋,王 进

1.中国建设银行,北京 100010

2.南京航空航天大学 计算机科学与技术学院/人工智能学院/软件学院,南京 211106

我国的数据库市场曾经被国外产品垄断,国产数据库市占率极低,主流数据库产品如Oracle、DB2、SQLServer等均是来自国外。特别地,目前金融等关键行业也存在这种现象,其核心业务普遍采用“大/小机+Oracle/DB2”的集中式数据库系统。而随着国产数据库技术的发展,尤其是移动端支付的发展,现有系统已无法满足金融等关键行业的要求,因此,建设新型数据库成为了重要的研究课题[1-2]。由于数据库向下调用底层硬件资源,向上支撑应用业务,作为三大基础软件之一的数据库是计算机功能实现的重要基础。随着数据库国产替代不断加速,其发展的主流之一便是分布式数据库。分布式数据库是传统数据库技术与计算机网络的有机结合,在平滑扩展、整体性能、高可靠、高可用、低成本等方面具有优势,特别是整体性能可突破集中式数据库的瓶颈,具有很强的研究和应用价值,目前很多数据库企业研发了分布式数据库产品,并在金融、电信、互联网等关键行业进行了成功应用,具有良好的发展前景[3]。

索引是集中式数据库性能优化最常见的手段之一,它是加速查询非常有效的手段[4]。但是索引本身也会带来弊端,比如会导致写放大和空间放大,同时过多的索引也会导致查询优化器的搜索空间增大,拖慢查询优化器的优化效率,并且不合适的索引会误导优化器。在分布式数据库中,计算节点和存储节点分离情况下,如果缺乏必要的全局索引,由于网络导致延迟更加严重,性能往往更加劣化。因此研究基于分布式数据库的全局索引具有重大的现实意义[5]。伍赛等人于2009年提出了一种双层索引框架[6],分为全局索引和本地索引两层结构,后续的关于双层索引方案的研究大都是基于该框架进行的,如基于Raft 协议研究出的混合交易分析处理(hybrid transaction analytical processing,HTAP)数据库TiDB[7]、基于Hash与B+Tree的双层检索结构[8]以及基于并发跳表的双层索引架构[9]。但是当前常用的全局索引采用同步写入方式,会导致连接放大严重,并使得可以优化的单节点事务退化成分布式事务,这使得单表能够支持的全局索引数量有限,且随着数量增加性能下降严重。

金融分布式数据管理的主要应用场景是交易场景,大部分任务在云端上进行,其特点是峰谷流量差异很大,因此需要一个能够用于云端的高效检索索引框架[10]。在交易峰值时,如果全局索引和本地索引一样,保持和主表数据完全同步的一致性写入,将会导致数据库的缓冲池负载较大,当达到缓冲池的阈值时,需要向磁盘写入脏页,脏页数量较多达到磁盘IO 的瓶颈时,将会产生比较明显的事务响应时间(response time,RT)抖动,在交易场景中这是不允许的。金融分布式数据管理的另一个典型场景是批量导入数据,每天凌晨12 点后,需要限定时间内,导入100 GB以上的来自其他系统的前一天的数据到本数据库中,而这些数据库表上同样存在一个或多个全局索引。实践证明,同步写入全局索引的话,尤其是有多个全局索引的情况下,会极大地影响效率,甚至无法在限定时间内完成该操作。

针对以上两个金融领域典型场景,当前的分布式数据库同步方式的全局索引存在以下不足:(1)单表支持的全局索引数量有限且随着数量增加性能下降非常快;(2)交易场景下,全局索引的存在会增加写入事务的时延,交易高峰容易出现明显的RT抖动;(3)批量导入数据场景下,全局索引的存在会增加系统负载,降低系统吞吐量。为了解决上述问题,本文提出了一种异步的全局索引设计思路和方法,同时利用RDMA(remote direct memory access)网络降低事务时延,满足金融交易场景的需要,通过金融典型场景下的海量数据实验表明,性能提高显著,且资源消耗降低,为进一步在生产环境中的商用奠定了良好的基础[11-14]。

1 背景与相关工作

当前全局索引设计思路主要分为两大类:一类是索引和主表数据存在相同的存储引擎下且同步更新,其优点是和主表数据保持ACID(Atomicity 原子性,Consistency一致性、Isolation隔离性、Durability持久性)特性,缺点是会对数据库的负载和RT造成不利影响;另一类是索引和主表数据不在相同的存储引擎下,比如利用Redis做的键值(key value,KV)索引,利用ElasticSearch做倒排索引,优点是查询速度比较快,缺点是维护较为困难,无法和主表数据做到外部一致性。

1.1 同构的全局索引

索引和主表数据在相同存储引擎下,全局索引有两种组织方式:全局非分区索引(global non-partitioned index)和全局分区索引(global partitioned index)[15-16]。

(1)全局非分区索引。索引数据不做分区,保持单一的数据结构,但由于主表已经做了分区,会出现索引中的某一个键映射到不同主表分区的情况,即“一对多”的对应关系。

(2)全局分区索引。索引数据按照指定的方式做分区处理,比如做哈希(hash)或范围(range)分区,将索引数据分散到不同的分区中。索引的分区和主表的分区是独立的,因此对于每个索引分区来说,分区中的任一个键都可能映射到不同的主表分区(当索引键有重复值时),索引分区和主表分区之间是“多对多”的对应关系。

1.2 异构的全局索引

索引和主表数据被独立存储在Cache 缓存系统和数据库的存储引擎中,具体有两种实现方式:一种数据库和外部Cache组件相互独立[17],业务系统优先到Cache 中查询,如果Cache 中查询不到,再查询数据库;另一种是直接在数据库内部集成Cache,典型的如MySQL 的innodb_memcached 组件[18]。两种方式并没有本质区别,客户端或应用都需要维护两条链路单独访问存储引擎和Cache缓存组件,同时需要维护两边的数据一致性。除此之外,异构环境下的并行离群点的检测也需要一定的算法来实现[19]。

2 基于RDMA的低时延异步全局索引

为了解决以上全局索引数量有限、高峰期写入事务RT抖动和资源占用集中度高等问题,本文中的全局索引设计为独立于主表的一套分片表,和主表的元数据独立,但是对于用户不可见。使用局限性小于主表的二级索引,行的长度没有限制,极端情况可以做成主表的聚集索引[20](clustered index,也称聚类索引、簇集索引)完全覆盖主表字段,避免网络回表导致的性能衰减。其次,在提供对数据的事务性访问中,采用动态时间戳[21]排序方式来提供可序列化,使得事务有更高的机会逻辑上可序列化的时间线。

在传统的分布式数据库或者并行数据库环境中,一般采用计算和存储分离的架构设计,计算和存储之间采用以太网连接,但网络的传输速率远低于内存访问速率,而随着RDMA等高速网络技术的发展,网络传输代价大幅度降低。此外,随着非易失性存储设备的发展,将索引放到非易失性存储中并做索引结构的重新设计也成为研究的热点[22-24]。

本文基于RDMA的低时延全局索引设计的分布式数据库系统的总体架构如图1 所示。整体架构主要分为四部分,分别为:(1)计算集群,由1 到N个计算节点(computing node,CN)组成;(2)存储集群,由1到M个数据节点(data node,DN)组成;(3)管理集群,核心模块主要包含全局事务管理器(global transaction manager,GTM)模块、元数据服务(meta data service,MDS)模块以及本文新增的Cluster Cache 和Cluster MQ 模块;(4)本文新增的全局索引构建引擎Index Sinker 模块,既可以单独部署,也可以采用与管理集群合设的部署方式。

图1 支持异步全局索引的分布式数据库架构Fig.1 Distributed database architecture supporting asynchronous global indices

本文的数据库架构中计算集群和管理集群之间采用RDMA连接,其余都采用25GE以太网连接。为了构建异步低时延全局索引,新增加的3类节点的主要功能如下:

(1)Cluster Cache:集群缓存,用来存储主表和索引表的日志的逻辑序列号(log sequence number,LSN)信息、时间戳(time stamp,TS)信息,以及Cache 类型的KV索引。

(2)Cluster MQ:集群消息队列,用来缓存全局索引的数据,采用appendOnly模式,写入性能远高于直接写入DN节点的B+Tree数据结构。

(3)Index Sinker:全局索引构建引擎,消费Cluster MQ 的索引信息,以批量方式写入DN 集群,然后向MDS模块更新该索引的LSN点位信息。

从应用角度看,事务对应的索引数据只要CN节点通过RDMA网络写入Cluster MQ之后就可以认为事务已经提交成功;而Index Sinker 采用异步模式根据一定规则把MQ 中的索引数据真正写入DN 节点。本文设计的主要目的是为了降低事务的响应时延和系统负载。

本文提出的全局索引总体结构如图2所示,由Hash(也可以采用列表、取模等方式组织)与B+Tree组成的两层组成。其中Hash 层用来进行分区路由,分区内的索引则以B+Tree 的方式进行组织。根据不同的查询条件,这两层索引配合的情况可以分成3 种:

图2 Hash和B+Tree结合的双层全局索引架构Fig.2 Hash and B+Tree two-layer global index structure

第一种情况,查询语句中携带了可以直接路由的主键(primary key,PK)值,则如图2的路径①所示,先根据Hash算法,定位到对应的B+Tree索引B2,再在B2中根据PK定位到具体的索引。

第二和第三种情况,如果全局索引的列可以覆盖检索字段,则如图2 的路径②所示,直接从全局索引返回数据,否则如图2 的路径③所示,以主表的Distributed Key 和PK 作为逻辑指针,通过主表再查询一次数据。

针对所有包含全局索引的表,如图3 所示,在Cluster Cache中会维持一张Map映射表。CN节点会维护主表的LSN 和TS 信息。Index Sinker 会维护全局索引的LSN和TS信息。全局索引TS和主表TS之间差值,表示全局索引相对于主表落后。同时CN节点和Cache 缓存节点直接的网络采用RDMA,利用RDMA API 用户态驱动进行通讯,避免内核中断,可降低网络时延。针对Cache数据需要落盘的场景,由于不通过系统的IO 落盘,以Kernel Bypass 的方式直接写入非易失性内存主机控制器接口规范(nonvolatile memory express,NVME)硬盘,目的是为了降低磁盘开销。

图3 基于分片表的全局索引组织Fig.3 Global index organization based on sharded tables

2.1 全局索引读取算法

优化器在判断表的元数据确认含有全局索引情况下,需要加入全局索引的优化规则。例如,全局索引扫描优化规则GlobalIndexScanRule、全局索引连接优化规则GlobalIndexJoinRule。CN节点在处理查询语句时,判断全局索引是否是覆盖索引。

如果是覆盖索引,查询代价显然是低于查询主表,因此执行计划是否可以使用全局索引,只需要判断全局索引数据和主表分片数据是否一致。在默认情况下,需要满足强一致性,即涉及到的主表分片的LSN=索引表LSN。业务SQL 上也可以增加hint 属性,指定容忍索引数据落后多长时间阈值范围内,可以路由到索引表。

如果是数据符合Cache索引,优先查询Cache,如果Cache 中存在,直接返回客户端,如果Cache 中不存在,到DN节点上查询一次。CN节点上使用RDMA API和Cluster Cache节点通讯,降低时延。

2.2 全局索引写入算法

全局索引写入时,Cluster MQ作为索引数据写入的缓存管道,典型的先进先出(first input first output,FIFO)队列。CN节点负责向Cluster MQ写入索引数据,Index Sinker 节点负责向DN 节点写入索引数据。由CN->Cluster MQ,Cluster MQ->DN,完成索引数据的二阶段异步写入,支持流控。在全局索引写入过程中,CN节点算法如下:

算法1CN节点写入数据(包含全局索引)

在用户事务的主流程中,不涉及把全局索引的数据写入DN 节点的流程,只需写入主表的数据到DN 节点,全局索引数据写入MQ 队列。同时在Cluster Cache上推高主表数据的LSN点位,SQL优化器在执行查询计划的时候是否走全局索引,可以根据Cluster Cache 上存储的LSN 点位信息精准地判断。LSN 的点位是以主表在每个DN 上涉及到的分表为key维度,LSN的MAP映射表,实现了一种无锁化的数据结构,可以在CN节点上通过RDMA API以用户态的方式高效写入。在全局索引写入过程中,Index Sinker节点算法如下:

算法2MQ上的索引数据写入存储引擎

判断MQ 上的剩余数据量和DN 的节点的负载是否需要进行索引数据同步。当MQ 上的数据量过少并且距离上一次同步时间小于阈值(比如500 ms)时,跳过本次同步;同时如果DN 节点上的负载过大时,也跳过本次同步,等待DN 节点的负载满足需求时才进行同步。Index Sinker 从offset 点批量读取Cluster MQ 上的Index 数据,读取的数据量需要参考DN节点的负载,考虑流控的因素(CPU负载、网络流量、BufferPool负载),以免对TP的流量产生影响。从MQ 上读取到的索引数据,按照路由分组生成batchInsert 的数据结构,其中需要按索引键进行排序,可以优化B+Tree索引数据的写入效率。写入DN节点成功后,本文利用RDMAAPI向Cluster Cache更新LSN 点位和TS 时间戳信息,以及MQ topic 的offset信息。

3 实验结果与分析

3.1 实验设计

3.1.1 实验环境和组网

本文搭建了基于RDMA 和以太网混合的3 主机实验仿真环境,机器具体配置和网络环境见表1,3个节点上部署的软件模块见表2。数据为脱敏后的真实银行交易数据。在实验对比中选取了典型的批量导入数据和交易场景,并分别与支持全局索引功能的Oracle 和CockroachDB 数据库进行对比。批量导入数据模型为:原表中含有40个字段,平均每条记录为4 KB。建立1至3个全局索引,索引字段个数为10个。通过控制并发数调整导入的数据量,具体为每增加10个并发,导入的记录个数增加100万条。

表1 实验环境和组网Table 1 Experimental environment and networking

表2 网元分布Table 2 Network element distribution

3.1.2 实验场景设计

实验的测试项命名为GAGI(GoldenDB with asynchronous global index)。为了验证GAGI 异步处理架构的表现,在实验对比中选取了典型的批量导入数据和交易场景,并分别与支持全局索引功能的Oracle和CockroachDB数据库进行对比。CockroachDB架构和GAGI结构类似,都有CN、DN节点等,因此实验涉及不同节点类型对比时,以CockroachDB 为主;Oracle 是单节点类型,涉及整体性能对比时,以Oracle数据库为主;其他情况则同时和这两者对比。

批量导入数据模型为:原表中含有40个字段,平均每条记录为4 KB。建立1至3个全局索引,索引字段个数为10 个。通过控制并发数调整导入的数据量,具体为每增加10 个并发,导入的记录个数增加100万条。

交易场景为:金融行业使用频率很高的快捷支付业务。如图4 所示的模型简要描述了该业务中查询与插入全局索引表的操作,对私业务往往插入数据量随机且有限,更加追求查询和插入的性能。

图4 金融快速支付交易场景Fig.4 Financial fast payment transaction scenario

本文实验所用的数据都来自国有大型商业银行的真实环境,部分字段进行了脱敏处理。下述的关系代数描述了此类交易对应的事务模型,金额档表TBSPAMT0(字段数>100 个,单条记录>30 KB)是此交易事务的主要业务表,对该表的查询操作单条记录的数据量都在10 KB以上,最后的批量插入对私明细表TBSPTXN0操作的数据量在100 KB以上。

(1)查询扣款

(2)查询准贷记卡

(3)查询补款账号

(4)查询内部账号

由于金融交易场景的高并发需求,上述操作性能不能出现大幅下降,在TBSPTXN0 表上建立了全局唯一索引。为了验证GAGI异步处理架构的表现,实验重点对比了目前业界内采取的同步处理全局索引表和二级索引子表。CockroachDB 架构和GAGI结构类似,都有CN、DN 节点等,因此实验对比涉及不同节点类型对比时,以CockroachDB 为主;Oracle是单节点类型,涉及整体性能对比时,以Oracle 数据库为主,对比前两者都做了相应性能调优。

3.2 实验结果分析

Index Sinker模块和异步机制的引入,使得GAGI在处理全局索引表的数据插入时能够根据业务流量调节负载压力。当数据导入全局索引表主表引起网络、磁盘和CPU等压力超过一定范围时,Index Sinker能够通过感知DN节点侧的流量,放慢或者暂停消费Cluster MQ端的消息的消费,从而达到提高业务承载能力的目的。

在实际金融场景中,高并发的数据导入和读取全局索引表通常是错开的,因此二级索引表的更新延时在一定区间内是可以接受的。为了对比引入Index Sinker 等模块后带来的性能改变,本文建立了3.1.2小节中描述的两种业务模型。第一种是为了模拟高并发情况下对多表导入数据,以求获得触摸到服务器性能瓶颈的情况下两种方案的表现;第二种是模拟日常交易场景中的随机读写,确认新方案的引入对单表随机读写的性能提升。本文通过调整并发度和全局索引的数目,验证在新方案的改造下Index Sinker 的流控能力对GAGI 整体负载的保护和疏导能力。

3.2.1 批量导入数据性能提升结果分析

批量导入数据场景具备如下特征,即单次导入的数据大多分布在相同DN节点,单条记录的数据大小几乎相同,并且受其他业务干扰可以忽略不计。针对此类业务模型,本文所提出的方案参考了Index Sinker 的流控能力,使得其性能优势较为明显。同时,由于二级索引表分布规则的限制(通过哈希等分布规则来平均各DN 节点存储的数据量),同步架构下全局索引表原表和二级索引表的插入通常情况下是分布式的,需要额外封装分布式事务来保证数据的一致性。而将原表和二级索引表的数据导入分离开后,原表数据分布在相同DN节点的分布式事务会退化成单机事务,减少了CN节点对分布式事务的控制处理、CN节点和DN节点的语句交互和DN节点刷脏处理等步骤,能够进一步提升数据导入的处理速度。

如图5、图6所示,通过对比两种方案下的每秒事务数(transaction per second,TPS)和事务执行平均耗时能够发现,异步处理全局索引表方案下分布式数据库导入全局索引表的性能有了明显的提升(图5(b)和图6(a),取表中带有一个全局唯一索引的场景)。针对Index Sinker的流控作用和异步处理方式下取消了分布式事务的封装两个优化点,图5(a)(取10~60并发度下各数据库的最高TPS进行对比)中GAGI给出了明显高于其他两个产品的TPS,且其优势在增加全局索引个数后更加明显。

图5 全局索引个数和并发度对TPS的影响Fig.5 Influence of global index number and concurrency on TPS

图6 不同数据库的全局索引性能对比Fig.6 Performance comparison of global indices in different databases

在扩大全局索引的数目,即在数据库内部增加二级索引表的个数之后,在此测试场景下同步处理方式对CN 节点和DN 节点效率的负面影响更为明显。全局索引个数达到两个时,同步方案很快便触及性能瓶颈(图6(a),CockroachDB数据库,单个全局索引的场景),对高并发的处理能力减弱,进而导致TPS的回落。对于Oracle和CockroachDB来说,增加全局索引的个数不只是增加CN 节点整理和分发数据的压力,更是带来了导入DN 节点的数据量的增加。而新的处理架构在全局索引数目达到3 个且并发较大时才触及性能瓶颈,如图6(b)所示。

通过监控服务器上的CPU 使用率(N核CPU,则最大利用率为N×100%,本文实验机器为64 核,因此最大利用率为6 400%,下同)和IO使用率可以看出,高并发多表导入场景下DN 节点接收端会出现长时间的网络峰值,其写入磁盘的效率会在磁盘写入性能达到极限后迅速回落。此时CN 节点需等待接收DN 节点的处理结果,并进行进一步整合和计算,导致CN节点的CPU消耗增加,影响了其处理客户端请求和向CN节点加大导入压力的能力,同步处理模式下CN节点的CPU使用率低于GAGI,如图7(a)所示。

图7 GAGI对资源的占用情况Fig.7 Occupancy of resources of GAGI

如图7所示,通过(a)~(d)的对比,展示了异步处理架构下GAGI内部控制流量压力的能力。CN节点的CPU 占用稳定为0 代表着客户端的业务压力(30并发度)已经结束,而该时间点后,在GAGI 的DN 节点的CPU 占用仍然存在且稳定在一定的水平(图7(a)、图7(b))。相对应的,磁盘的IO使用率在同步处理架构下快速冲高和回落,而GAGI能够在前端业务结束后仍然保持在较高的水平(图7(c))。以上两点充分说明GAGI 的异步处理方式能够将前端业务压力转移到Index Sinker 后,由Index Sinker 根据DN 节点的压力均匀地、异步地向其导入二级索引子表的数据。根据磁盘写入等待时间的对比能够看出(图7(d)),同步处理架构下数据库在集中导入数据期间IO压力过大导致写入等待时间过长(约20 s),过度地占用资源反而会导致执行效率的下降和严重影响其他并行的业务。而在新引入的异步处理架构下DN节点的IO、CPU 和网卡等压力不会在前端集中导入数据期间短时间内过载,在Index Sinker合理分配DN节点的压力后,GAGI不但提升了集中导入数据的效率,还能最大限度降低对并行业务的影响。

3.2.2 交易型场景性能提升结果分析

日常单表随机读写测试更注重读写并行化,以模拟金融业务中并发交易的场景。其中3.2.1小节中描述的分布式事务优化为单机事务的改进点同样适用于此模型。在此类测试架构下,对于插入语句,优化点在于二级索引表与原表的数据导入分离开来异步执行,以及分布式事务退化为单机插入的处理;对于查询语句,在二级索引表数据与全局索引表原表数据的导入时延处于较低的水平时,能够通过精确化查询策略、查询二级索引表的方式保证处理效率。图8(c)(单个全局索引情景)能够充分证明优化后的事务时延有了明显的下降。

图8 不同数据库的全局索引对比测试Fig.8 Global index comparison test of different databases

引入Index Sinker和Cluster Cache组件后,GAGI处理涉及全局索引表的读语句需要和Cluster Cache交互,获取该表的当前状态从而确定查询策略。在二级索引表导入时延较低的情况下,子表数据很快追上主表,从而推动CN 节点下发到DN 节点的查询语句能够包含索引字段,大大提升查询速度;同时CN 节点能够将分布式查询分布在多DN 节点的原表,简化为目的性更强的从确定DN节点捞取二级索引表的查询策略,上述两点优化能够弥补CN节点与Cluster Cache交互带来的损耗,甚至能够通过数据导入带来的性能提升来推动整体读写操作的更优表现(图8(a),单个全局索引情景下的TPS对比)。

如图8(b)所示,全局索引数目增大的情况下取10~60并发度下的最高TPS进行对比,异步处理方案较之原有方案愈加悬殊的优异表现能够充分论证写操作的性能提升对整体读写操作的影响。同时异步处理方案中CN 节点与Cluster Cache 的额外交互和二级索引表数据导入的时延,在可控范围内对业务模型没有带来明显的冲击。

相较于批量导入数据的测试模型,此交易模型下插入语句相对降低,且导入的数据量较小。如图9所示,能够看出在异步处理架构下,客户端业务停止后仅有小幅度的DN节点上的CPU占用,耗时相较于批量导入数据模型也更短。在导入数据语句更少、数据量更小的情况下GAGI 的异步处理架构仍能够带来非常明显的性能提升,也论证了此架构下对于查询语句的优化效果。

图9 GAGI和CockroachDB的关键节点CPU占用Fig.9 CPU usage of key nodes of GAGI and CockroachDB

4 结束语

针对传统的基于同步机制和以太网络实现的全局索引方案,在金融核心业务典型的交易和批量导入数据场景下单表索引数量少、吞吐量降低、写入事务时延加大等问题,本文提出了改进的分布式数据库中全局索引方法,将RDMA网络引入CN和Cluster MQ 之间的通讯,以此显著降低时延,将全局索引的实现方式修改成基于appendOnly的异步缓存队列方式,通过对实验测试数据的对比和分析,在同样场景下比现有方法性能显著提升,且对系统资源的峰值需求明显降低。本文工作可以有效地提升分布式数据库全局索引的可用性,有力促进对现有传统集中式数据库的升级和替代进程,支撑银行金融业务的高质量发展。

未来,计划在全局索引缓存队列中进一步修改ElasticSearch 等组件,这样可以更好支持全文索引,而且可以应用于金融数据管理之外更广阔的应用领域。

猜你喜欢
事务全局分布式
基于分布式事务的门架数据处理系统设计与实现
Cahn-Hilliard-Brinkman系统的全局吸引子
量子Navier-Stokes方程弱解的全局存在性
河湖事务
落子山东,意在全局
分布式光伏热钱汹涌
分布式光伏:爆发还是徘徊
基于DDS的分布式三维协同仿真研究
新思路:牵一发动全局
西门子 分布式I/O Simatic ET 200AL