资讯详情

系统架构专题(1):大型互联网系统架构演变

1.设计主题

**须知:**在实际工作中,任何公司都不会在一开始就设计出合理的架构方案,而是在满足业务需求的情况下不断带来诱惑。这是一种持续的生活 程。当然,如果一开始有好的基础系统设计,以后更容易达到满意的目标。

在设计系统时,要因场景、时间而异,一个系统也不是一下子就能设计的非常完美,在资源有限的情况下,一定是先解决当下最核心的问题,预测现在未来可能出 现在的问题,一步一步地解决最头疼的问题。也就是说,一个好的设计应该实现,解决现有的需求和问题,控制实现和进度的风险,预测和规划未来,不要从迭代中过度设计 进和完善。

在设计系统时,我们应该多思考 墨 菲 定 律

1. 没有什么表面上看起来那么简单。

2. 一切都会比你预期的要长。

3. 总会出错。

4. 如果你担心某种情况,它更有可能发生。

还要考虑康威定律。

1. 系统结构是公司组织结构的体现。

2. 应该按照业 实现闭环、高内聚、低耦合,降低沟通成本。

3. 如果沟通有问题,应考虑调整系统和组织结构。

4. 在适当的时候拆分系统,不要从一开始就把系统/服务拆得很好。虽然是闭环的,但是每个人都有很多维护系统,维护成本很高。

2.架构演变

由 单机计 算机的架构分 布式计 算机架

前言:一个成熟的大型网站系统架构一开始并不是很完美,世界上没有完美的架构,也没有高性能、高可用性、安全性等特点, 随着用户数量的不断增加,业务功能的扩展逐渐完善和演变。在这一过程中,开发模式、技术架构等都会发生很大的变化。针对不同的行业 业务特征系统将有自己的重点,如淘宝等网站,解决大量商品搜索、订单、支付等问题;像腾讯一样,解决数亿用户的实际问题 时间消息传输;百度需要解决的是搜索海量数据。每种业务都有自己不同的系统架构。

以电子商务系统的发展演变为例,分析架构的演变过程。 关注数据量和访问量的增加,网站结构的变化,而不是业务功能点的具体关注。 这个过程是为了让大家更好地了解网站演变过程中的一些问题和应对策略。

假如我们的系统有以下功能: 用户模块:用户注册管理 商品模块:商品展示与管理 交易模块:创建交易及支付结算

我得回忆一下公司刚创业的时候。那是很多年前,那天,公司成立了,老板兴致勃勃地租了一栋房子,买了一台服务器。然后每个人都开始工作。 大伙把所有软件和应用都部署在一台机器上,这样就完成一个简单系统的搭建,这个时候的讲究的是效率。 我们在机器上安装了它lnmp,下图描述了我们的服务器:

服务器上部署了最初的架构、应用程序、数据库和文件:

系统架构专题(1):大型互联网系统架构演变

随着网站的推出,访问量逐渐增加,服务器负载逐渐增加。当服务器超载时,我们应该制定计划,以提高网站的负载能力。如果代码层优化没有 办法继续提高,在不提高单台机器的性能,增加机器是一个比较好的方式,投入产出比非常高。现阶段增加机器的主要目的是谈 web 服务器和 拆卸数据库服务器 这不仅提高了单机的负载能力,也提高了容灾能力。并根据服务器的用途配置不同的硬件,以达到最佳的性能效果。

应用程序、数据和文件分离:

在硬件优化性能的同时,也通过软件进行性能优化,在大多数网站系统中,将使用缓存技术来提高系统的性能,缓存的使用主要来自热数据的存在,大多数 网站访问都遵循28原则(即80%的访问请求,最终落在20%的数据上),所以我们可以对热点数据进行缓存,减少这些数据的访问路径,提高用户体验。

利用缓存提高网站性能:

随着访问量的继续增加,单台应用服务器已经无法满足需求。假设数据库服务器没有遇到性能问题,我们可以通过应用服务器集群增加应用服务器 用户要求转移到每个服务器,以继续提高负载能力。此时,多个应用服务器之间没有直接的交互,它们都依赖于数据库提供外部服务。前部署应用服务器 根据分发策略,将负载均衡服务器调度用户请求分发给多个应用服务器节点

此外,我们还可以增加缓存服务器集群, 提高访问速度,降低访问速度mysql等待数据库的压力

应用服务器集群和缓存服务器集群 :

结构演变到这里,不是终点。我们提高了应用层的性能,但数据库的负载也在缓慢增加,那么如何提高数据库层的负载呢?有以前的想法 之后自然会想到增加服务器。但是,如果我们简单地将数据库一分为二,然后将后续数据库的请求分别负载到两个数据库服务器上,肯定会导致数据库不均匀 一的问题。 因此,我们通常首先考虑读写分离的方式, 。

现阶段不需要考虑分库分表,而是数据库优化的终极技能,因为会带来一些问题,所以不需要.

数据库读写分离:

如果数据库是读数库,模糊搜索的效率往往不是特别好。例如,搜索是电子商务网站的核心功能。即使读写分离,这个问题也无法有效解决。此时此刻 就需要引入Nosql还有搜索引擎。我们使用海量数据的查询和分析NoSQL数据库和搜索引擎可以实现更好的性能。并非所有的数据都应该放在关系数据中。 常用的NoSQL有MongoDB、HBase、Redis,搜索引擎有Lucene、Solr、Elasticsearch。

N oSQ L和搜索引擎

如果我们的服务器部署在成都的机房,四川的用户访问速度更快,而北京的用户访问速度更慢,这是因为四川和北京属于电信和联通的差异 在大地区,北京用户需要通过互联路由器通过长路径访问成都服务器,返回路径相同,数据传输时间较长。对于这种情况,常常使用CDN 解决,CDN将数据内容缓存到运营商的机房,用户首先从最近的运营商那里获取数据,这大大降低了网络访问的路径。比较专业的CDN运营商有蓝汛、网宿。

反向代理部署在网站的机房。当用户要求到达时,首先访问反向代理服务器。反向代理服务器将缓存数据返回给用户。如果没有缓存数据,则应继续访问 使用服务器获取可以降低获取数据的成本。反向代理有Squid、Nginx。

使用CDN反向代理提高网站性能

随着业务的进一步扩张,应用程序变得非常臃肿。此时,我们需要将应用程序分为新闻、网页、图片等业务。每个业务应用程序负责相对独立的业务 操作。通过通信或共享数据库实现业务之间的信息。

业务拆分

在我们网站演变的过程中,交易、商品和用户的数据都在同一个数据库中。虽然增加了缓存、读写分离,但随着数据库压力的增加,数据库 瓶颈仍然是最大的问题。因此,我们可以考虑垂直和水平的数据分割。

垂直拆分:将数据库中不同的业务数据拆分到不同的数据库。

水平分割:将同一表中的数据分割到两个甚至更多的数据库中。水平分割的原因是一些业务数据量已经达到了单个数据库的瓶颈。此时,可以将表分割到多个数据库数据库中。

此时,我们发现每个业务应用程序都使用一些基本的业务服务,如用户服务、订单服务、支付服务和安全服务,这些服务是支持每个业务应用程序的基本要素。我们将这样做 提取一些服务,利用分部服务框架构建分布式服务。Dubbo是个不错的选择。

服务拆分

3.了解分布式、集群和微服务

分布式

顾名思义,分布式服务分散在不同的机器上。一个服务可能负责几个功能,这是面向它的SOA架构的, 服务也是通过的rpc互动或者webservice来 交互的。逻辑架构设计完成后,应进行物理架构设计。系统应用程序部署在一个以上的服务器或虚拟机上,每个单独部署的部分可以通过各种通信协议相互交互信息 在布式部署中,生产环境中的微服务必须分布式部署。分布式部署的应用不一定是微服务架构,如集群部署。它将相同的应用程序复制到不同的服务器上,但辑功 能上还是单体应用。

在架构演变中的 3.2. 数据库服务器和应用服务器分离 实际就是一种分布式的方式部署;服务之间的职责各有不同;

 

集群

集群就是多个服务之间的职责相同,对于集群来说如果一个节点出现了问题,那么就可以让其他的节店顶上

 

 

其中MySQL的主从也是属于集群

 

微服务

微服务关注:架构设计方式;分布式关注:系统部署方式(两者概念不同) 主要是基于项目的业务模块进行细节化的拆分;把整个项目可以基于模块,功能拆分为单独的系统

 

比如

 

4. 高并发下拆分的原则

在系统设计初期,是做一个大而全的系统还是按功能模块拆分系统,这需要根据环境权衡;如果项目只是一个人就不要拆分,如果是项目比较大如京东,淘宝这样 的系统访问量是非常大的,而且设计时投入的资源足够就可以按功能拆分系统

系 统 维 度 :按照系统功能业务拆分,比如商品系统、购物车、结算、订单系统等。 功 能 维 度 :对一个系统进行功能再拆分,比如,优惠券系统可以拆分为后台券创建系统、领券系统、用券系统等。 读 写 维 度 :根据读写比例特征进行拆分。比如,商品系统,交易的各个系统都会读取数据,读的量大于写,因此可以拆分成商品写服务、商品读服务;读服务可以考

虑使用缓存提升性能:写的量太大时,需要考虑分库分表;有些聚合读取的场景,如商品详情页,可考虑数据异构拆分系统,将分散在多处的数据聚合到一处存储,

以提升系统的性能和可靠性。

 :比如,按照基础或者代码维护特征进行拆分,如基础模块分库分表、数据库连接池等:代码结构般按照三层架构 (Web、Service、 MODEL)进行划分。

 :根据访问特征,按照AOP进行拆分,比如,最典型的例子就是权限,配置

如下是对应拆分体系图:

 

AKF扩展立方体(参考《The Art of Scalability》),是一个叫AKF的公司的技术专家抽象总结的应用扩展的三个维度。理论上按照这三个扩展模式,可以将一个单体 系统,进行无限扩展。

X 轴 :指的是水平复制,很好理解,就是讲单体系统多运行几个实例,做个集群加负载均衡的模式。

Z 轴 :是基于类似的数据分区,比如一个互联网打车应用突然或了,用户量激增,集群模式撑不住了,那就按照用户请求的地区进行数据分区,北京、上海、四川 等多建几个集群。

Y 轴 :就是我们所说的微服务的拆分模式,就是基于不同的业务拆分。 场 景 说 明 :比如打车应用,一个集群撑不住时,分了多个集群,后来用户激增还是不够用,经过分析发现是乘客和车主访问量很大,就将打车应用拆成了三个乘

客服务、车主服务、支付服务。三个服务的业务特点各不相同,独立维护,各自都可以再次按需扩展

 

基于5.1的方式与规则进行系统的拆分,接下来需要做的就是系统服务化; 服务主要是指相对独立、功能内聚的一组业务,数据自我包含,对外提供标准化的业务功能或业务数据接口。不同服务之间是松耦合的,而服务自身也能获得更好

的复用。

服务化架构就是将原有的统一型架构按业务特点进行服务拆分,再通过服务注册以及企业服务总线将服务进行串联,从而构建出整个系统。

 

1. 服务和组件的区别

 

组件在功能上和服务有一定的相似性,都是完成一定的业务功能,都有内聚性。 两者不同之处主要在使用.上,组件要求包含在业务系统内部,需要业务系统进行集成,如果组件的功能发生了修改,则所有弓|用此组件的业务系统都需要进行组件

升级。而服务则是在业务系统外部独立部署的,业务系统仅需要调用服务的接口来完成功能即可,如果服务内部的功能发生了修改,只将该服务升级即可,其期调用

服务的业务系统并不要修改。

 

2. 服务和子系统的区别

 

服务和子系统在业务上都可完成一定的业务功能, 都可对外提供接口接入。两者的区别主要还是在系统功能的独立性上,子系统可以独立的安装部署,提供完整的 一-块业务功能供用户使用,而服务则还是需要依托业务系统,它无法独立于业务系统或其他服务单独给用户使用。

需要注意:服务化需要思考的点 首先,判断是不是只需要简单的单点远程服务调用,单机不行集群是不是就可以解决?在客户端注册多台机器并使用Nginx进行负载均衡是不是就可以解决?随着调

用方越来越多,应该考虑使用服务自动注册和发现(如Dubbo使用ZooKeeper)。 其次,还要考虑服务的分组/隔离,比如,有的系统访问量太大,导致把整个服务拖

垮,因此,需要为不同的调用方提供不同的服务分组,隔离访问。后期随着调用量的增加还要考虑服务的限流、黑白名单等。还有一.些细节需要注意,如超时时

间、重试机制、服务路由(能动态切换不同的分组)、故障补偿等,这些都会影响到服务的质量。

总结为:进程内服务→单机远程服务→集群手动注册服务→自动注册和发现服务→服务的分组/隔离/路由→服务治理放在括号内。

如果设计的应用是无状态的,那么应用比较容易进行水平打展。实际生产环境可能是这样的:应用无状态,配置文件有状态。比如,不同的机房需要读取不同的数据 源,此时,就需要通过配置文件或配置中心指定。

 

有状态:如果一个数据需要被多个服务共享,才能完成一笔交易,那么这个数据被称为状态。进而依赖这个“状态”数据的服务被称为有状态服务,反之称为无状态 服务。

那么这个无状态服务原则并不是说在微服务架构里就不允许存在状态,表达的真实意思是要把有状态的业务服务改变为无状态的计算类服务,那么状态数据也就相 应的迁移到对应的“有状态数据服务”中。

场景说明:例如我们以前在本地内存中建立的数据缓存、Session缓存,到现在的微服务架构中就应该把这些数据迁移到分布式缓存中存储,让业务服务变成一个无 状态的计算节点。迁移后,就可以做到按需动态伸缩,微服务应用在运行时动态增删节点,就不再需要考虑缓存数据如何同步的问题。

 

1. RestFul - REST over HTTP(S)

2. 消息队列

3. RPC (跨语言或单语言)

 

• 理 解 通 信

RestFul - REST over HTTP(S)

自Roy Fielding提出RESTful架构自提出以来,一直都是备受欢迎的方案,特别是在Web应用的开发中。Fielding提出的约束虽然不是标准,但在声明我们的API为 RESTful之前,应该始终遵循这些约束。

HTTP上有各种各样的REST,因为没有强制执行的标准。开发人员可以自由选择以JSON、XML或某种自定义格式形成请求有效负载。 REST over HTTP(S)仅意味着使用REST架构风格并通过HTTP(S)发送请求

 

消息队列

 

消息队列用来解耦此不需要同步调用的服务或者订阅一些自己系统关心的变化。使用消息队列可以实现服务解耦(- 对多消费)、异步处理、流量削峰/缓冲等。比 如,电商系统中的交易订单数据,有非常多的系统关心并订阅该数据,比如,订单生产系统、定期送系统、订单风控系统等等。如果订阅者太多,那么订阅单个消 息队列就会成为瓶颈,此时,需要考虑对消息队列进行多个镜像复制。

使用消息队列时,还要注意处理生产消息失败,以及消息重复接收时的场景。有些消息队列产品会提供生产重试功能,在达到指定重试次数还未生产成功时,会对 外通知生产失败。这时,对于不能容忍生产失败的业务场景来说,一定 要做好后续的数据处理工作,如持久化数据要同时增加日志、报警等。对于消息重复问 题,特别是一” 些分布式消息队列,出于对性能和开销的考虑,在一-些场景下会发生消息重复接收,需要在业务层面进行防重处理。

 

RPC(跨语言或单语言)

 

远程过程调用在分布式系统中并不新鲜,它通过在网络上的另一个设备上执行函数/方法/过程来工作。

1. 超时和重新连接需要处理服务器崩溃,即使使用了面向连接的协议(TCP)

2. 不指定服务和客户机的绑定,具体由实现人员决定

3. RPC实现的强制性要求:

被调用过程的唯一规范 响应消息与请求消息匹配的规定 对调用方进行服务身份验证的规定,反之亦然

• 消 息 队 列 与 选 择

RestFul:一般是对外提供服务提供给web端或者其他系统调用

rpc:实时性强 要实时返回数据用rpc, 比如查看商品列表,订单列表等等,通过rpc同步实时获取数据。

mq队列:下单那里,牵涉到减库存,发短信等,这些东西用户并不需要你实时返回,用户也不关心,就放到队列mq里面,采用异步的方式处理就行了。

 

• 数 据 异 构

订单分库分表一般按照订单ID进行,如果要查询某个用户的订单列表,则需要聚合多个表的数据后才能返回,这样会导致订单表的读性能很低。此时需要对订单表 进行异构,异构一套用户订单表,按照用户ID进行分库分表。另外,还需要考虑对历史订单数据进行归档处理,以提升服务的性能和稳定性。而有些数据异构的意 义不大,如库存价格,可以考虑异步加载,或者合并并发请求。

 

• 数 据 闭 环

如商品详情就需要获取:商品品牌,商品价格(要求实时性),图片,店铺,评价等等;这些数据在微服务的拆分下可能会分为如“用户服务,商品服务,交易服 务,评价服务,店铺服务,订单服务”

实现数据闭环,如商品详情页,因为数据来源太多,影响服务稳定性的因素就非常多。最好的办法是把使用到的数据进行异构存储,形成数据团环,基本步骤如 下。

因素:1. 核心就是速度需要,2. 数据分撒需要调用不同的服务,3. 网络及服务问题等

数 据 异 构 :通过如MQ机制接收数据变更,然后原子化存储到合适的存储引擎,如Redis或持久化KV存储。

数 据 聚 合 : 这一步是可选的,数据异构的目的是把数据从多个数据源数据聚合的目的是把这些数据做聚合,这样前端就可以个调用拿到此步骤般存储到KV存储 中。

前 端 展 示 : 前端通过一次或少量几次调用拿到所需要的数据。 这种方式的好处就是数据的闭环,任何依赖系统出了问题,还是能正常工作, 只是更新会有积压,但是不影响前端展示。

数据闭环和数据异构其实是一个概念,目的都是事先数据的自我控制,当其他系统出现问题的时候不影响自己的系统,或者自己出问题的时候不影响其他系统。一 般通过消息队列来实现数据分发.

 

缓存对于度服务来说可谓抗流量的银弹,可总结为下:

 

设置请求的过期时间,如对响应头Expires、Cache-control 进行控制。这种机制适用于对实时性不太敏感的数据,如商品详情页框架、商家评分、评价、广告词等: 但对于价格、库存等实时要求比较高的数据,就不能做浏览器端缓存。

在大促时为了防止瞬间流量冲击,一般会在大促之前把 APP需要访问的一些素材(如jssimage等)提前下发到客户端进行缓存,这样在大促时就不用去拉取这些素 材。另外,如首屏数据也可以缓存起来,在网络异常情况下还是有拖地数据给用户展示;如APP题图一般也会做地图的离线缓存

如NGINX搭建一层接入层,该接入层可以考虑

使用如下机制实现: proxy+cache:代理缓存

假设一个读服务需要如下数据

 

如果 串行执行获取,那么需要60ms

如果A数据,B数据,数据D 三者不会依赖谁;而数据C 依赖A和B,数据E需要C的数据;那么可以通过如下方式获取。

 

如果并发化获取,则需要30ms,提升一倍的性能

5. 高可用原则

微服务的雪崩效应 除了对服务可用性的追求,微服务架构一个绕不过去的问题就是服务雪崩。 在一个调用链路上,微服务架构各个服务之间组成了一个松散的整体,牵一发而动全身,

服务雪崩是一个多级传导的过程,首先是某个服务提供者不可用,由于大量超时等待,继而导致服务调用者不可用,并且在整个链路上传导,继而导致系统瘫痪。

 

限流的目的是防止恶意请求流量,恶意攻击,或防止流量超出系统峰值的策略 思路:

1. 恶意请求流量只访问到cache

2. 对于穿透到后端应用的流量可以考虑使用NGINX的limit模块处理

3. 对于恶意IP可以使用nginx deny进行屏蔽。

原则是限制流量穿透到后端薄弱的应用层

什么是降级:就是原原本需要考虑高校实时性相应数据,但是因为服务扛不住改为读缓存;或者需要获取的数据很多但是没有办法处理好则选择降级返回少量数 据。

典型生活例子:车站购票,平常与高峰期的处理 对于一个高可用服务,很重要的一个设计就是降级开关,在设计降级开关时,主要依据如下思路。

1. 开关集中化管理:通过推送机制把开关推送到各个应用

 

2. 可降级的多级读服务:比如

 

3. 开关前置化:如架构师Nginx->swoft,可以讲开关前置到NGINX接入层,在nginx层做开关,请求流量不回源后端swoft应用或者只是一小部分流量回源。

 

4. 业务降级:当高并发流量来袭,在电脑系统打出设计时保障用户能下单、能支付是核心要求,并保障数据最终一致性即可。这样就可以把一些同步调用改成异 步调用,优先处理高优先级数据或特殊特征的数据,合理分配进入系统的流量,以保障系统可用。

 

理解熔断

如果某个目标服务调用慢或者有大量超时,此时熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。 服务隔离与前面的三个略有区别,我们的系统通常提供了不止一个服务,但是这些服务在运行时是部署在一个实例,或者一台物理机上面的, 如果不对服务资源做隔离,一旦一个服务出现了问题,整个系统的稳定性都会受到影响!服务隔离的目的就是避免服务之间相互影响。 一般来说,隔离要关注两方面,一个是在哪里进行隔离,另外一个是隔离哪些资源。

何处隔离 一次服务调用,涉及到的是服务提供方和调用方,我们所指的资源,也是两方的服务器等资源,服务隔离通常可以从提供方和调用方两个方面入手。

隔离什么 广义的服务隔离,不仅包括服务器资源,还包括数据库分库,缓存,索引等,这里我们只关注服务层面的隔离。

降级和熔断的区别

服务降级和熔断在概念上比较相近,通过两个场景,谈谈我自己的理解。

熔断,一般是停止服务 典型的就是股市的熔断,如果大盘不受控制,直接休市,不提供服务,是保护大盘的一种方式。

降级,通常是有备用方案 从北京到济南,下雨导致航班延误,我可以乘坐高铁,如果高铁票买不到,也可以乘坐汽车或者开车过去。

两者的区别

降级一般是主动的,有预见性的,熔断通常是被动的,服务A降级以后,一般会有服务B来代替,而熔断通常是针对核心链路的处理。在实际开发中,熔断的下一步 通常就是降级。

对于一个大型应用,切流量是非常重要的,比如多机房环境下某个机房挂了,或者某个机架挂了,或者某台服务器挂了,都需要切流量,可以使用如下手段进行切 换。

1. DNS:切换机房入口。

2. HttpDNS:主要在APP场景下,在客户端分配好流量入口,绕过运营商LocalDNS并实现更精准的流量调度。

3. LVS/HaProxy: 切换故障的Nginx接入层。

4. Nginx:切换故障的应用层。

另外,有些应用为了更方便切换,还可以在Nginx接入层做切换,通过Nginx进行一些流量切换,而没有通过如LVS/HaProxy做切换。

 

版本化的目的是实现可审计前面加顿号,并且可回滚。当程序或数据出错时,如果有版本化机制,那么就可以通过回滚恢复到最近-个正确的版本, 比如事务回 滚、 代码库回滚、部署版本回滚、数据版本回滚、静态资源版本回滚等。通过回滚机制可保证系统在某些场景下的高可用。

 

6. 业务设计原则

比如,结算页需要考虑重复提交,还有如下单扣减库存时需要防止重复扣减库存。解决方案可以考虑防重key、防重表。而有些场景如重复支付,是因为有的电商 网站同时支持微信支付、京东支付,渠道不样是无法防止重复 支付的。但是,在系统设计时,需要将支付的每笔情况记录下来。

在交易系统中,经常会用到消息,而现有消息中间件基本不保证不发生重复消息的消费。因此,需要业务系统在重复消息消费时进行幂等处理。还有在使用第三方 支付时,第三方支付会进行异步回调,也要考虑做好回调的幂等处理。

如果接触过保险业务,就会发现不同保险的理赔服务是不一样的。我们在系统设计时就设计了一套理赔流程服务。而承保流程和理赔流程是分离的,在需要时进行关联,从而可以复用一些理赔流程,并提供个性化的理赔流程。

在设计交易订单系统时,会存在正向状态(待付款、待发货、已发货、完成)和逆向状态(取消、退款)等,正向状态和逆向状态应该根据系统的特征来决定要不要分离 存储。状态设计时应有状态轨迹,方便用户跟踪当前订单的轨迹并记录相关日志,万一出问题时可回溯问题。

另外,还有订单状态的变迁,比如待支付、已支付待发货、待收货、完成的迁移。要考虑要不要使用状态机来驱动状态的变更和后续流程节点操作,尤其当状态很 多的时候使用状态机能更好地控制状态迁移。

还要 考虑并发状态修改问题,如一个订单同时只能有一个修改:状态变更的有序问题,以及状态变更消息的先到后到问题,如支付成功消息和用户取消消息的时间 差。

良好的系统中,很多场景都需要反馈,比如,修改了某些内容后想预览看看最终效果,即想得到一些反馈:还有一些是在规则系统中,希望看到这些规则在系统数据 下的反馈。因此,在设计后台系统时,需考虑效果的可预览、可反馈。

对于有些重要的后台功能需要设计审批流,比如调整价格,并对操作进行记录日志,从而保证操作可追溯、可审计。

实际中有些系统是完全没有文档、代码没有注释的,完全是人传人。这将导致后来人接手很痛苦,而对有些代码是完全不敢改动的, 比如,有些代码完 全是因为 业务的一些特 殊情况而写的,可以说没有注释是完全不懂为什么那么做的。因此,在一个系统发展的一开始就应该有 文档库(设计架构、设计思想、数据字典/业 务流程、现有问题),业务代码和特殊需求都要有注释。

备份包括代码备份和人员备份。代码主要提交到代码仓库进行管理和备份,代码仓库应该至少具备多版本的功能。人员备份指的是一一个系统至少应该有两名开发 人员是了解情况的,即使其中一名离职了 也不会出现新人接手之后手忙脚乱事故频发的状况。 还有一些是“核心人员”,写着系统的核心代码,被认为是“不可替代 的”,这种情况也尽可能地让他带一名兄弟 起开发核心代码 (业务系统),即使他离职,另一个 人也还是可以努力一下克服困难。

标签: 高铁c型l型连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台