您好, 访客   登录/注册

基于微服务架构的数据一致性方法研究

来源:用户上传      作者:杨成荣 刘峻松 孙新杰 吴超

  摘要:随着微服务架构的兴起,越来越多的应用由单体式向微服务架构转移,由于微服务其分布式的特性,以及微服务架构自身强调数据的独立,整体的数据一致性问题被放大。该文主要针对在微服务通讯过程中引入分布式消息队列进行研究。首先,解决消息和指令的幂等性,保证重复消息的单次执行。其次,在分布式消息队列中对消息数据进行落盘保存通过偏移量的操作实现单方重新上线后的自我补偿,保证消息的投递。最后,人为模拟业务流程和可能出现的问题进行试验,由该机制进行自动处理,实现数据的最终一致性。通过分析实验结果,该机制可以在低时效性业务系统中自动解决由于服务或数据库离线造成的数据不一致,实现微服务整体的数据的最终一致性。
  关键词:微服务;分布式;数据一致性
  中图分类号:TP311 文献标识码:A
  文章编号:1009-3044(2020)08-0266-03
  随着互联网业务的复杂性和其用户量的不断增加,单体式应用的弊端已经逐步显现,微服务架构应运而生。微服务架构将巨大臃肿的单体式应用根据业务和功能的需求分解为无数小的且通过不同互联技术相互连通的微服务[1],其优势主要在于方便部署,扩展性高,开发周期和成本大大降低等[2]。但是,微服务架构自身的分布式特性也存在一定的弊端。在实际生产环境中,越来越多的行业领域都开始使用软件自动化来代替人工,相应的,计算机软件的稳定性、健壮性的影响也越来越大,计算机软件出现的错误所付出的代价也越来越大,目前微服务架构的兴起,也要面临其所带来的风险,数据一致性[3]的保证问题就是其中之一。
  目前针对微服务架构在分布式系统方面数据不一致情况有了一些研究和解决方案。文献[4]使用对关键业务进行整合的方法,将某些关联性极强的服务整合成一个服务,整合后自身使用事务管理来保证数据一致性。文献[5]采用了一种危机应对的机制,当任何一处发生异常时,触发一套针对异常的回滚事件,借此来使得整个系统来恢复到执行前的状态。文献[6]针对网络连接异常的问题进行了讨论和研究,设计了一个链路的检测机制来做到预先发现网络问题并进行处理,但是对于已经发生的数据不一致情况没有给出解决方案。
  1 业务流程概述
  本文针对微服务架构中存在的问题[7],重新设计了业务流程:业务从发送端的消息列表产生,也从发送端的消息列表结束,一个新的指令被创建的时刻将在消息列表进行记录和登记,接下来开始对该指令进行执行过程,每个关键点的执行都要对该列表内该事务状态进行更新,然后向指定位置发送消息,消息的接收者从指定话题中消费消息,将消息首先记录在本地消息列表中,然后再开始后续的执行过程,每个关键点的完成都要对列表内状态进行更新。
  2 关键模块概述
  针对以上业务流程分别设计五个关键模块,分别为业务发起模块、任务管理模块、消息发送模板、消息接收模块以及远程分布式消息队列模块。
  2.1 业务发起模块
  业务发起模块用于对一个新的业务进行发起。主要包括两方面功能,一方面是当该模块处于一个主动发起业务的服务中时,由服务在应用内部向该模块发送业务相关内容,该模块直接对该业务赋予一个唯一标记的Key值,生成相关任务条目信息将信息传送给任务管理模块,则为成功发起一项新的业务;另一方面当该模块处于一个被动接受指令的服务时,该模块从消息接收模块处接收任务指令,首先向任务管理模块发送请求对接收到的指令Key值进行核对,若该任务已经存在且尚未完成,则直接忽略处理,由任务管理模块自行处理,若该任务以完成,则由任务管理模块重新核对完成信息,由消息发送模块直接发送该任务完成的信息;若该任务不存在,则同新发起业务流程,生成必要信息递交任务管理模块。
  2.2 任务管理模块
  任务管理模块用于对所有已登记记录的任务进行管理。主要包括以下功能:1)对业务发起模块发出的查询请求进行回应,包括对Key值进行查重,向其返回查询状态和该任务状态。2)对业务发起模块所发起的业务进行登记,记录在任务列表当中,当该模块所在服务对该条任务的业务流程完成后,更新任务列表中的任务完成状态为已完成状态,对由于服务自身原因无法完成的任务标记为异常状态。3)定时扫描所有处于尚未完成状态的任务条目,向消息的发送模块递交发送任务结果请求;对于处于尚未完成状态但是最后发送时间较当前系统时间差值超过设定超时时间时,视该任务为超时,则直接向发送模块递交重发请求;对超时的任务但是发送次数已经超过预设阈值的条目进行标记失败,记录该条任务的全部信息,根据业务需求通知人工干预处理;对所有处于尚异常状态的任务递交消息发送模块进行转发处理。4)当该模块处于一个任务的发起服务时,将接收从消息接收模块递交的完成申请对该条任务的完成状态进行更新。
  2.3 消息发送模块
  消息发送模块用于根据其他模块递交的发送申请根据类型分类并整理为指定消息格式然后進行消息的发送和广播。该模块可以通过预设或者运行过程中动态改变发送Topic值来改变发送的目标;同时该模块下设一个后备列表,当该模块所在的服务由于种种原因不能完成该项业务,则想该后备列表查询与该服务功能相同的后备服务,然后将该异常任务直接递交给后备服务执行。
  2.4 消息接收模块
  消息接收模块包括被动消息监听守护模块和主动消息接收模块两个子模块。被动消息监听守护模块随服务启动监听固定的Topic,将获取的消息解读并根据分类递交给业务发起模块或者任务管理模块。主动消息获取模块可以在每次服务启动时或者是在预设阈值时间内没有接收到任何指令的情况下,或者在任务管理模块的指令下,使用底层API对远程分布式消息对列中当前终端的偏移量和本地记录的最近一次偏移量进行比较,若不相同则判定为有消息丢失,则根据实际情况重复消费指定偏移量的消息进行解读和递交。
  2.5 远程分布式消息队列模块   远程分布式消息队列模块处于发送与接收之间的中间件。本文使用Apache Kafka分布式队列[8]作为中间件,在本文所设计的整体机制中为所有的消息传递进行记录和落盘处理,由于其自身的特性,使用文件与偏移量的形式来实现消息队列,而且保证了每个用户分组只能有且只有一个用户消费到同一条消息,被消费过的消息不可重复消费,但是在本文设计的机制中由于需要对部分异常情况进行消息的补偿操作,所以使用该平台提供的低层API进行偏移量的操作[9];另外该分布式平台的落盘处理根据其节点的数量均有不同数量的备份,可以确保在部分节点宕机崩溃离线的情况下整个消息平台依旧可用且消息不丢失。最红该平台可以通过参数的设置来根据实际生产环境来设定定时对落盘的过久消息进行处理和清理,保证整个系统的资源占用。
  3 数据一致性保障机制
  根据上述描述,每个业务服务都可简单地理解为一个发送方和一个接收方的数据交互的组合,因此根据这一模型,可能会出现数据不一致的情况可能有如下几种:
  1)发送方成功发送业务请求,接收方成功接收,但此时发送方服务离线,在发送方重启后,可能会再次发送业务请求造成接收端重复执行相同指令。
  2)发送方成功发送业务请求,此时接收方离线,造成该消息丢失,进而该业务停滞无法继续进行。
  3)发送方成功发送业务请求,接收方成功接收该请求,两方自身业务成功执行,接收方发送指令回执,此时发送方离线,该消息丢失,在成该业务数据不一致。
  4)发送方成功发送业务请求,接收方刚刚接收该请求,接收方离线,造成该消息丢失。
  除此之外还有很多不可预料问题造成消息的丢失和消息的重复接收,进而造成数据不一致的发生。
  针对以上所可能发生的问题,根据微服务模块之间多种传输模式[10],采取如下一系列策略来保证数据的一致性:通过实现消息的幂等性来解决一切重复消费的问题,具体的实现方法体现在为每一条业务流程分配唯一的Key值,在接收到指令后首先对Key值进行核对如果出现重复则忽略该消息。通过引入一个外部的分布式消息队列来解决一切消息或者信息丢失的问题,具体实现方法体现在所有消息的传输均经过该消息队列,该消息队列对所有的消息进行罗盘存储,然后接收者通过消息队列进行消息的消费,通过一系列设置保证消息的百分百投递。通过对每一项业务进行记录,保证了所有自身环境的数据不一致的发生。通过对远程消息队列的偏移量的高级操作来实现在特定情况下对消息进行重复消费来保证数据一致性。
  4 模拟实验结果分析
  基于上述机制,本文使用Java线程模拟微服务场景,各个模拟微服务之间通过外部Kafka消息队列平台进行消息传输,然后通过手动阻塞的方式对微服务交互的每个阶段可能出现的离线情况进行模拟,用来检测该机制的处理情况。
  首先模拟正常通讯过程,服务A发起一个新的任务向服务B发送任务请求,同时执行自身业务逻辑,服务B接收到任务后执行自身业务逻辑,完成后向服务A发送完成回执,整个业务流程结束。
  第一次模拟服务A在发送指令之后崩溃离线,重启后重新执行该指令,造成对服务B的同一条指令的两次重复传递,服务B根据本条业务的Key值确定为重复指令,重复向服务A发送任务回执,保证了消息的幂等性。
  第二次模拟服务A发起业务并向服务B发送任务请求,服务B成功接收请求并执行自身业务逻辑,完成后向服务A发送任务完成回执,服务A成功接收回执,但是在对自身任务列表状态更改之前,服务A异常崩溃离线,重启后,根据启动机制,首先向远端消息列表查询当前偏移量和本地最后一次执行的偏移量做对比,发现出现误差,则前移偏移量重复消费上次的内容,获得服务B发送的消息回执,则此次业务流程完成。
  第三次模拟服务A发起业务并向服务B发送任务请求,服务B成功接收请求,但是在将请求记录在自身任务列表之前服务B异常崩溃,重启后,根据服务B自身启动机制,核对远端当前偏移量与自身本地偏移量,发现异常并重复消费,获取服务A发送的任务请求,正常执行业务流程。
  第四次模拟服务B接收到服务A的服务指令,但是在执行自身业务逻辑时由于自身问题无法完成该业务,则发送求助,此时服务C和服务D同处于该求助列表中,有且只有一个服务消费到了这条求助并执行B的任务,向A发送回执,保证该次业务流程完成。
  第五次模拟服务A发起一次业务流程,向服务B发送任务请求,但是由于一部分原因,服务B自身无法接收到该指令,因此,服务A在超时后再次向服务B发送同一条指令,发送超过规定次数后,服务A认为服务B已经离线,并且无法完成任务,于是向后备列表发送求助,此时服务C和服务D同时接收到求助,有且只有一个服务消费此求助,然后完成任务向服务A发送回执。
  本文设计并实现了在微服务架构中针对服务间数据交互中可能出现的各种导致数据不一致的问题的解决方案,该机制通过保证消息的幂等性,消息的落盘和每个服务对于偏移量的操作基本實现在较低的时延内在低时效性的业务模型中保证数据的最终一致性,通过人为模拟业务各个步骤当中可能出现的各类角色的离线情况验证该机制可以预防一定的数据不一致并且在数据不一致发生时能够触发一定的事件来对整个业务逻辑进行补偿,而且能够尽可能的单方自行解决,避免了在耗时较高的业务中重发等待时间过长导致的业务时延成倍增加问题,并且将该机制设计为服务模块可以随服务启动又可以独立于业务逻辑之外来保证该机制的运行。
  参考文献:
  [1] Dragoni N.Giallorenzo S.Lafuente A L et al-Microservices:yesterday, today, and tomorrow[Ml//Present and Ulterior Soft-ware Engineering. Cham: Springer Intemational Publishing,2017: 195-216.   [2] Pahl C,Jamshidi P.Microservices:a systematic mapping study[C]//Proceedings of the 6th International Conference on Cloud Computing and Services Science, April 23-25, 2016. Rome,It一aly. SCITEPRESS - Science and and Technology Publications, 2016: 137-146.
  [3]周婧,王意潔,阮炜,等.面向海量数据的数据一致性研究[Jl-计算机科学,2006,33(4):137-140,161.
  [4]徐进,黄勃,冯炯.基于消息通信的分布式系统最终一致性平台[J].计算机应用,2017,37(4):1157-1163.
  [5]孙赫勇.基于企业服务总线消息补偿方法的设计[J].微型机与应用,2013,32(10):90-91.
  [6]姜梦兰.基于消息中间件服务可靠性保障方案的研究与实现[D].成都:电子科技大学,2010.
  [7]李贞吴.微服务架构的发展与影响分析[Jl.信息系统工程, 2017(1):154-155.
  [8] Garg N.Apache Kafka[M]. 2013.
  [9]杜岳峰,申德荣,聂铁铮,等.基于关联数据的一致性和时效性清洗方法[J].计算机学报,2017,40(1):92-106.
  [10] Thones J.Microservices[J]. IEEE Software, 2015, 32(1):116.
  【通联编辑:谢媛媛】
  收稿日期:2020-01-25
  基金项目:教育大数据视域下学习干预模型构建与研究(项目编号:LPSSY201908)
  作者简介:杨成荣(1993-),男,河北衡水人,助教,硕士,研究方向为机器学习、数据处理;刘峻松(1995一),男,山东青岛人,硕士,研究方向为数据处理;孙新杰(1987-),男,河南驻马店人,副教授,硕士,研究方向为数据挖掘;吴超(1993-),男,江西鹰潭人,讲师,硕士,研究方向为数据处理。
转载注明来源:https://www.xzbu.com/8/view-15200441.htm