解析数据拆分的实现方法

我们知道在传统的单块架构中,一个系统中只存在一个独立的服务和数据库实例。


上图中的系统架构实现起来比较简单,但是扩展性和伸缩性都比较差。因此,越来越多的系统开始采用了微服务架构。在微服务架构中,一个系统被拆分成多个服务,而每个服务都拥有属于自身的数据库。


从单块系统到微服务系统的转变过程需要根据领域对系统进行合理的拆分,同时也要求数据层面从集中式的管理转变为分散式的管理。这就引申出今天我们要讨论的主题,即数据拆分。

数据拆分场景和解决方案

设想我们现在拥有一个运行了一段时间的数据库实例,内部包含了多个数据库。那么我们可以想象通常都会存在跨表查询和跨库查询场景。同时,如何我们使用了存储过程等特定的数据库实现技术,那么想要实现对数据的拆分操作也会变得不那么容易。这些场景构成了我们实现数据拆分的主要场景。


接下来,我们将分别对上述场景进行分析,看看分别应该采用哪种解决方案。

跨表查询场景

在日常开发过程中,跨表查询是非常常见的一种实现技术。在同一个数据库中,开发人员可以通过主外键之间的关联关系完成多个表之间的连接操作。

下图展示了一种表连接的表现形式,图中的连接1所涉及到的表1和表2都属于同一个业务模块。对于这个连接,我们不需要进行数据去中心化,因为位于单个业务模块内部的数据连接查询不会影响到其他模块,符合微服务架构下服务拆分的基本原则。


我们再来看另一种连接情况。


可以看到连接2和连接1不同,该连接所涉及的表3和表4则位于两个不同的业务模块中。显然,当我们基于业务模块拆分微服务时,这种连接就不应该再存在。

针对跨多个业务模块的跨表查询应用场景,我们想要去掉表与表之间的连接也比较简单,因为表连接的本质就是把位于不同表中的数据进行组装,我们可以把这个组装过程放到内存中。也就是说,我们先分别从数据表中获取目标数据,然后通用代码在内存中完成数据的动态组装,然后在返回给客户端,整个过程如下图所示。


基于跨表查询场景下的分析,也可以得出一条在日常开发过程中的最佳实践,即我们应该尽量避免不同模块之间的数据产生数据表级别的关联,而是应该通过代码来管理和维护这层关系。

跨库查询场景

讨论完跨表查询,接下来我们讨论跨库查询场景。从系统设计角度而言,跨库查询是应该被明确禁止的,因此这种场景相对比较少。但如果一旦出现这种场景,那么所带来的问题也就更为严重。下图展示了跨库查询的具体场景。


一旦涉及到跨库查询,我们的基本思路就是对查询语句进行改造,通过接口查询的方式来替换跨库的查询连接。


现在,如果想要获取数据表1和表2中的数据,那么唯一的操作方法就是暴露API接口,应用程序通过接口获取数据之后再在内存中进行数据的组装,并开放给客户端进行访问。请注意,上图中所示的跨库查询和跨表查询方案的本质区别在于:位于不同数据库中的数据必须确保严格的边界,而通过接口的方式来获取数据可以做到这一点。这样,基于不同数据的不同接口可以面向各自的应用程序,这也为微服务的拆分奠定了基础。

关于跨库查询,还有一种特殊的应用场景。有时候,位于不同数据库中的数据虽然有一定的关联关系,但这种关联关系并不像连接查询那样需要实时失效,而是允许一定的时延性。这时候,通过接口的方法实时暴露数据就不是很有必要,我们可以采用数据定时同步的方式来完成跨库的数据同步。


可以看到,在这种应用场景下,数据库A和B中同时保存着表1和表2的数据,我们通过定时任务确保这两张表的数据是一致的。通过这种方式,原本需要跨库才能完成的查询,就转变成了单库内的数据查询,跨库查询就降级成了跨表查询。

技术耦合场景

当我们面对遗留系统时,一大挑战在于对一些数据库内置技术组件的改造,这些技术组件包括存储过程、触发器、函数等。由于技术体系的不断演进,我们已经不推荐把业务逻辑通过这些数据库内置技术组件进行实现,但在遗留系统改造过程中则非常常见。对于这些位于数据库内部的数据处理逻辑,开发人员唯一要做的就是把他们全部用业务代码的形式全部实现一遍即可。


数据拆分流程

理解了数据拆分的主要场景和对应的解决方案,我们接下来讨论如何实施这些解决方案。请注意,无论是实施对跨表查询、跨库查询还是遗留系统的改造,我们都需要确保线上业务的稳定性,而不是直接采用一刀切的方式进行直接替换。在今天的内容中,我们基于主流的微服务架构,以单个数据库拆分的场景为例来开展讨论。数据拆分前和拆分后的对比效果如下图所示。


可以看到,我们需要根据业务边界把单块系统拆分成多个微服务,然后基于服务边界进一步对数据库中的表进行拆分。最后,原本属于表之间的关联关系就变成了服务之间的接口对接关系。

在今天的内容中,我们把数据拆分的过程分成三个主要的步骤。

边界分离

要想拆分数据,首先需要拆分业务。根据业务模块的不同职责和内容,我们可以把单块系统中的代码拆分成不同的服务。


可以看到,我们从物理上拆分了服务A和服务B这两个微服务。其中服务A和服务B分别独享了表1和表2,但对于表3而言,服务A和服务B都需要访问。

数据冗余

为了对表3进行拆分,我们这时候就需要采用一定的数据冗余策略。


可以看到,我们需要把针对表3的数据操作抽象成“写”和“读”两方面。通常,这部分工作并不会很复杂,因为针对某个业务数据写入的源头通常只有一个,只要明确这个数据源即可。万一我们发现写的操作有多个源头,那么把这些源头的代码都放在微服务A中就可以了。至于读操作,我们确保采用一定的数据同步机制确保服务B中的表3数据实时更新即可。

接口改造

最后,我们明确了表3的“读写”边界,就可以通过接口的方式去除数据同步机制。这也是数据拆分的最后一个环节。


数据拆分是我们开展微服务架构设计和实现过程中的一种常见场景。应对这一场景的基本思路是分析服务与数据之间的关联关系,然后针对传统规范化数据模型存在的问题,梳理数据拆分的典型场景和解决方案。今天的内容,我们对这一话题进行了深入的探讨,并结合典型场景给出数据拆分的案例分析。

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 解析一组Modbus通信数据方法一般涉及以下几个步骤: 1. 分析数据格式:Modbus通信数据一般由功能码、数据地址、数据值等部分组成。根据协议规范,了解数据每个部分的含义和格式,以便正确解析。 2. 读取功能码:首先从通信数据中读取功能码,该功能码表示Modbus协议中的操作类型,如读取、写入等。 3. 读取数据地址:接下来读取数据地址,该地址指示要访问的寄存器或线圈的位置。根据协议规范,确定该地址的格式和含义。 4. 解析数据值:根据功能码和数据地址,确定要解析数据类型,如寄存器、线圈等。根据数据类型,从通信数据中读取相应长度的数据,并进行解析。 5. 验证校验码:Modbus通信数据通常包括一个校验码,用于验证数据的完整性。对通信数据进行校验,确保数据接收的正确性。 6. 处理数据解析出的数据值可以进一步进行处理,如转换为实际物理值、进行计算等,以满足具体应用需求。 7. 错误处理:在解析数据过程中,需要处理可能出现的错误情况,如数据长度不匹配、校验失败等。对于无法解析数据,可以进行错误处理,如报错或忽略。 通过以上步骤,我们就能较为准确地解析一组Modbus通信数据。具体的实现方式可以根据具体的编程语言和开发环境进行选择和实施。 ### 回答2: Modbus是一种通信协议,常用于工业自动化领域中的设备通信。解析一组Modbus通信数据方法可以分为以下几个步骤: 1. 分析通信协议:了解Modbus通信协议的结构和规范,包括帧结构、寄存器地址、功能码等内容。根据不同的Modbus协议版本和设备类型,进行相应的协议解析。 2. 数据帧:将接收到的数据帧进行分,分离出其中的相关信息,如设备地址、功能码、数据内容等。可以使用相关的解析库或自行编写算法来实现数据帧的解析过程。 3. 解析寄存器地址:根据Modbus协议中定义的寄存器地址格式,将接收到的地址数据解析为对应的具体寄存器地址。根据不同的设备类型和通信模式,可能需要进行一定的偏移或转换操作。 4. 解析功能码:根据数据帧中的功能码字段,确定所需进行的具体操作,如读取寄存器值、写入寄存器值等。不同的功能码对应不同的操作类型,需要按照协议规定进行解析和处理。 5. 解析数据内容:根据功能码和数据帧中的数据字段,解析出实际的数据内容。以读取寄存器值为例,根据功能码和数据长度信息,将接收到的二进制数据转换为相应的数值类型或数据格式。 6. 执行相应操作:根据功能码和解析出的数据内容,执行相应的操作,如读取寄存器值后,将其显示或存储到相应的位置。 在解析Modbus通信数据时,需要遵循协议规范和设备要求,并使用合适的编程语言和工具进行实现。此外,还需要考虑数据的校验、异常处理等问题,确保数据的准确性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值