架构系列谈二: 映射

架构小课堂

架构从成型的时间维度看,一般来说可以分为业务架构、系统架构、部署架构,其中系统架构有时还包括数据架构,这里不单独列出。

大家知道,我们开发软件是为了解决业务问题,目标是把业务领域里面的知识抽象重新组织固化到软件代码中。

一般来说,业务知识固化到软件过程中,复杂度来源于以下方面:

  • 业务本身的复杂度
  • 软件实现的复杂度
  • 软件部署的复杂度

比如:一个泛电商系统,在流量比较小的时候,我们会抽象出:

用户管理

订单管理

支付管理

商品管理

等业务模块部分,然后给出这些模内部的核心元素以及元素的附加属性,并明确它们之间的上下游依赖关系,这就成了业务架构

抽象出:

列表页

详情页

下单页

货架页

订单处理页

作为展示层,逻辑处理作为服务层,数据库增删改查作为持久化层,这些作为系统架构

流量小的时候可以采用容器单机部署,流量逐步增大可以在

做负荷分担;

数据量较大时(单表超过1000w条数据)考虑数据库层做分库分表或者引入auto sharding数据库等;

同时考虑数据均衡访问均衡、数据平滑升级等,这些属于部署架构。

业务架构是纲,纲举则目张,它是整个架构设计的基础和起点。

业务架构的抽象一部分在本业务领域内,另一部分可能在本领域没有好的解决方案,可以采用映射的方式到另一个合适领域(该领域有较好处理该类问题的方案)并利用该领域专有知识进行建模,然后对问题进行求解答案,最后再把答案转换到原问题领域。

解决问题时通过映射的方式,有很多的实例。

比如:我们要跟一个不懂中文的人解释汉字“走”,一种方式可以把“走”拆解成详细步骤,演示给他看:

先迈左腿

然后甩右胳膊

胯往前送

然后告诉他这就是走。

另一种方式,就是告诉他“walk”,这就是映射到英文的领域,利用该领域的已有背景知识和思路进行解决。

大家经常讨论淘宝和京东的不同,其实如果不看电商,而是映射到实体商业,淘宝应该是商铺,出租出去供商户经营,靠租金收入。京东应该是商城,自营为主。

对于工程数学里面也有很多通过映射解决问题的例子,比如拉普拉斯变换就是将实数领域不易解决的问题映射到复数领域解决,类似还有傅里叶变换等。

人工智能领域中神经网络方面应用,

无论是FNN、CNN、RNN、LSTM等,其都是把线性不可分问题通过矩阵映射为线性可分问题,从而解决。

软件系统也有很多映射建模的应用,

比如:大家很熟悉的报数编程题:

它其实就是不同报数规则之间的逻辑组合,可以映射到关系逻辑的领域来解决,实现了and和or这两个逻辑,就可以实现不同报数逻辑的灵活定制。

其中,M3表示可以整除3的规则,C3表示包含3的规则,其余以此类推。

再比如:数据库里面sql语句其实就是映射到关系代数,sql里面的相关操作映射到关系代数的选择、投影(去重)、叉乘、差、并、交、除等操作。

make编译其实就是映射到依赖树管理,目标、关联、动作构成的三元组作为树的节点,最后对树进行深度遍历。

下面讲一个我们使用映射的思路解决状态机状态爆炸问题的思路。

大家都知道,电信领域中的核心网业务处理大部分都可以映射为状态机 操作,当业务流程比较复杂,需要引入大量 非稳态状态 的时候,这时稳态、非稳态状态之间会引发大量的 排列组合,排列组合的同时又和 时序 强相关,这时无论使用if else还是使用状态模式,都不可避免的要应对状态机状态爆炸的问题,业务逻辑深度耦合后,要实现的正确就变得及其困难。

我们当时碰到情况是程控电话控制流程,拿其中比较简单一个业务流程如拨号处理为例:

这是个典型的状态机,整个过程都是异步处理,这里做一些简化,分以下步骤:

1

步骤一

收到用户摘机消息,发指令给硬件播放拨号音,状态机跃迁到等待拨号音播放 状态(state1)

2

步骤二

硬件返回拨号音播放成功,状态机跃迁等待拨号 状态(state2)

3

步骤三

收到用户拨号消息,状态跃迁到接收拨号音状态(state3),循环接受用户拨号。

理想情况下以上3个状态都是稳态,状态机比较好处理。

现实总比理想要严酷,碰到一个急性子用户,他摘机后,不等播放拨号音就开始拨号,即state1的时候收到了不期望的state3的消息,怎么办?

一种处理方法是直接把不期望的消息丢弃,跳回state1,即只认拨号音播放后的拨号。

这样处理简单,但是会造成用户拨号混乱,体验差。

另一种做法是增加一个非稳态:等待拨号音播放同时接收用户拨号状态(state13),修改如下:

1

步骤一

步骤1后面增加一个步骤

1.1,收到拨号音,跳转到state13,循环接受拨号。

2

步骤二

修改步骤2,硬件返回拨号音播放成功,如果 state13,跃迁到state3;若干state1,跃迁到state2,已经记录的号码同时传递过去。

这里只是增加了一个非稳态,就需求和其他状态进行排列组合;

实际业务中由于用户操作中复杂场景和硬件强耦合,临时状态会非常多,状态之间排列组合也将非常多,从而造成状态爆炸。

状态爆炸其本质就是当前状态下,收到不期望收到的消息,考虑高可用性场景,又不能丢弃,只能先缓存,等需要的时候再取出。

这个过程和邮箱很相似,为了应对这种场景,我们可以把模型映射到邮箱机制:

1

为每个用户设立一个mailbox,之所以不是整个系统一个mailbox,主要考虑性能。

2

引入receive元语

当前步骤为step0:先遍历mailbox,找到当前步骤需要的邮件,走下面步骤step1;

没有想要的邮件的话,就等待新邮件,收到不想要邮件就存入mailbox后继续等待,直到收到期望的邮件走step1 超时处理;当然实际代码中会对mailbox的容量和邮件存取做优化。

对应到拨号流程

直接使用

1、收到用户摘机消息,发指令给硬件播放拨号音,状态机跃迁到等待拨号音播放状态(state1)

2、硬件返回拨号音播放成功,状态机跃迁等待拨号状态(state2)

3、收到用户拨号消息,状态跃迁到接收拨号音状态(state3),循环接受用户拨号。

综上,映射是一种非常重要的业务架构设计思路,其本质是让知识穿过身体,对业务领域的洞察后抽象,然后在另一个合适领域打一个恰当的比方,这个比方在该领域很容易被理解和实现,这就是映射。

土鳖扛铁牛(to be)

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/213236.html

联系我们
联系我们
分享本页
返回顶部