分享

分布式系统架构规范

 天下小粮仓 2018-05-12

1

前言

本系统架构规范仅适用于中型系统和大型系统,对此类项目,一般需要较多人员的参与,如不在开发进行之前定义好一些规范、原则,很容易在开发中产生各种各样的问题,如功能切分不合理、服务拆分粒度不足、数据冗余、性能受影响等各式各样的问题。在构建此类系统前,我们要进行统一的系统层级的设计,来尽量避免文中这些问题的出现。

对于影响不大、重要性不大或存活时间不久的项目,可以采用更为灵活的方式进行自行开发,以免过多人力投入产生浪费。

1

技术选型

应以满足系统的需求为出发,考虑选择某个技术对整个系统生命周期的影响:

1.需求层面的影响

是否能够满足当前或未来的业务需求,在整个系统生命周期中,应该优先满足目前业务情况,再考虑未来不确定的业务需求。

2.系统设计层面的影响

系统设计时需要考虑技术特性对整个系统生命周期的适应性,稳定性,可替代性,可维护性,是否可以跨平台,以及开发难度的综合考量,避免系统依赖于某项专用技术,或者和某项技术耦合紧密,降低技术选型变更成本。

3.系统开发层面的影响

应当为开发人员提供技术相关使用文档,以及入门指南等技术资料,应以技术透明为原则做好技术封装工作,和应用规范,减轻开发人员使用该技术的难度,降低开发人员学习成本。

4.系统实施层面的影响

应当考虑所采用技术在实施安装部署的技术难度以及硬件的兼容性,稳定性,以及资源消耗问题。并提供系统所采用技术安装部署操作文档。

5.技术实现难度的评估

评估所选技术实现的难点,算法,技术团队是否能够很好的掌握和使用,开发时间,以及是否会提高系统复杂程度。

6.技术的优缺点评估及同类技术之间差异评估

调研所选技术在行业内是否普遍认可和使用,社区维护情况,系统版本是否趋于成熟稳定的状态

7.技术是否开源以及是否成熟稳定

1 接口以及协议

1.1 原子性

接口原子性,包含三个层面的定义,一个是接口数据的粒度定义,一个是接口在进行写操作的不可打断原则,一个是组合接口的数据拼装的完整。

1. 接口粒度:定义的粒度是否合适,是否充分考虑接口使用者需求。接口定义是否清晰,通用以及粒度适中原则。

2. 不可打断:接口调用是不可被打断的,如果调用失败则数据不会被修改,要么成功要么失败。

3. 组合接口:是指某个接口的数据来源于其它多个接口的数据进行拼装的结果,这时接口要么返回其它接口都正常返回进行拼装的数据,要么返回接口异常。

原则上,对于服务系统,其接口应该是完成单独的某个功能,应该提供原子级(不可再拆分)的接口,某个复杂的功能,可拆分成几个不同的接口调用来完成。对于原子级的接口,出错回滚处理也会比较简单。对于原子级别接口的定义,应当基于对数据操作的不可打断为原则,例如:用户下单,需要扣减库存生成订单两个数据操作步骤,正确定义:提供创建订单接口,在创建订单接口里进行库存扣减,错误定义:创建订单接口+库存扣减接口

1.2 可组合性

1. 基于接口的原子粒度,根据不同的业务需要,灵活调整接口的拼装调用,完成业务需求的快速实现。

2. 定义接口时,要区分服务系统和业务系统或是业务服务组合的系统,服务系统完成服务的提供,业务系统完成业务的封装和转发调用。

3. 组合性的接口原则上只用于数据的读取进行组合,当接口存在写操作时,则不建议用组合接口的方式完成事务工作。具体参考<数据:原子性>

1.3 可读性

1. 所有系统提供的接口文档,应该是统一、规范的、格式一致的。

2. 接口文档的定义,可读,可理解。在接口中,完整的定义好上传报文和返回报文的相关字段、报文头、报文格式的规范。

3. 接口字段中的数据字典要明晰,每个字段代表的意义要明确,每个标准数据对应的值,要明确,或标明在哪里可以查询(附录或其他)。

4. 不同的服务系统,应有统一的接口命名规则,可根据服务模块直接查找响应接口功能及要求,并可在代码内简单查找。

5. 接口还应该明示接口是否会对数据进行读或写的操作。

1.4 兼容性

1. 接口的调用如果产生异常,或接口参数非法等情况时,接口是否做到充分的提示。

2. 系统接口设计,要避免依赖于开发语言特性,应考虑兼容于其它开发语言为原则。

3. 接口是否充分考虑了各种终端的接入,不同开发语言间的接入等

4. 接口应当考虑不同开发语言对于数据类型的定义与区别,应当避免不同语言对数据类型的解析问题,例如:java的doubble类型,在php里面是有区别的。

1.5 独立性

每个接口都应该是独立可被调用的,不因依赖于其它接口被调用为前提才可以正常被调用。接口的调用不依赖于会话状态的建立,接口调用者只需根据接口参数的定义,满足于接口调用的参数要求后既可正常调用接口返回相应数据。

1.6 安全性

1. 接口是否公开开放,如果开放是否充分考虑接口调用的合法性问题,如果接口被非法调用怎么处理。

2. 接口调用者的合法性校验。

3. 接口是否有做入参的合法性检查。

4. 接口应当仅限于内部系统网络可以访问,并且具有安全性的检测机制防止接口异常调用的发生,非开放式接口不应暴露于公网环境

5. 开放接口必须要做好接口鉴权工作,不允许任何一个接口绕过鉴权直接调用,以及做好沙箱隔离。

1

数据

数据是系统的产出结果,数据的一致性、原子性、完整性、隔离性直接反映了系统架构设计是否合理以及是否严谨。维护数据的一致性,原子性,完整性,隔离性需要系统在各个层面(数据库设计,系统架构设计,事务处理机制,编码规范)进行系统的设计规划以及对编码有严格的约束和要求,才能够很好的保证数据的四性要求。在数据操作中,事务对于数据的四性原则起到关键作用,事务操作确保了数据的真实有效。在系统中事务操作,不仅指数据库的事务还指业务逻辑的事务。良好的系统架构理应对数据的四性,以及事务的粒度做到统一的平衡保证系统在高负荷情况下也不会崩溃以及数据出错。

1.1 一致性

在系统设计时,跨系统之间的调用要考虑事务数据的一致性,要么A系统和B系统成功完成数据操作,要么A系统和B系统都回滚。系统需要考虑异步处理时保障数据的一致性,不因系统的异步处理导致数据的不一致因而导致数据失真。系统需要保障数据在系统于系统之间,模块于模块之间,同一时间数据是一致的。

跨系统间的数据要保障数据最终一致性。

数据的一致性也包括在跨系统或模块之间对同一数据的定义也应当是一致的,例如用户名称的数据类型以及长度或格式等在不同系统中对用户名称的数据类型是一致的,长度是一致的,数据格式也是一致的。

1.2 原子性

数据的原子性是指,在系统中的业务处理逻辑被执行时导致的数据(创建、修改、删除、文件保存、删除、改名)变更,在整个事务中或许存在多次的数据操作,此时在进入某个数据操作时发生异常应当回滚之前完成的数据操作,以保障本事务要么全部数据修改完成要么全部不做修改。

这里的数据原子性区别于接口的原子性,接口的原子性还包含了接口粒度的原子性,即接口的粒度小到不能再拆分的。

1.3 完整性

系统需要保障用户操作的数据是完整的,在数据库设计时应当考虑好表之间的数据约束关系。代码层面主表与外表的数据操作应当在同一个事务里面完成,不可分割不可打断。

当某个表数据操作失败时,相应的其它表数据的修改也需要同时回滚。

尤其在跨系统间的数据操作,必须保证同一数据A系统存在,B系统对应存在,这设计到分布式事务的处理机制。

数据的完整性,不仅包含于数据库表之间的完整性,还包含于系统的业务逻辑中,假如上传一个商品,其中包含图片信息,商品信息,分别存放于文件服务器,以及多个商品表中,这时应当完整保存商品数据到对应的商品表中以及文件服务器中,如果其中一个表或一个文件保存异常,应当全部回滚保障数据的完整性。

数据的完整性,还包含于单个表内的数据完整,假如用户录入信息必须包含时间,如果用户没有填写时间则也不应当保存数据。这除了数据库范式进行约束,在代码层面也应当进行约束,以保障数据的完整性。

1.4 持久性

数据修改后,对系统的影响是永久性的,即使系统停机或故障也不会丢失修改后的数据。数据的持久性不仅限于数据是否正常保存到数据库当中,还包括数据保存介质的可靠,以及保存的数据是否有冗余备份,在数据存储环节出现故障或其它不可遇见的风险时,如何保障数据长久的安全和不丢失。

持久性的另一层意思,是在系统经过持续的更新升级后,老的数据,是否还可以被系统使用的,可读的,可追查的,以及可以被转化再利用的。

当系统出现故障时或硬件出现故障时能保证系统及时恢复故障前的数据。

1.5 隔离性

系统与系统间或模块与模块之间对同一数据的操作需要遵循一定原则,避免事务死锁的情况发生,保障系统和模块间的事务操作是隔离的,不会导致A,B,C三个数据之间互相等待对方锁的情况发生。假如三个事务同时需要对三个数据A,B,C进行操作,这应当遵循优先操作A数据的事务肯定也会优先操作B数据和C数据。数据的隔离性需要在系统设计和编码阶段尤其需要考虑的工作。事务的隔离直接影响到系统的稳定性以及系统的可用性。严重情况会导致整个系统崩溃无法运行和导致数据出错。以下举例错误的事务隔离和正确的事务隔离例子

错误的事务隔离:X事务与Y事务需要同时对A,B数据进行操作,此时X事务的操作顺序是BA而Y事务的操作顺序是AB,在极端情况下X事务在锁定B数据后等待A数据的锁释放,而同时Y事务才锁定A数据后等待B数据释放锁,进而X事务与Y事务循环等待对方释放锁导致数据的死锁问题。

正确的事务隔离:X事务与Y事务需要同时对A,B数据进行操作,此时X事务的操作顺序是AB而Y事务的操作顺序也是AB,在极端情况下X事务在锁定A数据后,此时由于Y事务也优先操作A数据只能等待X事务完成后Y事务再继续操作,进而避免了事务之间循环等待对方事务释放所的可能。

数据的隔离也既事务的隔离,在分布式系统在多个事务对同一数据的操作应当遵循先启动事务者先锁定数据的原则,进行事务操作。

1.6 可移植性

在大型的分布式系统中,不可避免的存在不同系统使用不同的数据库以及数据库版本的不一致问题,虽然可移植性不是系统架构的必须要求,但基于数据的可移植性考虑,在数据定义时应当避免使用数据库特性来定义数据属性,数据的定义应当兼容于不同数据库的种类,数据库使用的版本等。在架构设计时应当优先考虑统一使用统一厂商的数据库品种以及同一版本的数据库为原则,尽可能避免数据库移植产生的转换成本。

1.7 标准数据定义

系统中存在的常见数据字典的定义,业务状态数据等的数据要有标准的定义名单。

标准数据定义一般是指跨系统或模块之间广泛使用的以及频繁被使用的数据,或业务状态数据,对标准数据定义的名字应当人机可读的并遵循固定的命名规则,便于开发人员理解以及使用。

标准数据的定义,应当广泛考虑在各个场景中使用的普遍适用程度,以及在跨系统和跨语言之间的通用性,避免使用特定语言的数据类型或格式。

1

系统

设计软件系统的模块层次结构,设计数据库的结构以及设计模块的控制流程,其目的是明确软件系统"如何做"。这个阶段又分两个步骤:概要设计和详细设计。概要设计解决软件系统的模块划分和模块的层次结构以及数据库设计;详细设计解决每个模块的控制流程,内部算法和数据结构的设计。这个阶段结束,要交付概要设计说明书和设计说明,也可以合并在一起,称为设计说明书。

在系统分析的基础上,设计出能满足预定目标的系统的过程。系统设计内容主要包括:确定设计方针和方法,将系统分解为若干子系统,确定各子系统的目标、功能及其相互关系,决定对子系统的管理体制和控制方式,对各子系统进行技术设计和评价,对全系统进行技术设计和评价等。

系统设计需要考虑的原则,必须遵循并考虑以下问题。

1.1 系统可靠性

系统的可靠性与系统的稳定性紧密相关,系统的可靠性往往建立在系统的稳定性基础之上,这里对系统的可靠性仅限于在系统发生不可预测的故障问题时对系统的影响程度的要求,原则上基础设施没有大面积瘫痪的基础上系统应当都能够可靠的运行并提供应有的服务。

系统运行中某个独立模块发生故障,不应当影响其它不相关模块的正常运行,系统故障时能够及时恢复系统或新增机器资源保障系统能够正常继续工作,系统不因硬件的故障问题导致整个系统瘫痪无法运行。

平均无故障时间,系统平均正常运行多长时间才发生一次故障

1.2 系统稳定性

系统的稳定性主要考虑下列各项指标因素,系统的稳定性也间接反应系统的架构设计的优劣以及代码质量优劣问题。

1. 系统在无外界干预情况下是否能长期稳定运行

2. 系统在高负荷情况下是否能正常运行不影响用户使用

3. 系统在受到网络攻击时是否能够正常运行

4. 系统在受到网络资源限制时是否能够正常运行

5. 系统在受到内存资源瓶颈时是否能够正常运行

6. 系统在受到CPU资源瓶颈时是否能够正常运行

7. 系统在受到磁盘资源瓶颈是是否能够正常运行

1.3 系统安全性

系统安全性包括系统能够鉴别非法和合法用户的安全性以及用户对数据操作的安全性,隔离非授权用户对数据的访问以及操作,另外对于合法用户也需要做到鉴别非法数据的输入鉴别处理。

授权:在需要授权的操作中,如果用户未获得授权许可应当决绝用户对数据的操作行为。

注入:往往非法的入侵伴随着系统存在着可以被注入恶意代码的漏洞,注入方式有web脚本注入,sql注入,可执行命令注入或堆栈溢出漏洞等,系统应当在用户提交的数据中做好数据的合法性检查。

1.4 系统扩展性

系统应当具有新的功能模块扩展的能力,不因新需求的增加而造成系统的重大变更甚至重构才能满足需求。系统的扩展性不仅限于新功能的可扩展,还包括无用功能的移除也不应造成系统重大的变更或重构才能完成。

系统的扩展性还包括计算能力的可扩展性,当系统负荷压力超过单机能够完成的计算量时,系统能够动态的增加机器资源完成负载压力的分布,降低系统的计算压力,当系统压力下降后能够自动的或手动的撤销机器资源。

系统还应支持数据存储层面的扩展,在系统的存储层面已经产生瓶颈时系统能够支持存储的扩展以其能够很好的解决数据存储的瓶颈而不至于整个系统重构或做出很大的变更来满足拓展存储的需求瓶颈。

1.5 系统移植性

系统的设计时应当注意避免使用某项技术的特性来构建系统,尽可能使用技术的标准件,或对某项技术做好封装和隔离并考虑后备方案。

例如:系统在使用tomcat时,不应依赖于tomcat特有的技术特性,如果系统移植到jboss时则会导致系统无法正常运行。

1. 系统环境能够自由切换到不同云平台

系统设计时应当考虑在各种云平台中能够正常运行而不限制于特定的平台技术限制。同时也应当考虑系统能够运行在不同操作系统以及不同硬件机器资源,而不依赖于特定的硬件或特定的操作系统以及某种技术。

系统应当支持所用操作系统的版本升级,例如操作系统更新升级后不会影响系统的正常运行。

2. 系统环境是否可自行部署

系统安装部署应当能够脱离开发人员自行部署,其它人员根据安装部署文件即可完成部署工作,不因为使用某种技术而需要开发人员协助才能安装部署。

3. 系统是否依赖于特定硬件

如果没有特殊需求,系统不应依赖于特定的硬件作为系统的必须条件,系统应当支持所用的硬件升级,硬件升级而不影响系统正常运行。

4. 系统是否依赖于特定技术

系统所使用技术当发现有一定风险或存在隐患时能够比较容易的迁移到其它技术方案替代,而不会导致系统发生颠覆式的重构或无法迁移。如果系统确实需要用到某种特定技术,应当在设计层面做好封装解耦系统对某种技术的紧密依赖。

例如系统用到RocketMQ,由于后期发现存在一定风险转用更加可靠稳定的替代技术时,不会因为系统严重依赖RocketMQ而导致无法替代或替代成本高昂。

1.6 系统独立性

1.系统应该是独立的,不因其它不相关的系统发生故障而不能运行,不会因为依赖于别的系统才能使用,不会因为其它系统发生故障而导致本系统不能运行或发生连锁反应。

2.系统中的子系统也是相对独立的,除了核心模块外,不会因为不相关模块的故障而不能使用和运行。

3.系统设计时,应当考虑各模块之间互相独立以及各系统接口之间互相独立,互不影响对方的运行与使用,不应该因为某个模块或某个系统发生故障而影响其它系统或全部系统的正常使用和运行。

1.7 系统可监控性

在大型的分布式系统中,系统运行时总会出现各种不可预见的异常、资源瓶颈、并发、系统瓶颈等问题,往往这些问题在开发环境中都难以体现或难以模拟。当系统在运行过程中如果没有有效的监控手段,在系统存在问题或bug时无异于盲人摸象浑水里抓鱼无从下手,系统的可监控性具有重要的意义,系统的可监控性有助于问题的排查和分析并促进问题快速有效的解决的一个手段,同时可监控的系统也有助于提前预警系统未发现的隐患,具有预警问题发现问题排查问题和解决问题的重要作用。

在分布式系统中,系统间的接口调用应具备可监控的手段,及时监听系统的各种运行指标,并输出相应接口调用频率,每次调用时间,平均调用时间,异常次数,接口入参数据,数据库负载情况,缓存使用情况,缓存使用频率等等便于开发人员和运维人员做问题的预警和分析优化,调拨机器资源,改善技术方案或调整系统架构等工作。

监控涉及到系统的重要环节当中,包括不仅限于以下环节

1. 运维人员随时可以查看系统运行的事实状况,磁盘IO,CPU,内存,网络等

2. 技术人员随时可以查看请求的调用链条,系统负荷状况,接口调用频率,接口异常次数,接口调用耗时,数据库链接数,数据库请求耗时,缓存请求耗时,缓存命中率,内存使用状况,PV,UV,并发线程数,消息队列堆积情况,数据库状态等。

系统监控还应当支持系统各种治标值的预警能力,允许运维人员或系统管理人员设置系统的监控报警阀值,以及各种指标的报警开关等,并将系统报警信息通知并发送给相关人员。

1.8 系统易维护

分布式系统的体量庞大,系统与系统间或多或少都存在关联性,系统的变更和改动会对其它系统造成大小不一的影响,这需要对系统的设计以及代码的要求都比较高,同时在系统的架构设计以及开发编码中应当充分考虑系统的可维护性。

系统在设计阶段就要充分考虑好系统的可维护性,系统的可维护性包含代码的可读,可调试,可跟踪,可测试,可还原的基本原则.

可测试原则:既系统设计的接口,对象,方法,包括但不仅限于接口层服务层以及数据持久层应当可以互相独立进行单元测试。

可读原则:既开发出来的代码核心对象和重要方法都应当有充分的注释说明描述,代码命名以及定义符合编码规范,应做到开发人员能够轻易理解做在对象或方法的意图。对于比较复杂的方法,应当拆分成多个简单的方法。

可调试原则:既代码的编写在符合编码规范的前提下应注意空指针变量被执行在代码中做好空指针判断对无效或非法入参进行过滤和检查,确保业务被执行时的数据合法有效。多用临时变量减少堆栈的深度,变量类型明确定义和声明。

错误的例子

D d =funA().funB().funC().funD();

这个例子的代码是难移调试的。

正确的例子

A a = funA();

B b = a.funB();

C c = b.funC();

D d = c.funD();

这样写的代码是可调试的

可跟踪原则:代码的可跟踪与可调试密不可分,这里仅描述在非调试状态下,便于技术人员能够跟踪异常的执行情况。系统在设计和编码阶段应当充分考虑好测试日志的输出,不同层级的日志输出以及日志输出的可配置化,系统应当支持日志配置的动态生效以及动态禁止而不用重新启动服务器。做好日志输出的规划工作,对于接口以及重要方法的执行必须做入参数据的日志输出以及返回数据的日志输出,确保在系统出现异常时技术人员能够跟踪日志信息快速定位和排查问题的原因。

1

处理机制

处理机制是针对在系统中广泛存在的特定问题进行统一处理的方式,把开发人员解放出来,避免开发人员过多和重复考虑广泛存在的问题。处理机制应当是有针对性的解决某一领域广泛存在的问题,同时处理方式应当避免或尽可能的降低跟现有的业务代码产生紧密的耦合。

1.1 缓存使用机制

在一个高并发的系统中,每一次请求都需要读取响应的数据,在当前磁盘读取效率底下的情况下,为了更好的实现快速响应,而引入缓存机制既在用户请求数据时,第一次访问则读取磁盘数据而后将磁盘数据放如内存当中提高下次读取同一数据的效率,缓存的使用大大提高了系统整体的并发效率,这一机制同时也增加了系统的复杂度。

在系统使用缓存后,既同一数据产生了两份一份在内存中一份在磁盘中,如何保障缓存数据与磁盘数据的一致性至关重要,在系统架构层面应当统一处理缓存的使用读取,写入等的一些列标准化抽象,避免由开发人员直接管理和使用缓存不当而导致数据的不一致性。

缓存的使用原则,缓存的使用应视具体业务情况,并非所有数据都需要使用缓存,缓存的目的是为了提高数据的多次读取效率,一次读取多次使用,某些数据的操作频率非常低的情况下则可以不用缓存。

缓存命中率,命中率也既缓存被使用的概率,命中率的高低直接反应了系统对缓存使用的合理程度以及缓存带来的效率,命中率高则缓存使用合理,命中率低则使用不合理,甚至可以不用缓存,衡量缓存命中率的关键因素在于数据读和数据写的频率,其方程式可以简单概括为(读次数÷写次数=命中率)如果命中率等于1则完全可以不用缓存。命中率越高则证明缓存使用越合理和必要。

1.2 日志处理机制

在高并发的大型分布式系统中,日志信息输出有助于系统的优化以及问题跟踪处理,同时日志输出也会给系统带来额外的运行开销,滥用日志输出会严重影响系统性能,日志的处理应当遵循一些原则和规范,尽可能减少不必要的日志输出。

可配置,日志的输出应当允许运营人员动态的去配置,而不需要重启服务器。

格式化,日志的输出应当遵循一定的约定和规则。

日志输出应当是可配置的,运维可通过配置打开或关闭日志输出。

日志输出不应该影响系统的正常运行。

日志输出不应造成系统性能大幅下降。

日志输出内容应该是可读的,既日志内容不用经过工具解析开发人员是可以看得懂的没有加密的,日志文件也是可以打开的,同时日志输出内容应该是可分析的,既内容具有一定的代表性反映了系统真实的当时运营状态。

1.3 异常处理机制

异常的处理方式关系到系统的友好性以及容错性和健壮性,系统在运行过程中会抛出各种可预见和不可预见的异常,这是系统架构应当充分考虑到各种异常对系统造成直接或间接的影响,在系统中广泛存在的异常抛出应当有个统一的解决方案来处理各种异常的抛出。对异常进行分类和分级管理,区分对待业务流程异常,输入数据异常,程序处理异常,数据出错异常,系统环境异常,以及其它不能预见的异常等。

异常的抛出与捕获在很多时候存在不合理的地方,既不该捕获时捕获该捕获时则没有捕获,不该抛出的异常被抛出或该抛出异常却没抛出,这源于开发人员对异常没有深刻的理解。

不同的异常应当采用不同的处理方式,在系统设计时应当定义好在业务中所存在的各种异常情况,并统一解决方案。

异常抛出:

每种异常的抛出都应带有异常编号以及异常说明,方便系统对异常的加工处理和开发人员分析解决。

在某个对象的某个方法被调用过程中如果预见一个或多个必要的条件不能满足时则应该抛出异常,并在异常中附带抛出异常的原因。通过异常抛出的方式中断代码的执行并告知调用方在执行时遇见了什么问题。异常抛出应当遵循在执行中遇见不能处理或不可处理的问题时则应抛出异常。

异常捕获及处理:

在什么条件下应该捕获一个异常,这似乎比如何抛出一个异常更加难于界定也是很多开发人员容易犯错的地方。在代码执行中已经预见执行过程中会出现的异常并且能够确定这个异常是可以被解决的并且无需告知被调用者就能处理,这时就应当捕获这个异常进行处理,并返回执行结果给调用者。

异常的抛出与捕获并非无规可循,异常的抛出与捕获核心是调用者与执行者之间的一种协作方式,开发人员应当深刻理解调用者与执行者之间的关系,在这里我们可以把调用者和执行者比喻成领导与下属之间的关系,既上司安排一项任务,下属在执行某项任务时遇上具体问题无法处理则立即通报(抛出)领导并中断工作再由领导进行决策(捕获),此时领导判断问题在可控范围内采取应对措施后再由下属继续执行,假如领导对次问题超出可控范围或超出权责范围则会再往更高领导通报(抛出),以此类推直到问题被解决为止。

1.4 权限控制机制

每个系统中都普遍存在不同角色的使用者,权限控制对于系统的安全性有这重要的作用,系统中的接口或功能允许哪些使用者使用也是普遍存在的问题,系统架构应当对此类问题有统一的解决方案,避免开发人员重复考虑权限的控制和过滤问题。

权限的控制机制应在不影响业务逻辑的情况下对接口进行拦截做鉴权处理,隔离会员与业务逻辑之间的耦合问题。

1.5 事务处理机制

在分布式的系统中,事务处理是系统中的核心中的核心,事务处理机制决定了整个系统中的数据的一致性,原子性,完整性,隔离性的四性原则问题,事务的有效管理直接影响到系统的稳定性以及系统的可靠性,以及系统是否正常良好的运行。

这里所说的事务处理不仅包含数据库的事务,还贯穿于一个请求被处理到完成返回的整个处理过程。

事务的定义,一个事务的定义需要满足数据四性的要求,如果不满足四性要求这个事务是不完整的有缺陷的。可以简单的认为一个请求既为一个事务,事务具有不可分割性既原子性,事务的定义就是用于保障数据的四性。

事务的粒度,一个事务的粒度直接关系到事务对系统的整体运行效率大粒度的事务被执行意味着事务长时间的占用和锁定资源,在系统处于高并发高负荷的情况下往往会导致堵塞和等待,所以在事务的粒度定义中应当尽可能的减少非事务资源在事务中所暂用的时间,将非事务资源尽量放在事务外面完成,减少事务内的计算量。

事务的隔离,事务总是需要锁定资源的,在事务发起到事务结束的过程中事务一直锁定并独占相关资源,如果在此时另一个事务已经锁定同一资源时则本事务进入阻塞状态等待另一个事务执行完成释放资源后再继续进行未完成的事务工作,基于这样的事务特性,在系统层面可能发生事务之间互相等待对方释放资源的恶性循环当中无法及时响应用户的请求,严重情况下直接导致系统崩溃,甚至大面积瘫痪,事务的隔离在系统中有至关重要的作用,规划事务锁定资源的顺序可以有效避免以上问题的发生,这需要在系统设计层面充分考虑以及在代码层面遵循约定的资源锁定顺序,不能有丝毫偏差。

事务的原子性,事务是为了保障数据四性而诞生的,事务的执行是不应该被打断的,如果在事务中出现异常则应当回滚事务修改过的数据,要么全部操作成功要么全部操作失败,既事务的执行是不能被打断的。

事务的一致性,在跨系统之间的事务,往往在不同的独立系统中难于同时锁定对方系统的资源进行操作,这时跨系统的事务是无法保障数据严格的一致性的,为了保障一致性的结果,则需要系统间做出资源占用的协议约定,既在事务启动时通知对方系统占用某一资源并在事务完成后通知对方系统释放某一资源,以达到数据一致性的目的,这样的事务会付出比较大的代价,另一种做法是只保障数据的最终一致性,既通知对方系统修改指定资源并要求对方系统保障指定资源一定会被修改,由于此时资源已经被其它事务占用和修改则会造成数据不一致,对方仅保障了请求一定会被执行。

1.6 并发处理机制

在一个高并发的系统中离不开缓存的使用,但仅仅使用缓存是远远不够的,需要在系统设计,编码规范,异常处理,事务机制,日志输出,消息队列,线程使用,最优的算法,以及业务流程等多个维度综合统一考虑的结果。

为了系统能够及时响应用户请求的目的,也既系统需要尽快的完成一个事务处理,往往不同事务需要完成计算量不同,在系统设计中需要考虑每个事务需要处理的数据,区分需要即时处理的和不需要即时处理的,相应的将非即时处理的数据延后处理以达到快速响应的目的。

分布计算,一台机器的计算能力有限,为了能够尽快响应请求,应考虑把事务拆分成不同计算单元分布到多台机器来完成,以达到及时响应的目的。

异步处理,在一个事务或请求被执行时,除了用户期望需要返回的结果外还有额外的数据产出(例如,日志输出,消息通知等),额外的数据应当尽可能考虑异步处理方式,减少事务内处理时间和等待时间,以达到快速响应的目的。

算法优化,在处理一个事务时,高效的算法也是及时响应的重要保障,开发人员应尽可能使用能够降低计算量的算法,提高计算效率,以达到快速响应的目的。

日志输出,在大型系统中日志的输出是必不可少的,同时代价也是巨大的,日志输出需要占用很多的CPU资源以及IO资源,系统设计以及开发人员,应当尽可能的避免无效日志的输出,降低CPU使用率以及IO使用率,以达到快速响应的目的。

线程使用,在一个事务中并非所有的数据处理都需要同步进行处理,当有些数据可以异步处理时,可以使用一个线程或多个线程处理,待全部数据处理完成后再响应用户的操作,以达到快速响应的目的。

编码规范,规范的编程方式和编程习惯同样也可以提高系统的响应速度,例如用户需要执行一个事务,其中事务中包含计算量不同的三个任务单元A,B,C其中A计算量最大,B计算量其次,C计算量最小,当任务异常终止执行并响应用户时,任务的计算顺序总体上影响平均响应速度,为了总体上降低平均响应速度,应当考虑计算量小的任务单元优先计算为原则,以达到快速响应的目的。

事务机制,在一个事务处理中往往包含一些与事务无关的计算任务或计算单元,在系统设计中和编码阶段应当尽可能缩小事务操作粒度,解耦与事务无关的计算任务,例如在保存订单的事务中,需要读取地区数据,则应当在读取地区数据后再启动事务,这样可以降低事务对资源占用时间,同时能减少低其它事务等待同一资源时间既减少了响应时间,以达到快速响应的目的。

1

使用技术

以及

中间件

1.1 标准化

在做系统的技术选型时,所考虑使用的第三方的技术或中间件,应当充分论证,所采用的技术或中间件,在所在领域中是否标准化,以及是否得到行业的认可,判断标准化

1. 所采用技术是否得到行业的认可,技术是否达到标准化程度

2. 技术是否开源?是否可维护?

3. 技术是否还有人继续研究?

1.2 开放性

技术的开源在商业系统中的重要性是不言而喻的,非开源的技术会大大增加技术投入成本,包括技术学习成本,技术升级成本,开放源代码有助于降低技术投入成本以及避免版权问题,如非必要,则不应采用非开源技术或中间件。

1.3 稳定性

使用的技术以及版本,是否处于技术稳定期,避免使用太新或不完善的技术或中间件,除非有不可替代的需要

1.4 可替代

在使用的中间件中,行业上是否有类似的产品作为替代品,以及系统设计时需要考虑某个技术的替代方案,避免系统过度依赖某种技术或某种中间件。

1.5 是否可满足需求

评估是否满足系统的各种技术指标需求,例如并发量,稳定性,可扩展性,分布式,易于学习,学习资料多少等,上手难度等

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多