0%

Newbe.Claptrap 框架中 State 和 Event 应该如何理解?

Newbe.Claptrap 框架中 State 和 Event 应该如何理解?最近整理了一下项目的术语表。今天就谈谈什么是 Event 和 State。

Newbe.Claptrap 是一个用于轻松应对并发问题的分布式开发框架。如果您是首次阅读本系列文章。建议可以先从本文末尾的入门文章开始了解。

事件 Event

Claptrap 是基于事件溯源的 Actor 模式。事件自然就起到了至关重要的作用。

想要操作 Claptrap 就需要对其传递事件。事件也是改变 Claptrap State 的唯一参数。因此,在使用 Claptrap 构建系统时,所有的系统操作都会转换为事件而传入到 Claptrap 中。事件具有以下这些特点:

事件是有序的

每个事件都包含有一个唯一的序列号。在本框架中,这个序列号被称为版本号(Version)。事件的版本号是一个从 1 开始逐 1 递增的序列。事件的有序性,确保了状态的计算不存在并发问题。这是状态数据可靠性的重要保证。

事件的有序性直接反应了 Claptrap 执行事件的先后顺序。而由于需要确保这种顺序,Claptrap 在执行事件时,必须逐个事件进行处理。这点恰好与 Actor 模式的单线程特性产生了天然的契合。

事件是不可变的

事件一旦产生,它就是不可变的。事件溯源,正由于事件的不可变性,才使得数据是可靠的。因为只要读取事件,就能够还原出任何一个事件执行之后的状态。但不可变性并不是物理上的限制。你仍然可以修改物理存储中的事件数据。但请注意,这是危险的,极为不建议的行为。

让我们联系设计模式中的“开闭原则”,经典的可以被概括为“对扩展开放,对修改封闭”。其中为什么要强调“对修改封闭”呢?就笔者看来,对修改封闭的原因其实是因为修改所带来的未知性。因为过往执行的代码,产生的数据。他们都已经形成了一定的封闭性。他们是经过已有的测试所验证的。如果尝试修改他们,势必就需要调整相应的测试,而这就更进一步加剧了修改,这可不是一件好事。事件的不可变是一种性质,更是一种要求。

那如果由于一个 BUG 导致了过往的产生事件数据不正确,现在需要修正这个 BUG,该怎么办呢?笔者的建议,不要尝试修改已有的事件。应该追加新的事件和算法来修正当前的状态。不要去调整旧的内容。笔者认为这更符合开闭原则。开发者可以自行斟酌。

事件是永久的

事件是确保 Claptrap State 正确性的重要参数。因此,需要确保事件被永久保存。但,这不是绝对的情况,如果满足以下条件,那么事件就允许被丢失:

  1. 在丢失事件之前存在一个永久的 State 快照
  2. 对应的 Claptrap 已经生命终结,永远都不会再被激活

反之,如果不满足以上的条件,那么请必须确保在生产环境中的事件被正确的保存在持久化层,并且已经有相应的容灾手段。

状态 State

State 在 Actor 模式中代表了 Actor 对象当前的数据表现。而在 Claptrap 仅仅只是在此之上增加了一个限制:“State 只能通过事件溯源的方式进行更新”。由于事件溯源的可靠性。Claptrap 中的 State 也就拥有了更好的可靠性。

State 的版本号。在 Claptrap 中的 State 中有一个名为 Version 的属性,它表示 State 当前的版本。版本号是一个从 0 开始的自增数字,会在每次处理一个事件之后进行自增。

版本号为 0 的 State 是 Claptrap 的初始状态,也可以被称为创世状态。初始状态可以根据业务需要进行定制。

Claptrap 和 Minion 对于版本号的处理也有一些区别。

对于 Claptrap 而言,Claptrap 是事件的生产者,因此,事件的版本号本身就是由 Claptrap 进行赋予的。例如,在一次事件的处理过程中,以下这些事情将会依次发生:

  1. State Version = 1000
  2. 开始处理 Event ,其 Version = State Version + 1 = 1001
  3. Event 处理完毕,更新 State Version = 1001

对于 Minion 而言,由于它是 Claptrap 事件的消费者。因此版本号的处理略有不同。例如,在一次事件的处理过程中,以下事件将会依次发生:

  1. State Version = 1000
  2. 读取到了 Event Version 为 1001 的事件
  3. Event 处理完毕,更新 State Version = 1001

State 的版本号和 Event 的版本号相互依存,相互验证,是事件有序性的关键。如果在处理过程中,出现 State 的版本号和 Event 的版本号不匹配的情况,将会是严重的问题。通常来说,出现版本号不匹配,只有两种情况:

  1. 持久化层中的事件出现了丢失
  2. 框架恶性 BUG

最后但是最重要!

最近作者正在构建以反应式Actor模式事件溯源为理论基础的一套服务端开发框架。希望为开发者提供能够便于开发出“分布式”、“可水平扩展”、“可测试性高”的应用系统——Newbe.Claptrap

本篇文章是该框架的一篇技术选文,属于技术构成的一部分。如果读者对该内容感兴趣,欢迎转发、评论、收藏文章以及项目。您的支持是促进项目成功的关键。

联系方式:

您还可以查阅本系列的其他选文:

理论入门篇

  1. Newbe.Claptrap-一套以“事件溯源”和“Actor模式”作为基本理论的服务端开发框架

术语介绍篇

  1. Actor 模式
  2. 事件溯源(Event Sourcing)
  3. Claptrap
  4. Minion
  5. 事件 (Event)
  6. 状态 (State)
  7. 状态快照 (State Snapshot)
  8. Claptrap 设计图 (Claptrap Design)
  9. Claptrap 工厂 (Claptrap Factory)
  10. Claptrap Identity
  11. Claptrap Box
  12. Claptrap 生命周期(Claptrap Lifetime Scope)
  13. 序列化(Serialization)

实现入门篇

  1. Newbe.Claptrap框架入门,第一步——创建项目,实现简易购物车
  2. Newbe.Claptrap框架入门,第二步——简单业务,清空购物车

样例实践篇

  1. 构建一个简易的火车票售票系统,Newbe.Claptrap框架用例,第一步——业务分析
  2. 在线体验火车票售票系统

其他番外篇

  1. 谈反应式编程在服务端中的应用,数据库操作优化,从20秒到0.5秒
  2. 谈反应式编程在服务端中的应用,数据库操作优化,提速 Upsert
  3. 十万同时在线用户,需要多少内存?——Newbe.Claptrap框架水平扩展实验
  4. docker-mcr 助您全速下载 dotnet 镜像
  5. 十多位全球技术专家,为你献上近十个小时的.Net微服务介绍

GitHub 项目地址:https://github.com/newbe36524/Newbe.Claptrap

Gitee 项目地址:https://gitee.com/yks/Newbe.Claptrap

您当前查看的是先行发布于 www.newbe.pro 上的博客文章,实际开发文档随版本而迭代。若要查看最新的开发文档,需要移步 claptrap.newbe.pro

Newbe.Claptrap

------ 本文结束------