技术发展的很快,作为架构师,新的技术要不要尝试应用在当前项目中?比如 Docker 技术流行,每年节省几十万元的硬件成本。比如竞争对手用了阿里的云计算,使得业务增长了很多倍。这个问题一般有几种类型,一种保守派,一种潮流派,一种跟风派(同行业用有效果我也用)。

技术发展的动力

实际上,应该从更高的纬度去思考这个问题 —— 企业的业务发展。影响一个企业业务的发展主要有 3 个因素:市场、技术、管理。此处只讨论“技术”和“业务”相关的问题。

企业的业务有很多种类型,有的是产品,有的是服务,有的是两者结合。比如浏览器、云盘、云计算、AI 写作、线上购物、短视频等等。

其中,对于一些规模化的服务类业务中,比如线上购物、短视频播放等等,发展路径大概是这样的:提出一种创新的服务模式→吸引了一批用户→业务开始发展→吸引了更多用户→服务模式不断完善和创新→吸引越来越多的用户,如此循环往复。这个发展路径中,是通过业务的创造和改进,引发用户规模上涨,对技术提出更高的要求,进而引起技术的发展。即,业务创新驱动技术发展

其实回到产品类业务,如果我们将观察的时间拉长来看,即使是产品类业务,在技术创新开创了一个新的业务后,后续的业务发展也会反向推动技术的发展。例如,第一代 iPhone 缺少对 3G 的支持,且只能通过 Web 发布应用程序,第二代 iPhone 才开始支持 3G,并且内置 GPS。

综合这些分析,除非是开创新的技术能够推动或者创造一种新的业务,例如近些年突然涌现的 AI 创作,其他情况下都是业务的发展推动了技术的发展。即,业务的复杂度引起了技术发展

技术演进方式

在并非技术为主推力的情况下,进行技术的演进也就是需要找到当前业务遇到的“复杂性”问题。这个问题,可能是性能问题,可能是可用性问题,可能是功能复杂度,可能是成本问题等等。所以,架构师需要根据当前业务遇到的问题、业务发展阶段进行判断。

例如淘宝的演进过程如下所示:

  • 2003 年,业务刚刚创立,主要的复杂度体现为如何才能快速开发各种需求,淘宝团队采取的是买了一个 PHP 写的系统来改。
  • 2004 年,上线后业务发展迅速,用户请求数量大大增加,主要的复杂度体现为如何才能保证系统的性能,淘宝的团队采取的是用 Oracle 取代 MySQL。
  • 用户数量再次增加,主要的复杂度还是性能和稳定性,淘宝的团队采取的是 Java 替换 PHP。
  • 2005 年,用户数量继续增加,主要的复杂度体现为单一的 Oracle 库已经无法满足性能要求,于是进行了分库分表、读写分离、缓存等优化。
  • 2008 年,淘宝的商品数量在 1 亿以上,PV2.5 亿以上,主要的复杂度又变成了系统内部耦合,交易和商品耦合在一起,支付的时候又和支付宝强耦合,整个系统逻辑复杂。淘宝的团队采取的是系统解耦,将交易中心、类目管理、用户中心从原来大一统的系统里面拆分出来。

互联网常见技术演进过程

若当前业务是一个世界上全新的的业务方向,那么技术往往这样发展:

  • 第一步,初创期。产品能用就行,可能用户体验不一定完美,可能有 Bug。
  • 第二步,发展期。快速的堆功能期 → 优化系统期(系统可用性太差) → 重构架构期(系统仍然撑不住,如数据库数据量过大问题)。
  • 第三步,竞争期。新的公司冒出来,同时有新业务发展,互相借鉴开创业务方向,导致重复造轮子 + 系统交互一团乱麻。
  • 第四步,成熟期。当成为一方势力后,开始进一步优化,如建立中台、优化用户体验等。

补充:第二步不一定最后重构架构,在足够时间、人力、资源的情况下,可以选择直接设计一个更好的架构形式。

互联网架构模板-存储层

SQL 架构模板

  • 数据库需要进行分表等改造时,可以选择做成中间件形式,例如百度的 DBProxy、淘宝的 TDDL。不过这部分的技术要求很高,将分库分表做到自动化和平台化,不是一件容易的事情。中小公司可以考虑 MySQL 官方推荐的 MySQL Router、360 开源的数据库中间件 Atlas。
  • SQL 服务器越来越多后,数据库资源利用率不高,SQL 集群分开维护成本高。可以大公司此时一般都会在 SQL 集群上构建 SQL 存储平台,以对业务透明的形式提供资源分配、数据备份、迁移、容灾、读写分离、分库分表等一系列服务,例如淘宝的 UMP(Unified MySQL Platform)系统。

NoSQL 架构

在 NoSQL 集群基础上,实现统一存储平台。功能可以考虑:资源动态按需动态分配(根据内存利用率分配给多个业务),资源自动化管理(无需关注哪个服务器提供服务),故障自动化处理。几十台做存储平台收益不大,几千台 NoSQL 服务器再做存储平台才有意义。

小文件存储

例如,淘宝的商品图片、商品描述;Facebook 的用户图片;新浪微博的一条微博内容等。这些数据具有三个典型特征:一是数据小,一般在 1MB 以下;二是数量巨大,Facebook 在 2013 年每天上传的照片就达到了 3.5 亿张;三是访问量巨大,Facebook 每天的访问量超过 10 亿。

在开源方案的基础上封装一个小文件存储平台并不是太难的事情。例如,HBase、Hadoop、Hypertable、FastDFS 等都可以作为小文件存储的底层平台,只需要将这些开源方案再包装一下基本上就可以用了。典型的小文件存储有:淘宝的 TFS、京东 JFS、Facebook 的 Haystack。

大文件存储

一类是业务上的大数据,例如 Youtube 的视频、电影网站的电影;另一类是海量的日志数据,例如各种访问日志、操作日志、用户轨迹日志等。和小文件相比,数量相对较少,但是每个文件都很大。

几个流行的开源方案,例如,Hadoop、HBase、Storm、Hive 等。实力雄厚一些的大公司会基于这些开源方案进行修改,封装成大数据平台,例如淘宝的云梯系统、腾讯的 TDW 系统。

40 | 互联网架构模板:“存储层”技术-从0开始学架构-极客时间

用户层

43 | 互联网架构模板:“用户层”和“业务层”技术 - 极客时间已完结课程限时免费阅读
用户层技术
用户管理
单点登录 sso,又叫统一登录。
单点登录的技术实现包括 cookie,jsonp,token 等,比较成熟的开源单点登录方案当属 cas。
在业务变大,成长为平台后,又引出了用户管理的第二个目标:授权登录。现在流行的就是 oauth2.0 协议。
消息推送
消息推送根据不同途径,分为短信,邮件,站内信,app 推送。除了 app 推送以外,不同的途径基本上调用不同的 app 即可完成。
重点的 app 推送包括 ios 推送,以及 android 推送,ios 一般用 apns 推送就好了,而 android 就不一样了,在国外 google cloud message 是可以用的,但是在国内是没法用的。所以就衍生了各种版本,主要有大厂自己实现的消息推送机制(阿里云移动推送,腾讯信鸽推送,百度云推送),以及专业的第三方公司提供的推送服务(友盟推送,极光推送)。
消息推送主要包括三个功能:设备管理(唯一标识,注册,注销),连接管理和消息管理器
如果要自己处理的话,那么要注意三点挑战。

海量设备和用户管理
为方便业务推广,还需要收集用户信息,将用户跟设备关联,提取用户特征对用户进行分类和打标签。

连接保活
一般设备为了节省电(流)量,都会限制应用后台运行,限制应用后台运行连接通道可能被中断,导致消息不可达。方法有很多,比如互相拉起,找手机厂商开白名单。

消息管理
实际业务中,需要根据用户的特征选择一些用户进行消息推送,由于用户特征变化大,需要将推送给哪部分用户的逻辑设计非常灵活,才能满足需求。

存储云,图片云
互联网场景下,用户会上传多种类型的文件数据,这样文件的特点:
1)数据量大,用户基数大
2)文件体积小,几百 kb 到几 mb,
3)访问有时效性,大部分文件是刚上传时访问最多,随着时间的推移访问量越来越小。
存储云/图片云都是基于 cdn+小文件存储的技术,没有合并的原因在于图片业务复杂还包括裁剪,压缩,美化,审核,水印等处理。
业务层技术
随着业务复杂度越来越高,一般的方法就是拆,化整为零,分而治之,将整体复杂性分散到多个子业务/子系统里面去。
当然随着子系统数量越来越多,还可以采用合的做法,比如,按照高内聚,低耦合的原则。将职责关联比较强的子系统合成一个虚拟业务域,通过网关对外统一呈现,类似于 facade 设计模式。

44 | 互联网架构模板:“平台”技术 - 极客时间已完结课程限时免费阅读
运维+测试+数据+管理平台

架构重构

相比全新的架构设计来说,架构重构对架构师的要求更高,主要体现在:(1) 业务已经上线,不能停下来;(2) 关联方众多,牵一发动全身;(3) 旧架构的约束。

程序是否要重构:从 0 设计该系统,新老架构的差异是否大。若不大,直接选择优化现有系统;若比较大,再考虑重构。

作为架构师,架构重构需要注意哪些?(1) 抓住关键问题 (2) 人员的沟通和配合 (3) 先救火、再优化、后重构

抓住关键问题

例如,M 系统是一个后台管理系统,负责管理所有游戏相关的数据。A 业务和 B 业务的游戏数据都存在于 M 系统中。除此之外,A 业务的一部分业务数据也放在 M 系统中,和游戏数据放在相同表里,导致开发与改动的可扩展性比较差。那么这里不合理的耦合就是“关键问题”。

这个系统中还存在其他问题,如下所示,但是并不属于关键问题。

  • 数据经常出错。
  • M 系统是单机,单机宕机后所有后台操作就不能进行了。
  • 性能比较差,有的操作耗时好久。
  • 界面比较丑,操作不人性化。
  • 历史上经过几手转接,代码比较混乱。
  • 业务数据和游戏数据耦合,开发效率很低。

在通过重构解决了关键问题后,可以再逐步优化解决剩余问题。

人员的沟通和配合

在沟通方面主要会涉及到两类人,一类是同项目组的产品经理、项目经理、上级,另一类是相关项目组的架构师、研发等角色。

同项目组的沟通。重构需要耗费研发人力和时间成本,影响业务功能推进,因此需要和产品经理、上级等进行沟通,确保达成一致,避免后期不必要的反复和争执。

在产品经理进行沟通的时候,需要用通用语言,而非技术语言。比如可扩展性、可用性之类的词汇,产品经理是无法理解的。那么怎么沟通和解释会更有益处呢?

  • 将“可扩展性”转换为“版本开发速度慢,在屎山上增加新功能,要考虑是否会牵连到其他业务,造成不必要的损失”。再举一些实际的例子,比如某个相对容易的功能,设计阶段用了多久,实际开发多久,为了避免影响其他业务,测试和联调用了多久。
  • 将“可用性”转换为“线上故障的次数、每次影响的时长,影响的用户,客服的反馈意见”。再拿其他系统的数据进行对比,无论是产品人员、项目人员,还是运营人员,明显就看出系统的可用性有问题了。

不同项目组的沟通。项目的运转牵涉到其他项目,在测试或联调时需要其他项目组配合。此时的阻力在于,“这对我有什么好处”和“这部分我这边现在不急”。解决阻力的办法就是,“换位思考、合作双赢、关注长期”。简单来说就是站在对方的角度思考,重构对他有什么好处,能够帮他解决什么问题,带来什么收益。若对小组利益不大,对公司整体利益较大,此时需要协调更高层级的管理者才能够推动。

先救火、再优化、后重构

如果一个系统问题过多、程序过于复杂,那么直接重构可能会非常困难。采用“先救火、再优化、后重构”的策略,将有限的资源集中解决一类问题,有多种好处:(1) 目标明确,决策和方案相对容易 (2) 每个阶段都可看到结果,信心 up。比如说第一阶段的“救火”,做完之后,系统很少有因为机器过载、缓存响应慢、虚拟机挂死等问题导致的故障了;完成第二阶段的事项后,因为组件、外部系统故障导致系统故障的问题也很少了。

  • 救火阶段:机器扩容、业务降级、立体化监控等
  • 优化阶段:缓存组件化、队列组件化、接入服务中心等
  • 重构阶段:核心与非核心业务分离、业务中台、公共能力组件化等

例如,S 系统是一个单点登录系统,是一主多从形式。如果主库因为压力挂了,会导致后续所有系统不可用。或者如果整个机房都挂了,也是如此。此时,“救火”阶段做了扩容(防止资源不足导致系统被压死)和 Nginx 一键切换功能(故障时快速切换);优化阶段将一些明显的可用性问题解决(包括性能问题等);重构阶段将原来的单点数据库改为多中心。

总结就是“分段实施”,将要解决的问题根据优先级、重要性、实施难度等划分为不同的阶段,每个阶段聚焦于一个整体的目标,集中精力和资源解决一类问题。“分段实施”的策略:(1) 找到高优先级任务,先救火 (2) 问题分类 (3) 先易后难 (4) 循序渐进,每个阶段不可超过 3 个月,否则再拆分。其中,问题分类方面参考:性能类,可用性类、可扩展类、管理类、流程类、测试类等,还可以继续分类,例如性能类可以分:数据库类、缓存类、外部系统依赖类等。

这里的问题分类,有点类似于系统可能出现什么问题,或者当前系统或公司可以有哪些改造之处。

本二级标题“架构重构”内容来自于:45 | 架构重构内功心法第一式:有的放矢46 | 架构重构内功心法第二式:合纵连横47 | 架构重构内功心法第三式:运筹帷幄

杂谈

Shawn:“PPT 架构师”的口头禅是“细节不讨论”,一个优秀的架构师,需要对细节有多少考虑呢?

华仔:这是一个非常好的问题,也是很多同学困惑的问题,我分享一下我的做法,以我学习 Elasticsearch 为例,具体的做法是:

  • 搭建一个单机伪集群,搭建完成后看看安装路径下的文件和目录,看看配置文件有哪些配置项,不同的配置项会有什么样的影响。
  • 执行常用的操作,例如创建索引,插入、删除、查询文档,查看一下各种输出。
  • 研究其基本原理,例如索引、分片、副本等,研究的时候要多思考,例如索引应该如何建,分片数量和副本数量对系统有什么影响等。
  • 和其他类似系统对比,例如 Solr、Sphinx,研究其优点、缺点、适用场景。
  • 模拟一个案例看看怎么应用。例如,假设我用 Elasticsearch 来存储淘宝的商品信息,我应该如何设计索引和分片。
  • 查看业界使用的案例,思考一下别人为何这么用;看看别人测试的结果,大概了解性能范围。
  • 如果某部分特别有兴趣或者很关键,可能去看源码,例如 Elasticsearch 的选举算法(我目前还没看 ^_^)。
  • 如果确定要引入,会进行性能和可用性测试。

这样一套组合拳下来,基本上能够满足在架构设计时进行选型判断,而且花费的时间也不多。我并不建议拿到一个系统一开始就去读源码,效率太低,而且效果也不好。

主要还是积累不够,清点一下自己看过的书,做个的项目,研究过的系统,看看到底有多少。

想问下华哥,有没有技术方案相关的文章详解及文档模板呢,比如说现在有业务场景需要预研引入新技术,但是这种新技术在宽度上有其他同类型的,这种情况下,这种技术选型有哪些方面需要考虑,最终选定了其中一种后,预研的时候又该做什么,最终形成的预研文档需要呈现出哪些内容,想学习这方面的知识
作者回复: 预研文档一般包括如下几部分内容:
1)方案本质:本质是指方案的核心原理,例如 MySQL 是 OLTP、Clickhouse 是 OLAP、HBase 是 sorted map、Redis 是 data structure store,本质决定了方案的基本原理和大概的实现方案,redis 再怎么牛逼,都不能完全替代 mysql,这就是本质决定的。
2)总体架构:技术方案由哪些部分组成,每部分的作用是什么,目的在于整体了解方案的复杂度、如何部署等
3)核心能力:核心能力决定了方案的应用场景,理解核心能力才能知道具体怎么应用。
4)优缺点:与已有方案对比的优缺点
5)典型场景测试:包括性能测试、可靠性测试、压力测试等,按照你自己的业务来设计场景。