Amazon web services 仅在Aurora事务提交时调用Lambda函数,但保证调用(ACID)

Amazon web services 仅在Aurora事务提交时调用Lambda函数,但保证调用(ACID),amazon-web-services,microservices,amazon-aurora,Amazon Web Services,Microservices,Amazon Aurora,对于新项目中的微服务,我目前正在考虑是否使用DynamoDB或auroramysql作为底层数据存储。micro服务为用户界面提供了一个RESTAPI,还有其他几个micro服务。这些其他微服务应该侦听由UI连接服务生成的事件流(事件源),以保持其他读取模型同步 我试图找出一种方法来保证发布到变更事件流的事件与底层数据存储中的数据的变更完全匹配。通常,问题在于,如果REST API处理程序(例如)在执行过程中中途中断,它可能已经更改了数据,但尚未创建事件(假设更改事件在数据更改后发布)。我现在正

对于新项目中的微服务,我目前正在考虑是否使用DynamoDB或auroramysql作为底层数据存储。micro服务为用户界面提供了一个RESTAPI,还有其他几个micro服务。这些其他微服务应该侦听由UI连接服务生成的事件流(事件源),以保持其他读取模型同步

我试图找出一种方法来保证发布到变更事件流的事件与底层数据存储中的数据的变更完全匹配。通常,问题在于,如果REST API处理程序(例如)在执行过程中中途中断,它可能已经更改了数据,但尚未创建事件(假设更改事件在数据更改后发布)。我现在正在寻找能够减轻这种担忧的机制

对于DynamoDB,有DynamoDB流和AWS Lambda触发器,用于在数据存储级别对数据更改做出反应。触发的Lambda可以将低级数据更改转换为有意义的更改事件,然后将该事件发布到SNS、SQS或Kinesis

对于Aurora MySQL,我还没有想出这样的机制。我看过描述两种机制的文章:

  • 启用Aurora的二进制日志,并使用额外的EC2实例来处理更改流。从该流发布其他服务的事件
  • 使用本机lambda_sync或lambda_async函数从MySQL触发器调用lambda。从此Lambda中发布其他服务的事件
  • 首先,我对这两种方法都不太满意:1)我不希望管理额外的EC2实例和处理原始SQL更改。2) 我计划在Aurora中使用约束、乐观并发和事务,这意味着事务可以也将失败并回滚。但是,无论事务结果如何,都将执行lambda(a)sync调用

    对极光有更好的想法吗?还是我从错误的角度看待这个问题


    我想把这个问题和讨论的重点放在如何保证底层数据存储的更改和带有更改事件的传出流之间的一致性上,而不是放在Aurora和DynamoDB上。

    我找到了一个适合我们情况的答案,使用Aurora和MySQL兼容。在我的研究过程中,我发现了一个极好的信息来源。具体来说,关于的页面引用了四种相关模式,以保证更新状态和发布事件的原子性

    • 活动来源
    • 应用程序事件
    • 数据库触发器
    • 事务日志跟踪
    事件来源是不可能的,因为它对于我们想要实现的目标来说太复杂了。在我最初的问题中,我已经反对tx日志拖尾。应用程序事件和DB触发器非常相似,因为作为事务的一部分,状态被更新,并且条目被写入事件表:Tx成功提交,状态被持久化,事件条目显示在该表中。Tx回滚,状态不变,不显示任何事件条目。两者之间的唯一区别在于事件条目是由应用程序/服务逻辑本身生成的,还是由DB触发器生成的

    然后,一个外部进程轮询该表,并根据事件条目发布其他微服务的事件(当然,随后会删除已发布的事件)。这两种模式保证一个状态更改总是导致至少一个事件(恰好一次会稍微复杂一些)

    现在关于如何实现这一点。。。我的第一个想法是使用Fargate容器和进行轮询的节点应用程序,我认为使用此解决方案可以保持无服务器状态。然而,事实证明并非如此:为了保证事件的顺序,应该只有一个容器轮询和发布。一个Fargate容器被分配给一个可用区域,如果该区域“消失”,容器也会消失。现在,我必须在顶部构建某种监控,以便在需要时在不同的AZ#2中实例化一个新的容器#2。但是如果AZ#1和container#1回来呢?那么就有两个例子。这太复杂了

    现在我决定采用以下方法:CloudWatch事件每分钟触发一次轮询Lambda函数(CW的最小间隔)。一旦调用,函数将继续轮询DB,直到一分钟后第二次Lambda函数调用结束。为了协调两个Lambda函数调用,我在我的DB中创建了第二个表Event Polling State,其中最新的Lambda函数调用更新该表中的一个专用行,并向上一个函数调用指示它已启动(这是在SELECT…for UPDATE和TXs的帮助下完成的,以防止争用情况)。在每个轮询周期之前,如果在此期间没有其他函数启动,该函数将检查处于事件轮询状态的行

    这种方法的优点(在我看来):

    • 真正的无服务器和AZ-,VPC,无子网
    • 事件的顺序是有保证的,因为不会有多个Lambda调用并行轮询和发布
    • 如果轮询Lambda函数因任何原因终止(例如,因为AZ消失),则发布间隔最多为1分钟,直到CloudWatch下次调用Lambda函数。这个差距是可以接受的