数字化转型与架构 - 架构设计篇|建模之“动态”模型
在上一篇文章中介绍了建模的原因和“静态”的模型,本章节开始介绍另一类“动态”模型。
建模多以静态图形的方式呈现在大家面前。“静态”模型中通过各种形状表示业务实体,用线段表示实体之间的关系。那么实体自身的状态变化通过什么方式表达?实体对象受外部事件的影响,自身的状态会发生变化。这种状态变化,可以用状态机模型进行描述。
状态机模型
状态机描述的是一个实体从创建到最终消亡的全生命周期。每一个实体被一个个的具体事件改变自身的状态。事件(Event)是在特点时间或条件下发生的情况或动作。像我们的人生一样,有求学阶段、工作阶段、退休阶段。求学结束后,进入工作阶段;达到退休年龄后,进入退休阶段。毕业和达到退休年龄就是人生的两个事件。
在绘制状态机模型前,我们首先应确保生命周期完整;其次要找出改变实体的每一个事件并确认关键事件;最后还需要确认各阶段对实体操作的限制。下面将以大家熟悉的订单状态机为例。
订单在用户提交购物列表、优惠活动、提货方式之后被创建,进入到订单最初始的阶段。订单的“完结”却有很多种情况,用户放弃支付、用户取消订单、用户确认收货、用户退货、用户换货、用户售后服务。因此这些“完结”状态其实都是可以进入结束状态的前置状态。
状态转换表示意图
订单创建时被提交、顾客完成支付、商家发货、顾客确认收货都是几个关键节点。在发货之前,我们都可以修改收货地址。地址修改是对订单实体的一个修改事件,但并不影响订单状态的转换,所以不是关键节点。修改事件作为订单的一个操作,需要在系统中进行记录,但不是改变订单状态的一个事件。
订单状态机示意图
特定的操作可以改变状态,特定的状态也限制着不同的操作。例如订单提交之后有支付、修改地址和取消订单三个操作。当订单支付之后,订单状态变更为顾客完成支付,同时也不能再次进行支付操作。
并发模型
独立实体的状态变化由状态机模型描述,实体处理过程中程序如何协同工作就需要并发模型进行描述。
计算机硬件系统中,CPU、内存、存储的速度逐级递减。为了更好的使用 CPU 的资源,操作系统首先实现了进程复制功能,即 fork 操作。运行中的进程通过调用 fork 函数,创建出一个新的进程,此进程被称为子进程,调用 fork 函数的进程称为父进程。子进程本身与原进程一样,只是为了独立处理父线程交给的任务。当任务处理完成之后,此进程退出并通知父进程,退出和通知的操作叫 join。即进程之后还有线程和协程,线程也是操作系统级别的功能,但协程是语言的特性。这些方式虽然可以带来性能的提升,但也是导致很多隐藏 bug 的元凶。
最常见的“fork”模式是各种 Web 服务框架使用的多线程模型。进程会创建一定数量的线程,当请求过来时,进程将请求分配给一个线程独立处理。每个线程处理完一个请求后再等待处理下一个请求,可以认为线程处在一个“死循环”的状态。对多线程模型的线程进行动态创建和回收,就成为了线程池模型。
当有多个进程处理同一个请求时,就会引起资源的竞争。不对资源进行保护,就会导致资源被破坏形成脏数据;对资源进行保护,系统从并行处理模式又退化回顺序处理模式。
多线程模型示意图
在处理一个业务请求时,可能需要创建进程分头去处理多个操作,此时就需要考虑如何处理 Join 的操作。当需要获取返回结果时,父线程就必须等待并处理 Join 操作。像缓存更新操作,是一个“非必须”确认操作,往往因为没有确认,出现偶发性问题。
Join 示意图
“动态”模型弥补了“静态”模型描述运行过程方面的不足。特别是运行过程中的限制及互相之间可能存在的干扰。下一篇文章将讲述数据模型。
版权声明: 本文为 InfoQ 作者【数字随行】的原创文章。
原文链接:【http://xie.infoq.cn/article/c13f1aec89e658d9372ed2b8c】。文章转载请联系作者。
评论