{
    "componentChunkName": "component---src-templates-case-study-detail-ts",
    "path": "/case-studies/42",
    "result": {"pageContext":{"next":{"id":43,"attributes":{"feature":true,"title":"OPPO云数据库访问服务技术揭秘","content":"## **1、背景**\n\nMySQL是OPPO使用最广泛的关系数据库，不同编程语言的微服务都是通过MySQL官方的SDK直连真实的数据库实例。这种最传统的使用方式，会给业务开发和数据库运维带来一系列影响效率和稳定性的问题。\n\n- 不合理的数据库访问，比如不恰当的连接池设置、高危SQL无拦截、无限流和熔断等治理能力\n- 无弹性伸缩能力，单机数据库性能或者容量不足时，扩容非常繁琐低效\n- 缺乏常用的功能特性，不支持读写分离、影子库表、单元化架构、数据库加密\n- 不支持跨语言，并且与应用服务强耦合，编码和升级都非常困难\n\n以上问题，我们讲通过CDAS来解决单MySQL带来的一系列问题。\n\n## **2、CDAS产品简介**\n\nMySQL在并发能力、稳定性、高可用方面久经考验，是绝大多数网联网产品首选的OLTP场景存储组件，但单机MySQL在超高并发、海量存储、OLAP能力上先天不足，因此当数据到达一定量级后一般采用分库分表的方式来水平扩展MySQL，提升系统的整体处理能力。CDAS基于分片理念设计，目的是解决MySQL单机性能瓶颈，对外提供超过并发、海量存储、支持HTAP的MySQL服务。在一组MySQL集群前搭建一套高可用的代理 + 计算集群，提供分片能力、自动化的弹性伸缩能力、读写分离、影子库、数据加密存储能力，为用户提供一体化的产品。\n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=ZjhkYTExOTEyN2EwNjBlYzE3YjIzZjEzZDRhMGYyMTZfM3dFcXZ0d1RCN2FjVGVxeXpYbWJ2ZTJnNGFuNGFRd1VfVG9rZW46Ym94Y25tWlhpYU85Wjcxb2RVM2NEUlF0SXNiXzE2ODAxNTg5NDE6MTY4MDE2MjU0MV9WNA)\n\nCDAS Proxy使用Java语言开发，基于开源产品Apache ShardingSphere Proxy改造而来，并添加了许多高级特性来支持内部业务。我们的开发理念是依托开源的成熟产品来搭建服务，从社区汲取营养的同时也把发现的问题、特性回馈给社区，积极参与、和社区共同发展。 \n\n**2.1 CDAS产品特点**\n\n**（1）稳定性**\n\nCDAS进行了大量的基准测试、调优，实现了特殊的动态队列 + 线程池模型来保证Proxy的总体并发程度不会由于线程数过多导致上下文切换频繁从而性能下降，同时Proxy在长时间高负载的场景下不会产生Full GC导致业务中断，目前正式环境已有多个QPS:5000+的业务场景使用了CDAS，表现稳定。\n\n**（2）高度可扩展**\n\n我们建议业务在申请分片表时预估未来3~5年的数据总量来设定分片总数，前期可申请1~2个数据库，数据量变大后扩容。理论上可扩展性和分片总数相关，最大可扩展分片数相等的数据库实例，最大可扩展到250TB，同时Proxy集群也支持在线扩容。\n\n**（3）平台化运维**\n\n由云平台统一运维、部署，MySQL和Proxy都支持自动化流程申请和变更，自动接入元数据管理系统。\n\n**（4）兼容MySQL语法**\n\n支持绝大多数MySQL语法。\n\n- 路由至单数据分片100%兼容\n- 支持分页、去重、排序、分组、聚合、关联等常见查询场景\n\n**（5）功能丰富**\n\n- 多种分片算法\n- 自增分布式ID\n- 读写分离，可设置主从同步容忍阈值\n- 影子库\n- HTAP\n- 完善的监控信息：审计日志、慢日志、鉴权 \n\n## **3.核心设计** \n\nCDAS的核心目标是解决用户海量数据存储、访问问题，聚焦到分片场景中，主要体现在解析、路由、重写、聚合等逻辑 。\n\n**3.1 内核架构**\n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=Y2E0NjkzNmEyZDdmMDI1ODhjZmIxMzc1NWEyMzMwZTFfbm00REp3aU9kbFhXRHNCVVdtUTlmcm1ETHlkVVhQcmNfVG9rZW46Ym94Y25HZmtiRWdWSW9MR0RjVUZqRjhDaWVnXzE2ODAxNTg5NDE6MTY4MDE2MjU0MV9WNA)\n\n站在高处看Proxy内核，主要分为连接接入模块、I/O多路复用模块、解析路由执行引擎3个大的部分，左侧可以看到线程模型也分为3块，实际涉及线程资源的还有其他子逻辑，如并行执行线程池等，接下来将围绕多个模型和执行流程了解内核架构的细节\n\n**3.2 线程模型**内核入口层基于Netty实现，从整体上看是一个典型的Netty使用场景，内核图从可以看到主要分为3个部分。 \n\n**（1）Boss Thread**负责Accept connection，也就是接受、建立连接，客户端一般都会使用连接池技术，因此建立连接的请求不会太多，单线程即可处理 \n\n**（2）I/O Threads**即Netty EventLoopGroup ，负责编解码、发起auth认证，基于Epoll事件驱动 I/O多路复用，一个线程可处理多个连接，共CPU核心数 * 2个线程。 \n\n**（3）Worker Threads**负责执行、回写数据等核心流程。Worker线程整体是同步的，其中Parser\\Router\\Rewriter\\RateLimter是纯CPU计算，Executor Engine、ResultManager底层基于JDBC规范，JDBC目前对外暴露的是一个同步的调用模型，在数据库未响应前线程状态为blocked，因此Worker线程池的配置决定了Proxy整体的并发能力。 线程资源在操作系统中是相对昂贵的资源，在CPU核心数固定的情况下，线程数量过大会耗费大量内存和导致上下文频繁切换，降低性能。我们在压测过程中额外关注了线程数对服务的影响，找到了一个合适的计算公式。\n\n```Plaintext\nMath.min(cpuNum * X, maxThreadsThreshold)\n```\n\n- X：默认75，可配置\n- maxThreadsThreshold：默认800，可配置\n\n同时我们自研了DynamicBlockingQueue，在队列积压任务到一定阈值后提前创建新线程执行任务。\n\n**3.3 连接模型**\n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=NmExYWRlYzEzOTBiYmQ0N2MyZTE1YzAyYWYzOWQ3MWJfZ2oyeHM0R3FVM2lqaUEwMk9wc3E4R0p4RW53UDB4bTBfVG9rZW46Ym94Y253YVNQeWpFZUxOM2NiZGRxTEplMzRiXzE2ODAxNTg5NDE6MTY4MDE2MjU0MV9WNA)\n\n在接受客户端连接后，Proxy内部会为每个客户端连接维护1个Backend Connection的逻辑连接。Backend Connection的connections列表保存执行过程中用到的真实连接，请求执行完毕或事务结束后清空connections列表，释放物理连接。同时，Proxy内部使用连接池技术来保存物理连接，减少连接建立时间并控制总的连接数量\n\n**3.4 事务模型**接下来聊一下在事务场景中的执行流程。\n\n**3.4.1 单库事务**假设有以下事务场景：\n\n```Plaintext\nbegin;\nselect * from t_order where order_id = 1;\nupdate t_order set gmt_modify = now() where order_id = 1;\nupdate t_order_item set cnt = 2 where order_id = 1;\ncommit/rollback;\n```\n\n事务过程中一共会和数据库顺序交互5次。 语句1：begin时Proxy并不知道后面要执行什么语句，无法路由到RDS，只是在连接上记录了一个begin状态语句2：执行带分片键的select，还是以16分片为例，最终语句会路由到t_order_1这张表中，获取connection_db1，先执行begin，再执行select，并放入逻辑连接的连接列表中\n\n> connection_db1为t_order_1表所在数据库上的连接\n\n语句3、语句4：路由到t_order_1,t_order_item_1,和语句2路由到相同DB，复用connection_db1执行语句5：单纯的commit或rollback语句，取出当前逻辑连接的所有RDS连接，挨个执行commit/rollback在事务执行过程中，是否会产生分布式事务完全由用户SQL语句来控制，如果事务执行过程中不会切换数据库，则会退化成单纯的RDS transaction，保持完整的ACID特性，如果事务执行过程中出现路由到多个DB的情况，则会产生分布式事务。\n\n**3.4.2 分布式事务**目前分布式事务的解决方案主要有以下3种\n\n**（1）最终一致**\n\n业务发起的最终一致性方案，如Seata\\TCC等，业务有感，多用于跨服务调用场景，如订单和库存系统，某一环提交失败需特定逻辑来整体回滚，不适合Proxy场景\n\n**（2）强一致XA**\n\n多用于跨服务调用场景，目前存在性能不佳，协调器单点\\Recovery锁占用等问题，不适合高并发场景使用\n\n**（3）厂商提供分布式事务**\n\n分布式数据库厂商如OceanBase本身会对数据进行分片，事务执行过程中操作了多个分布式节点从而引入分布式事务。针对单个分布式库内的事务保证ACID，Proxy后端基于MySQL协议，无法在多个RDS间实现这类事务。\n\n**（4）现状**\n\nCDAS Proxy并没有提供XA来保证跨RDS实例的强一致性，也没有在内部支持最终一致性。如果触发多库事务则分开提交，有部分提交成功、部分失败的风险，因此建议业务方在设计事务时尽量不再RDS集群内部产生跨库事务。\n\n**3.5 分片模型**\n\n以4库16分片场景为例阐述CDAS分片方案和传统方案的区别\n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=M2QzMmRkNGU3YWQ4ZjQxOTM0MTM5NDRmZmZiNTZkMjlfc3ZiM2Y0akdiVnBKNjZHTUgyZ1F1bG9rOTJubkR5cmxfVG9rZW46Ym94Y25TWU1xTnhaTFhvaFlhSTZFWXo1Q2xjXzE2ODAxNTg5NDE6MTY4MDE2MjU0MV9WNA)\n\n传统方案每个DB中的分片名都是从后缀0开始的，每个库中有相同的分片数量。有以下劣势：\n\n- 热点分片处理困难 \n- 无法针对分片进行迁移 \n- 分片名无意义，无法自解释 \n\n针对以上问题，我们采用了类似范围分片的思路来优化了分片名。\n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=ZGJkYTA5NDM3YjRmOTA3YzUzMjRjZTY2MWMyNGVjMjRfWk1uaGFVdG5mdWd3QWFEc2wxazVSeVhWSFVZak52ZXFfVG9rZW46Ym94Y253NEJRTHMxejFNVDFTNXQzM2o1SkZjXzE2ODAxNTg5NDE6MTY4MDE2MjU0MV9WNA)\n\n分片名是唯一的，位于不同DB中的分片名互不相同，这种设计方式与Redis/MongoDB中不同slot位于不同实例上很相似，有利于扩展。\n\n| 问题         | 解决方式                                                     |\n| ------------ | ------------------------------------------------------------ |\n| 热点分片     | 热点分片可以通过扩展1个新RDS来解决，如添加DB5，将某个流量特别大的热点迁移到DB5 |\n| 分片迁移     | 单个分片迁移不影响其他分片，也不会被分片算法影响             |\n| 分片名无意义 | 通过分片名唯一让每个分片能表述它在整体集合中的位置           |\n\n t_order_1为热点分片或DB1压力过大时迁移t_order_1到新的DB5中：\n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=Mjg3NDVkZTE5ZDk1ZDViM2ZlZjQzN2RiOGZmYmViMGJfWk1NNEdxTXVBNmhsZGpwdEtZQ0hDZ095dTFoR3JJemhfVG9rZW46Ym94Y25rbDJLQ1dNTXB2RVdHS1Z0cTF1aWpmXzE2ODAxNTg5NDE6MTY4MDE2MjU0MV9WNA)\n\n当然这种迁移方式并不适用于所有场景，如表t_order、t_order_item的分片算法完全相同，则他们一定落到同一个DB中，如果迁移过程中只迁移其中一张表势必会导致不必要的分布式事务，因此迁移时会将绑定关系的表一并迁移。**3.6 执行流程** 以最简单的场景举例，逻辑表：t_order分16片，分片键：order_id\n\n```Plaintext\nselect * from t_order where order_id=10\n```\n\n**（1）解析**\n\nWorker线程拿到这条语句后首先要做的是解析SQL语句，基于开源产品Antlr实现语法树解析。\n\n```Plaintext\n{type：select，table：t_order，condition: order_id=10}\n```\n\n**（2）路由**\n\n在获取到分片表名和条件后，根据表名获取分片规则并计算分片\n\n```Plaintext\norder_id mod 16 => 10 mod 16 => 10\n```\n\n得到真实的table：**t_order_10**（**3）重写**重写流程会将逻辑表名替换为真实表名，并计算真实位于哪个DB中。\n\n```Plaintext\nselect * from t_order_10 where order_id=10\n```\n\n**（4）限流**\n\n限流功能可以控制某类SQL的瞬时并发度，目前仅对部分场景进行了限流，如OLAP请求。\n\n**（5）执行**\n\n语句将会发往真实的数据库中执行，目前OLTP请求使用MySQL官方Connector/J发送，OLAP请求使用ClickHouse官方SDK发送，并且AP流量不会路由+重写，因为在整体设计上ClickHouse集群中的分布式表名和逻辑表名是相同的\n\n**（6）聚合结果**\n\n聚合的主要场景是查询请求被路由到了超过一个真实表的场景，如\n\n```Plaintext\nselect * from t_order where order_id in (10,11)\n```\n\n这种情况一条SQL最终到DB层面会是两次子请求\n\n```Plaintext\nselect * from t_order_10 where order_id in (10,11)select * from t_order_11 where order_id in (10,11)\n```\n\n聚合时，通过JDBC API遍历两个子请求的ResultSet，在内存中新建一个逻辑ResultSet，当逻辑ResultSet被遍历时会触发子ResultSet被遍历，最终将逻辑ResultSet编码在MySQL协议包发往客户端。如果SQL语句中包含order by，聚合时会在内存里面进行归并。内存里面排序需要将所有行数据加载到内存中排序，内存压力会很大，因此虽然有排序能力，我们还是不建议在请求分裂多个子请求的场景中使用order by语法。\n\n**3.7 HTAP**HTAP的是指混合OLTP（Online Transactional Processing）和 OLAP（Online Analytical Processing），在数据库中同时支持在线事务请求和后台分析请求。 MySQL是一个典型的OLTP型数据库，不太适合OLAP型业务，因为分析语句一般需要执行复杂的聚合和查询大量数据，这可能会影响其在OLTP上的稳定性。同时OLAP数据库一般在存储方式上采用列存来最大化压缩效率、空间占用，而MySQL采用行存，一般情况下须先将整行记录查询出来再过滤出某些列，在执行分析请求时会有明显的IO读放大，效率不高。CDAS通过DTS（数据传输）服务将MySQL各分片数据传输并聚合到ClickHouse（分析型列存数据库），形成统一的数据视图。AP流量到达Proxy后会被转发到ClickHouse，数据响应后再以MySQL数据包的形式返回给客户端，通过这种方式，CDAS实现了基于MySQL协议的HTAP能力。\n\n## **4.部署架构**\n\n部署拓扑图如下：\n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=MWNiOGQ1YzAxODA2OTMxYzdhZGYwOWY1OTQzNTBhZmVfMGhLaXF6c1FsTWUyQ2hFbFhGZTYwc3Vmcnd3R0JSUHJfVG9rZW46Ym94Y25acFNIek5pMlJ6NG5BS3c1bFNSd2I4XzE2ODAxNTg5NDE6MTY4MDE2MjU0MV9WNA)\n\n现代架构中业务方对高可用的要求越来越高，目前大多数重要的服务都会采用多机房主备或互为主备的方案来部署，一般采用双机房或双中心化方案，保证其中一个区域挂掉后仍然能对外服务。在设计之初CDAS考虑到作为L7层的数据流量入口拥有极高的高可用要求，因此允许用户申请双机房Proxy集群，保证其中1个机房挂掉后另1个机房依然可以承接流量对外服务，实现机房级的高可用。业务系统通过L4负载均衡来和Proxy建立连接，L4和Proxy紧密协调保证优雅下线以及新实例发现，并感知Proxy节点的健康状态，及时下线不可用节点。同时由L4来做同机房优先路由、流量转发，Proxy后的所有MySQL集群都采用semi-sync的高可用架构模式。这种部署架构使CDAS具备了机房级灾备的能力。\n\n## **5.性能测试**\n\n在测试过程中我们尤其关注了性能方面的损耗，并对Proxy代理、直连RDS进行了对比测试，这样就能直观的得到性能损耗程度。\n\n**5.1 压测工具**\n内部压测平台(内部基于JMeter)\n\n**5.2 压测方式**\nJava SDK + 连接池方式压测 主要分为两组\n\n- 压测Proxy，Proxy连接2个RDS集群  \n- 压测单个RDS集群，作为Proxy性能对比的基准 \n\n压测语句：参考**SysBench**的数据库压测语句，由于分片场景一般不会直接使用主键ID分片，且主键ID在InnoDB中查询效率高于二级索引，因此添加sharding_k列进行分片测试，更符合实际的应用场景。\n\n```Plaintext\nCREATE TABLE `sbctest_x` (  \n`id` bigint(11) NOT NULL,\n`sharding_k` bigint(11) NOT NULL,\n`k` int(11) DEFAULT NOT NULL,  \n`name` varchar(100) NOT NULL,  \n`ts` timestamp NULL DEFAULT NULL,  \n`dt` datetime DEFAULT NULL,  \n`c` char(100) DEFAULT NULL,  \n`f` float DEFAULT NULL,  \n`t` tinyint(4) DEFAULT NULL,  \n`s` smallint(6) DEFAULT NULL,  \nPRIMARY KEY (`id`),  \nKEY `sharding_k_idx` (`sharding_k`),\nKEY `k_idx` (`k`),\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n\n压测SQL\n#QPS 非事务的简单查询\nSELECT COUNT(1) FROM $table WHERE sharding_k=?\n\n#TPS 包含 1条查询，4条变更语句\nBEGIN;\nSELECT c FROM $table WHERE sharding_k=?\nUPDATE $table SET k=k+1 WHERE sharding_k=?\nUPDATE $table SET c=?,ts=?,dt=? WHERE sharding_k=?\nDELETE FROM $table WHERE sharding_k=?\nINSERT INTO $table (id,sharding_k,k,name,ts,dt,c,pad,f,t,s) VALUES(?,?,?,?,?,?,?,?,?,?,?)\nCOMMIT;\n```\n\n**5.3 压测报告** 以8C16G规格为例：SSD\\100分片\\单片250W行\\数据量大于InnoDB buffer pool\n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=MjczNGU0ZWI0OTczM2I0NzRmNDQxMGJiY2UxMTY2OTlfMFZEQWlLd3BwT1V3aDNaUEt0UjBheGZYTFJjMXVidlZfVG9rZW46Ym94Y254UzQxVW8zM0NsSlZwbzZFOFo0VmFkXzE2ODAxNTg5NDE6MTY4MDE2MjU0MV9WNA)\n\n**（1） QPS 场景**\nProxy QPS只有RDS QPS的1/2，压测过程中观察到RT约为2倍 QPS场景主要是大量非事务查询的场景，Proxy的性能损耗约1/2，QPS压测过程中我们观察到Proxy后的RDS实例CPU使用率较低，于是将Proxy的CPU规格提升1倍后，Proxy QPS立即提升1倍，接近直连RDS的性能。\n**（2） TPS 场景**\n由于TPS涉及事务提交、log等操作，I/O频繁，瓶颈也主要在I/O，即使是SSD磁盘性能也都不高。Proxy后挂载了2个RDS实例，TPS在各并发用户数中都明显高于直连单个RDS，且在并发用户数增加后可达到其2倍，性能损耗几乎可忽略。\n**（3） 结论**\n如果业务场景中非事务查询的请求占绝大多数，且RDS的CPU利用率较高，建议选择Proxy的规格时CPU要高于RDS的规格如果业务场景中事务执行请求较多，Proxy不会成为性能瓶颈，规格可和RDS保持一致\n\n## **6.案例**\n\n目前支持了多个在线业务，拥有完善的指标展示、报警机制，我们例举个业务的控制台界面及监控图。 Proxy列表：\n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=MWU2YjRmMWFmMDNiOGI2OTkwYjI3NWY0MmZmMzQzMTVfUnd2aGpZNVdjT3Jvck5pOEYzQXJXcDE5TFczM1pwd1BfVG9rZW46Ym94Y25uMVpueEg5emlkVUx5eWQ4d1lxeWtkXzE2ODAxNTg5NDE6MTY4MDE2MjU0MV9WNA)\n\n单个节点TPS:\n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=NzYxODMxN2ZlNDRmMDNiMTI2MzliMTMyMjFlYzllMmFfb0djVHU2dThteDZueGxTQW53dlZaRG1RQ0sxOXluSjNfVG9rZW46Ym94Y25DS2JjNjFBY2cxMVRCaE5hM1BmS1ZoXzE2ODAxNTg5NDE6MTY4MDE2MjU0MV9WNA)\n\n单个节点QPS:\n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=ODg3ZDg2NGZkMmVkNjkzMWExYmUwMWQ1YmZkMTkzZTZfcnlwc3NKTFgyQW1MYlM5MGRZakc1dGxFdXZVZnVYVGhfVG9rZW46Ym94Y24ycEhPSzA0RGc4RThtN1ZJR1hrVU9nXzE2ODAxNTg5NDE6MTY4MDE2MjU0MV9WNA)\n\n在多个产品的使用过程中CDAS表现稳定，我们将会继续往更大流量的场景推广，服务更多的业务方。 \n\n## **7.总结与展望**\n\nCDAS为数据分片而生，构建基于MySQL分片场景的内部标准，通过MySQL协议实现跨语言可访问，统一使用方式，简化使用成本。  未来我们将持续专注于CDAS的性能提升和功能补充，主要体现在下面2个方面： \n\n1. ShardingSphere社区已计划将Proxy的数据库驱动从MySQL Connnector/J 替换为事件驱动组件vertx-mysql-client（一款Reactive MySQL Client），基于Netty实现和MySQL交互I/O多路复用、事件驱动替换后worker线程池执行语句时将从blocking等待变为事件驱动，少量的线程即可支持大量的并发，我们将持续关注社区的开发进度、积极参与。 \n\n2. CDAS和MySQL交互过程中会自动解码Rows数据包，产生大量的对象并且都是朝生夕灭的，导致GC压力增大，同时编解码也会耗费大量CPU时间。 Rows数据包在非解密等特殊场景外都可以基于Netty ByteBuf实现零拷贝发送，这是最佳的方案。我们计划在开源版本替换为vertx-mysql-client后对这部分逻辑进行优化，使绝大多数的请求的响应时间能达到接近4层负载均衡的性能。","date":"2022-03-14","author":"SphereEx","excerpt":null,"metaDescription":null,"createdAt":"2023-03-30T07:01:59.275Z","updatedAt":"2023-03-30T07:02:00.368Z","publishedAt":"2023-03-30T07:02:00.365Z","locale":"zh","caseStudiesType":{"data":null},"cover":{"data":null},"metaLogo":{"data":null},"localizations":{"data":[]}}},"prev":{"id":38,"attributes":{"feature":true,"title":"金鹰系统数据库分库分表策略","content":"为了全面监测区域内企业的金融风险，金鹰系统汇集了工商、舆情、投诉举报等多维度的大量数据。随着时间的推移，积攒的数据量越来越大，对系统的数据处理效率提出了更高的要求。目前金鹰系统单表最大数据量已达到亿级别，传统的数据库性能优化手段已无法满足系统的性能需求。为了减少数据库的负担，提升数据库响应速度，缩短查询时间，防控中心技术团队对数据进行分库分表。\n\n**什么是分库分表？**\n\n分库指从单个数据库拆分成多个数据库的过程，将数据散落在多个数据库中。而分表指从单张表拆分成多张表的过程，将数据散落在多张表内。\n\n**分库分表能解决什么问题？**\n\n如果数据库的查询压力过大，就需要考虑拆库，通过分库来分担单个数据库的连接压力。比如，数据库每秒需处理3500笔请求，假设单库每秒能处理的请求数最大为1000笔，那么就可以考虑拆分成4个库，来分散查询连接压力。\n\n如果单表数据量过大，当数据量超过一定量级后，无论是对于数据查询还是数据更新，在经过索引优化等纯数据库层面的传统优化手段之后，还是可能存在性能问题。这时候就需要去换个思路来解决问题。比如：从数据生产源头、数据处理源头来解决问题，既然数据量很大，那我们就来个分而治之，化整为零。可以通过分表把数据按照一定的规则拆分成多张表，来解决单表环境下无法解决的存取性能问题。\n\n►►►\n\n**金鹰系统数据库分库分表策略**\n\n金鹰系统目前采用ShardingSphere（一款分库分表框架）作为数据库中间件。通过对企业名称、法人等多个关键字进行组合散列运算得到企业ID。以企业ID作为分片键，ShardingSphere将根据企业ID与配置的路由信息决定该企业的数据落于哪个数据库分片、哪张表上，合理的算法使数据均匀分布在各数据库分片上，不同分片保存的数据量大致相同，从而确保数据处理效果能得到最大的优化。 \n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=MGM5YWQ1NmU0MzBlNzFiYzhmMjYyN2MyNjk5MTE5ZThfQzlkaERYQzZWTWVWRFBkNkRYTm1WcG13eWtlZXVDZzVfVG9rZW46Ym94Y25QSGdXUEwwaTQwenB6eWRoajFIU2xlXzE2ODAwNzM5MzQ6MTY4MDA3NzUzNF9WNA)","date":"2022-04-21","author":"广州金融科技","excerpt":"金鹰系统通过对监管企业的海量信息数据采用数据分库分表方式治理，提高了数据查询、数据处理效率","metaDescription":null,"createdAt":"2023-03-29T07:12:54.670Z","updatedAt":"2023-03-29T07:12:56.574Z","publishedAt":"2023-03-29T07:12:56.571Z","locale":"zh","caseStudiesType":{"data":null},"cover":{"data":null},"metaLogo":{"data":null},"localizations":{"data":[]}}},"article":{"id":42,"attributes":{"feature":true,"title":"智能电站数据中台建设与应用","content":"## **引言**\n\n \n\n近几年随着计算机技术、通信技术、人工智能技术的发展，电站正逐步向网络化、数字化、智能化迈进。智能电站是以电站生产和管理活动中各种信息的数字化为前提，计算机、网络、通信技术为基础，通过采用数据分析和处理、智能控制、自动决策等技术，使得在各种环境条件下都能够提供经济、环保、安全、稳定的电能并与智能电网高度融合的发电站([1-3])。数据信息资源正逐步成为电站的关键要素资源。由于电站信息系统大多是分阶段、分功能实施的，在电站智能化建设过程中，特别是在数据资源使用过程中暴露出来了许多问题。（1）数据孤岛现象严重。各个业务系统数据各自存储、各自定义，数据无法有效连接，数据分散、指标重复建设、数据实用价值低的现象普遍存在。（2）数据缺乏全生命周期管理。电站设计、基建阶段产生的数据不能传递到生产、运维阶段，影响了后期机组及设备的性能诊断和运行优化分析。（3）数据能力未能积累和沉淀。数据服务化程度低，数据共享和交互上缺乏整体协同性，无法形成有效的电站数据资产框架。\n\n如何唤醒电站沉睡的数据资产、打通数据信息壁垒、消除数据烟囱，把数据融合利用起来，是电站智能化转型过程中的难题。而以构建数据资产体系、释放数据资产价值为核心的数据中台正是这一问题的完美解决方案，对提升电站精益化运行管理水平具有十分重要的意义。\n\n \n\n### **1  数据中台架构设计**\n\n \n\n**1.1  电站数据源**\n\n来自电站不同设备和系统的数据主要是生产数据和管理数据，数据类型包含结构化、半结构化和非结构化3类数据。（1）结构化数据包括时序数据和非时序数据。时序数据一般指控制系统现场传感器数据采集过来的数据，比如火电厂的锅炉设备温度、压力等传感器信号，经过规整后存入工业实时数据库中；非时序数据包括各类关键业务系统数据，如智能检修、智能燃料、智能运行、智能经营等系统数据，这些数据基于关系型数据库存储，表现为二维形式。（2）半结构化数据包括各类系统的配置文件、产生的日志文件等，这类数据一般以XML、JSON或自定义文本文件格式存储。（3）非结构化数据包括电站档案系统、门禁系统、智能摄像头、移动机器人产生的各类技术文档、图像文件、音频文件、视频文件等。电站现有平台的管理数据与生产数据没有有效融合，实时数据库与关系数据库的互联互通也存在一定问题，未能进行数据有效组织管理和数据赋能。\n\n**1.2  数据中台架构**\n\n智能电站数据中台通过构建面向电站应用的数据共享和数据分析智能平台，克服了电站现有系统的技术缺陷。数据中台以数据资产高效管理为基础，沉淀数据通用能力，通过构建规范的、安全的、智能的、全域化的数据处理架构，提供数据采集、数据存储、数据萃取、数据治理、数据服务、数据可视化等全链路一体化的服务([4-9])，其技术架构如图1所示。\n\n \n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=ZGEyOTI5OGNmOGY2OGIwZDJmZjM1MjE0MTU3NGE2ZDFfUEgxamM0bWJEWFY4UmllVWNhUktLWVc5SW0xeHVoR1BfVG9rZW46Ym94Y25HYkllUWh2WERZWGtwY25kMWwzNUJmXzE2ODAxNTc3MDQ6MTY4MDE2MTMwNF9WNA)\n\n<center>图1  智能电站数据中台技术架构</center>\n\n<center>Fig.1  Technology architecture of intelligent power station data middle platform</center>\n\n数据采集是数据中台接入数据的入口，把各种异构数据源的数据采集到数据中台进行集中存储；数据萃取与分析将低价值的原始业务数据转换为高价值的数据资产，通过数据资产框架进行治理；基于数据服务体系将数据以服务化方式交付给业务系统，通过数据可视化框架进行数据展示，激活整个数据中台。\n\n**1.3  数据中台价值**\n\n数据中台的价值体现在“存、通、用、统、快”，如图2所示。通过构建智能电站数据中台，打通数据隔阂，统一数据标准，实现一切业务数据化、一切数据业务化、快速响应用户需求。（1）一切业务数据化。通过业务信息系统的建设，将系统中沉淀的业务数据汇聚到数据中台进行存储，实现一切业务数据化。（2）一切数据业务化。数据中台基于业务系统产生的数据进行体系化加工，将结果以服务化方式提供给业务使用，进而反哺业务，实现一切数据业务化。 \n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=Y2Y0OGY1YmU1MzhkNzljNTAxNDg2MTM1ZWQxODQ1YmJfRVZkUnNSbXNjQWpXQmN2aFpZU0NRaTJLR1ZpOE9HcFRfVG9rZW46Ym94Y25QR2tWS3JRZzExcVZkaG5BVkpHdWljXzE2ODAxNTc3MDQ6MTY4MDE2MTMwNF9WNA)\n\n<center>图2  数据中台价值</center>\n\n<center>Fig.2  Value of data middle platform</center>\n\n \n\n### **2  数据中台关键技术**\n\n \n\n**2.1  全域数据采集**\n\n全域数据采集是智能电站数据中台建设的第一步，也是非常重要的一步，为数据中台全面汇集异构数据。数据采集平台可以针对不同的数据源，建立不同的数据采集任务，具备数据采集、转换、传输、复制、迁移、同步等能力([10-11])。（1）电站每台机组控制系统大约有10万个传感器测点，时间戳精度为秒级。转子设备振动数据时间戳精度可以达到毫秒级。采用自主研发的实时数据采集传输程序，基于例外发送、数据缓存、断点续传和历史回补机制，实现电站实时数据的快速高效传输，目前支持OPC、Modbus、101~104规约、CDT规约、RTU规约及其他私有TCP/UDP通信协议。（2）电站业务关系数据库众多，其采集与同步可使用Sqoop和Kettle开源程序。抽取模式可采用全量抽取和增量抽取模式，增量数据抽取一般基于时间戳、触发器、更新标识等机制。（3）电站日志系统数据采集可采用Flume。（4）针对电站外部互联网数据，使用网页爬虫方式自动抓取目标数据。\n\n**2.2  数据湖底座建设**\n\n数据湖底座是智能电站全域数据的存储中心，针对不同数据源和不同数据应用分析需求提供灵活、可扩展的混合型存储架构，以分布式存储系统为核心，能够实现任意规模结构化、半结构化和非结构化数据存储，以提高生产力、主动维护设备，为电站的数据融合提供支撑，为智能运行、智能检修等生产决策提供依据。（1）电站机组控制系统的传感器测点数据采集频率和时间戳精度均为秒级，考虑到存储性能和后期查询、统计、分析性能，采用自主研发的睿腾（Rython）工业实时数据库进行存储，数据库系统架构如图3所示。睿腾实时数据库基于高并发网络通信技术、IO资源管控技术、多级高速数据缓存算法、无损压缩和有损压缩相结合的机制，实现海量测点数据的高效传输、存储、管理和访问。 \n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=YTVlYjFlN2MxZTE2NWRhZjU1YWU3NjY2ODgyMDY0MjlfTHkxRFhNeGRhbTAwYWQ1SEF0MTBsSjV2SzJnZnhtNWtfVG9rZW46Ym94Y25uVm40WElHdHRiUHJmbFo3bU9kanVnXzE2ODAxNTc3MDQ6MTY4MDE2MTMwNF9WNA)\n\n<center>图3  睿腾实时数据库系统架构</center>\n\n<center>Fig.3  System architecture of Rython real-time database</center>\n\n \n\n睿腾实时数据库可管控的测点规模可达千万级别。测点表基于两级索引构建，其索引结构如图4所示。在此索引结构中，如果已知一个测点的记录号RecNo，就可通过以下步骤在测点表文件中进行索引定位并进行相应的操作：①计算RecNo/10240可得到该测点所属的一级索引表单元位置，并从一级索引表中读取到二级索引块的起始文件块号；②计算RecNo % 10240可得到该测点所属的二级索引块的单元位置，并从二级索引块中读取到测点属性的文件块号；③根据索引得到的测点属性文件块号，可对该测点属性进行创建和编辑操作；如果需要删除一个标签，则只需要将该测点的二级索引块单元中的标签属性文件块号的高位（第31Bits）置为1即可，不需要更新测点属性。\n\n \n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=ZWI2NzQ5ZjY2ZGFiYjBlYTUzOTZkYjA5NzgwYzZjODVfbVNlZEI3V2tsZ2VVelROYThBeU9NNURZVldlalhweWdfVG9rZW46Ym94Y25aVTE4eVdCZGthSkV0aTEyYTVhN0tjXzE2ODAxNTc3MDQ6MTY4MDE2MTMwNF9WNA)\n\n<center>图4  睿腾实时数据库测点表索引结构</center>\n\n<center>Fig.4  Tag’s index structure of Rython real-time database</center>\n\n（2）分布式大数据平台基于自主研发的大数据产品，以分布式文件系统为核心，由管理节点和一定数量的工作节点组成大数据存储集群，支撑大数据分析、萃取、挖掘，保存加工处理后的结构化数据和图片、文档等非结构化数据([12])。（3）电站关键业务数据采用分布式关系数据库进行存储。关系数据库平台基于改进的MySql+MHA的部署方案，提供高可用、高数据吞吐能力、扩展性强的关系型数据库引擎。对于分布式数据访问层，采用开源shardingjdbc技术路线。\n\n**2.3  数据萃取与分析**\n\n基于数据开发和算法开发平台，数据萃取层通过电站业务主题域和数据仓库建设，构建完整的智能电站测点数据体系、指标数据体系、设备数据体系、成本数据体系、人员数据体系和文档数据体系。数据开发是将价值不大的原始数据变成对业务有价值的数据资产。数据开发平台产品提供批量计算、流式计算和查询分析能力([13])。（1）批量计算基于MapReduce、Spark等计算框架进行处理，主要用于人机交互较少的批量数据高延时处理，如离线数据仓库的加工、大规模数据清洗与挖掘等，其数据吞吐量大、延时高。（2）流式计算基于Storm、Spark Streaming等计算框架进行处理，数据源为源源不断的流式数据，适用于对数据的加工处理和应用有较高时效性的场景，如设备异常监控告警。（3）查询分析使用ElasticSearch、Kylin、ClickHouse等技术进行处理，适用于历史数据的在线查询、条件过滤和维度分析。算法开发作为一站式的企业机器学习开发平台，包括数据集管理（如数据接入与标注等）、核心算法组件（如回归、聚类、神经网络等）编写、主流算法框架（如TensorFlow、PyTorch、Mahout等）集成、可视化建模，旨在为企业快速提供核心算法服务([14])。基于自主研发的分布式图形化建模计算平台，通过简单的拖拽操作，就可组态出复杂的算法逻辑，为数据中台提供强大的数据建模和计算能力。图形化建模计算平台主要包含以下功能。（1）模型设计器：提供可视化的机理建模、数学建模工具。（2）工程组态：组态工程的编辑、调试、上线、维护管理。（3）算法因子：提供基础通用算法、热力学专用算法、大数据算法等不同种类算法因子。同时可以自定义算法，具备集成第三方算法的能力。（4）计算引擎：基于时间、条件、公式等基础引擎，采用流式计算、离线计算、内存计算等计算模式，进行分布式在线和离线计算。\n\n**2.4  数据资产治理**\n\n数据治理框架，为智能电站提供统一数据标准制定、主数据管理、元数据管理、数据质量管理等能力，通过数据地图和数据血缘实现电站数据360°全链路追踪。框架提供数据全生命周期的管控机制，当发生数据质量问题时，可通过可视化图形方式追溯指标的血缘及逻辑关系、关联指标的数据和权重，进而定位问题([15])。（1）电站资产模型通过设备树的方式进行组织定义，每个设备都用元素表示，元素的关联数据将作为元素的属性进行存储，元素属性数据包括常量、实时数据库测点值、关系数据库引用值、指标公式计算值、图片、文档等。（2）数据治理计算框架基于分布式消息引擎RocketMQ和分布式缓存Redis集群，采用事件触发和周期触发机制，实现设备树海量元素属性数据的层次计算和分析计算。**2.5  数据服务化交付**智能电站数据中台将数据进行服务化交付，企业内部业务系统和第三方应用不必关心底层数据库结构，就可以获得目标数据。通过这样的架构设计，对下屏蔽了异构数据的差异性，对上提供了统一的数据服务接口和标准化数据。当新的业务需求出现时，可以快速进行开发响应。基于自主研发的数据服务网关，可以为业务应用提供以下3种形式的数据服务。（1）OPC UA数据服务。在应用端对数据访问效率要求极高时，如实时性很强的测点数据，推荐使用OPC UA服务。（2）Restful WebAPI数据服务。基于微服务架构和SpringCloud技术体系，提供基于HTTP/HTTP2的服务接口。（3）文件数据服务。基于FastDFS分布式文件系统，为业务应用提供在线文档服务。\n\n**2.6  数据可视化框架**\n\n数据可视化框架基于Vuejs前端开源javascript库和CSS响应式布局模式构建，框架设计器如图5所示。框架组件设计采用MVVM（model view viewmodel）模式进行定义，框架内部基于HTML5、Canvas和WebGL图形绘制技术，实现了大量的2D、3D、VR等图形组件。框架组件间消息通讯采用Weak Event机制实现，这样不仅降低了组件间的业务耦合度，也消除了内存泄漏的风险。开发人员或业务人员使用数据可视化框架能够快速进行生产运营决策驾驶舱的数据准备、指标集建立、业务模型配置、管理视图及可视化图表构建，实现对电站海量数据的汇总统计、多维分析、报表呈现、图形展示，以交互、生动的形式直观、全面、快速地了解电厂生产经营情况并进行辅助决策，进而提升工作效率。 \n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=Mjg5OGFlZWUyNTljOTYxMWJjZGRjMWQ1NDhmNGNmNDlfTUhaazU0VTFvT1d6WWt5RjcxNDJVOUtaUGk1R1VTNHFfVG9rZW46Ym94Y25XaUJJUGJNRWdYa1pDOGZJVWkyODliXzE2ODAxNTc3MDQ6MTY4MDE2MTMwNF9WNA)\n\n<center>图5  数据可视化框架设计器</center>\n\n<center>Fig.5  Designer of data visualization framework</center>\n\n \n\n### **3  数据中台应用**\n\n \n\n建设智能电站数据中台的最终目的是高效组织利用数据资源，提升电站精益化运行管理水平。以智能电站建设过程中的3个典型应用场景为例，阐述企业如何应用数据中台，提高数据治理、分析计算和展示能力。\n\n**3.1  设备运行监视**\n\n电站在运行过程中，需要对锅炉、汽轮机、发电机、磨煤机、引风机等关键主辅机设备进行实时监控。设备数据种类复杂、来源众多，以磨煤机为例，主要监视的信息如下。（1）一次测点数据。这些数据来自现场控制系统传感器，如磨煤机电流、功率、进口风量、出口风粉温度等，采集频率为秒级，为时间序列型数据。（2）指标数据。这些数据由不同业务系统产生，如发电量、利用小时、非计划停运次数等指标来自可靠性系统，而发电量、负荷率、耗煤量等指标来自在线经营系统。指标数据均通过一次测点数据不同的运算逻辑统计计算得到。（3）设备基础信息。这些数据主要来自设备管理系统，主要包括设备名称、编码、设备KKS编码、所属专业、设备分类、型号规格、生产厂家、出厂编号、安装地点、安装现场图片等信息。（4）设备检修和缺陷记录。这些信息主要来自ERP系统（如SAP），包括检修发生时间、故障描述、参与人员、耗费人工、使用物料、消缺状态等。在传统信息系统建设方式下，电站的各种系统大多是独立建设的，存在指标重复计算、统计口径不一致、数据信息无法互联互通等问题，也无法很好地应对快速变化的前端业务。通过建设智能电站数据中台，可以消除数据壁垒、统一数据标准，实现异构数据融合和设备运行监视的数据可视化快速配置展示。\n\n**3.2  脱硫优化系统**\n\n当前环保压力日益增大，在保证烟气二氧化硫排放达标的前提下，实现脱硫系统的安全、经济、优化运行日益重要。脱硫优化系统基于智能电站数据中台，采用数据驱动模式和大据挖掘技术，进行机组工况的规律发现、特征抽取、自动识别和智能寻优，给运行人员提供及时精细的操作指导，实现企业效益的最大化([16-18])。（1）确定优化关联指标。对脱硫系统的历史运行原始数据进行多维相关性分析，确定与寻优目标“浆液量”强相关的指标：机组负荷、入口二氧化硫浓度、入口烟气流量、入口烟气温度、入口烟气湿度、吸收塔浆液pH值和出口二氧化硫浓度。（2）采集机组稳定运行工况。一般机组负荷波动不超过15%、至少持续运行1 h认为是一个稳定工况。基于机组运行的海量数据，在数据中台萃取层配置提取规则，进行脱硫系统优化关联指标数据的采集和统计，存储到中台数据湖底座。（3）工况标签化分类。采用中台提供的聚类算法对不同负荷工况进行分类，并对聚类类心进行合理选择。（4）以聚类获得的类心作为训练样本，采用中台提供的有监督机器学习算法建模，如图6所示，建立脱硫系统优化模型([19-21])。 \n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=ZTI2NzRmNjIxYjViYWJhOWJhYWQ2ZDRjZGY4Yzk2ZTdfcUp4S1VMV0psektTeVJHMjBwZTNjMTdwcG9Sd3EwVzBfVG9rZW46Ym94Y25VWHp0eWpyVjRFNkM4Y2dyZ3lwTEFlXzE2ODAxNTc3MDQ6MTY4MDE2MTMwNF9WNA)\n\n<center>图6  脱硫系统优化机器学习模型</center>\n\n<center>Fig.6  Machine learning model of desulfurization system optimization</center>\n\n（5）根据实时采集的机组负荷、入口二氧化硫浓度、入口烟气流量、入口烟气温度、入口烟气湿度、吸收塔浆液pH值和出口二氧化硫浓度数据，与稳定工况进行匹配，获得期望的“浆液量”优化目标值。\n\n**3.3  大屏幕和移动应用发布**\n\n大数据时代，电站业务数据场景分析和终端展示呈多样化发展。企业通过大屏幕发布系统，可以建立良好的形象宣传窗口；通过终端移动应用，可以随时随地查询生产实时数据、浏览生产过程图形、监控主要设备状态，对关键运营指标进行分析、钻取和统计分析。基于中台数据治理和可视化框架，采用海量酷炫图表组件和所见即所得数据源配置，用户可以快速进行大屏幕和移动应用功能设计。图7展示了智能电站“发电量分析”移动应用业务场景。 \n\n![img](https://u01f1kqxrl.feishu.cn/space/api/box/stream/download/asynccode/?code=MmZiY2E1OGUxYjNjODliNjNmNWRiMTNjOTI4OTE5YTRfczBFWnhVRVVweGRBcXJTVzIwcWg2TzhYRXhzTVdjYkpfVG9rZW46Ym94Y25yZzV1UU5kZktJRmlHRWh2czdTY2xsXzE2ODAxNTc3MDQ6MTY4MDE2MTMwNF9WNA)\n\n<center>图7  智能电站移动应用</center>\n\n<center>Fig.7  Mobile app of intelligent power station</center>\n\n \n\n### **4  结语**\n\n \n\n（1）针对电站现有系统存在的数据孤岛、数据未能有效利用问题，分析了电站发电过程中产生的海量数据的数据源类型，设计了智能电站数据中台架构，消除了数据烟囱，统一了数据标准，实现了多源异构数据融合。（2）以数据资产高效治理为基础，通过全域数据采集、数据湖底座建设、数据萃取与分析、数据服务化交付、数据可视化等关键技术方案设计，构建和实现了智能电站数据中台。（3）介绍了智能电站数据中台的典型应用场景，阐述了如何应用数据中台提高数据治理、分析计算和展示能力，对于发电企业建设和应用数据中台具有一定的借鉴意义。","date":"2022-04-20","author":"王毅, 王智微, 何新","excerpt":"在电站智能化建设过程中，为解决现有系统的数据孤岛、数据利用率低等问题，设计了数据中台产品。基于全域数据采集、数据湖底座建设、数据萃取与分析、数据服务化交付、数据可视化关键技术，建立了智能电站数据中台，实现了多源异构数据融合、共享和服务能力，有效提升电站精益化运行管理水平。最后介绍了智能电站数据中台的典型应用场景，对发电企业建设和应用数据中台具有一定的参考价值。","metaDescription":null,"createdAt":"2023-03-30T06:40:05.006Z","updatedAt":"2023-03-30T06:41:58.790Z","publishedAt":"2023-03-30T06:41:58.787Z","locale":"zh","caseStudiesType":{"data":null},"cover":{"data":null},"metaLogo":{"data":null},"localizations":{"data":[]}}}}},
    "staticQueryHashes": []}