从0开始学架构
01 | 架构到底是指什么?
软件架构指软件系统的顶层结构
02 | 架构设计的历史背景
20 世纪 60 年代第一次软件危机引出了“结构化编程”,创造了“模块”概念;
20 世纪 80 年代第二次软件危机引出了“面向对象编程”,创造了“对象”概念;
20 世纪 90 年代“软件架构”开始流行,创造了“组件”概念
03 | 架构设计的目的
是为了解决软件系统复杂度带来的问题
04 | 复杂度来源:高性能
单台计算机内部为了高性能带来的复杂度
多台计算机集群为了高性能带来的复杂度
任务分配:任务分配的意思是指每台机器都可以处理完整的业务任务,不同的任务分配到不同的机器上执行。
任务分解
简单的系统更加容易做到高性能、可以针对单个任务进行扩展
05 | 复杂度来源:高可用
高可用:系统无中断地执行其功能的能力,代表系统的可用性程度,是进行系统设计时的准则之一。
高性能增加机器目的在于“扩展”处理性能;高可用增加机器目的在于“冗余”处理单元
计算高可用:这里的“计算”指的是业务的逻辑处理
存储高可用:对于需要存储数据的系统来说,整个系统的高可用设计关键点和难点就在于“存储高可用”
高可用状态决策
1. 独裁式:独裁式决策指的是存在一个独立的决策主体,我们姑且称它为“决策者”,负责收集信息然后进行决策;所有冗余的个体,我们姑且称它为“上报者”,都将状态信息发送给决策者
2. 协商式:协商式决策指的是两个独立的个体通过交流信息,然后根据规则进行决策,最常用的协商式决策就是主备决策
3. 民主式:民主式决策指的是多个独立的个体通过投票的方式来进行状态决策。例如,ZooKeeper 集群在选举 leader 时就是采用这种方式
06 | 复杂度来源:可扩展性
可扩展性:可扩展性指系统为了应对将来需求变化而提供的一种扩展能力,当有新的需求出现时,系统不需要或者仅需要少量修改就可以支持,无须整个系统重构或者重建
第一种应对变化的常见方案是将“变化”封装在一个“变化层”,将不变的部分封装在一个独立的“稳定层”
第二种常见的应对变化的方案是提炼出一个“抽象层”和一个“实现层”
07 | 复杂度来源:低成本、安全、规模
低成本、安全(1. 功能安全、2. 架构安全)、规模
08 | 架构设计三原则
合适原则:合适优于业界领先
简单原则:简单优于复杂
演化原则:演化优于一步到位
设计出来的架构要满足当时的业务需要
架构要不断地在实际应用过程中迭代,保留优秀的设计,修复有缺陷的设计,改正错误的设计,去掉无用的设计,使得架构逐渐完善
当业务发生变化时,架构要扩展、重构,甚至重写;代码也许会重写,但有价值的经验、教训、逻辑、设计等(类似生物体内的基因)却可以在新架构中延续
09 | 架构设计原则案例
10 | 架构设计流程:识别复杂度
识别复杂度实战:这个消息队列是否需要高性能、这个消息队列是否需要高可用性、这个消息队列是否需要高可扩展性
11 | 架构设计流程:设计备选方案
第一种常见的错误:设计最优秀的方案、第二种常见的错误:只做一个方案、第三种常见的错误:备选方案过于详细
设计备选方案实战:
1. 备选方案:采用开源的 Kafka:Kafka 是成熟的开源消息队列方案,功能强大,性能非常高,而且已经比较成熟,很多大公司都在使用
2. 备选方案:集群 + MySQL 存储
采用数据分散集群的架构,集群中的服务器进行分组,每个分组存储一部分消息数据。
每个分组包含一台主 MySQL 和一台备 MySQL,分组内主备数据复制,分组间数据不同步。
正常情况下,分组内的主服务器对外提供消息写入和消息读取服务,备服务器不对外提供服务;主服务器宕机的情况下,备服务器对外提供消息读取的服务。
客户端采取轮询的策略写入和读取消息。
3. 备选方案:集群 + 自研存储方案
在备选方案 2 的基础上,将 MySQL 存储替换为自研实现存储方案,因为 MySQL 的关系型数据库的特点并不是很契合消息队列的数据特点,参考 Kafka 的做法,可以自己实现一套文件存储和复制方案(此处省略具体的方案描述,实际设计时需要给出方案)。
12 | 架构设计流程:评估和选择备选方案
最简派:设计师挑选一个看起来最简单的方案。
最牛派:最牛派的做法和最简派正好相反,设计师会倾向于挑选技术上看起来最牛的方案
最熟派:设计师基于自己的过往经验,挑选自己最熟悉的方案
领导派:领导派就更加聪明了,列出备选方案,设计师自己拿捏不定,然后就让领导来定夺,反正最后方案选的对那是领导厉害,方案选的不对怎么办?那也是领导“背锅”。
360 度环评:列出我们需要关注的质量属性点,然后分别从这些质量属性的维度去评估每个方案,再综合挑选适合当时情况的最优方案。
常见的方案质量属性点有:性能、可用性、硬件成本、项目投入、复杂度、安全性、可扩展性等
按优先级选择:综合当前的业务发展情况、团队人员规模和技能、业务发展预测等因素,将质量属性按照优先级排序,首先挑选满足第一优先级的,如果方案都满足,那就再看第二优先级……以此类推。
架构师经过思考后,给出了最终选择备选方案 2,原因:
排除备选方案 1 的主要原因是可运维性,因为再成熟的系统,上线后都可能出问题,如果出问题无法快速解决,则无法满足业务的需求;并且 Kafka 的主要设计目标是高性能日志传输,而我们的消息队列设计的主要目标是业务消息的可靠传输。
排除备选方案 3 的主要原因是复杂度,目前团队技术实力和人员规模(总共 6 人,还有其他中间件系统需要开发和维护)无法支撑自研存储系统(参考架构设计原则 2:简单原则)。
备选方案 2 的优点就是复杂度不高,也可以很好地融入现有运维体系,可靠性也有保障
针对备选方案 2 的缺点,架构师解释是:
备选方案 2 的第一个缺点是性能,业务目前需要的性能并不是非常高,方案 2 能够满足,即使后面性能需求增加,方案 2 的数据分组方案也能够平行扩展进行支撑(参考架构设计原则3:演化原则)。
备选方案 2 的第二个缺点是成本,一个分组就需要 4 台机器,支撑目前的业务需求可能需要12 台服务器,但实际上备机(包括服务器和数据库)主要用作备份,可以和其他系统并行部署在同一台机器上。
备选方案 2 的第三个缺点是技术上看起来并不很优越,但我们的设计目的不是为了证明自己(参考架构设计原则 1:合适原则),而是更快更好地满足业务需求。
13 | 架构设计流程:详细方案设计
例如,Nginx 的负载均衡策略,简单按照下面的规则选择就可以了
轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器,后端服务器分配的请求数基本一致,如果后端服务器“down
加权轮询:根据权重来进行轮询,权重高的服务器分配的请求更多,主要适应于后端服务器性能不均的情况,如新老服务器混用。
ip_hash:每个请求按访问 IP 的 hash 结果分配,这样每个访客固定访问一个后端服务器,主要用于解决session 的问题,如购物车类的应用。
fair:按后端服务器的响应时间来分配请求,响应时间短的优先分配,能够最大化地平衡各后端服务器的压力,可以适用于后端服务器性能不均衡的情况,也可以防止某台后端服务器性能不足的情况下还继续接收同样多的请求从而造成雪崩效应。
url_hash:按访问 URL 的 hash 结果来分配请求,每个 URL 定向到同一个后端服务器,适用于后端服务器能够将 URL 的响应结果缓存的情况。
1.数据库表如何设计?
数据库设计两类表,一类是日志表,用于消息写入时快速存储到 MySQL 中;另一类是消息表,每个消息队列一张表。
业务系统发布消息时,首先写入到日志表,日志表写入成功就代表消息写入成功;后台线程再从日志表中读取消息写入记录,将消息内容写入到消息表中。
业务系统读取消息时,从消息表中读取。
日志表表名为 MQ_LOG,包含的字段:日志 ID、发布者信息、发布时间、队列名称、消息内容。
消息表表名就是队列名称,包含的字段:消息 ID(递增生成)、消息内容、消息发布时间、消息发布者。
日志表需要及时清除已经写入消息表的日志数据,消息表最多保存 30 天的消息数据。
2.数据如何复制?
直接采用 MySQL 主从复制即可,只复制消息存储表,不复制日志表。
3.主备服务器如何倒换?
采用 ZooKeeper 来做主备决策,主备服务器都连接到 ZooKeeper 建立自己的节点,主服务器的路径规则为“/MQ/server/ 分区编号 /master”,备机为“/MQ/server/ 分区编号/slave”,节点类型为 EPHEMERAL。
备机监听主机的节点消息,当发现主服务器节点断连后,备服务器修改自己的状态,对外提供消息读取服务。
4.业务服务器如何写入消息?
消息队列系统设计两个角色:生产者和消费者,每个角色都有唯一的名称
消息队列系统提供 SDK 供各业务系统调用,SDK 从配置中读取所有消息队列系统的服务器信息,SDK 采取轮询算法发起消息写入请求给主服务器。如果某个主服务器无响应或者返回错误,SDK 将发起请求发送到下一台服务器。
5.业务服务器如何读取消息?
消息队列系统提供 SDK 供各业务系统调用,SDK 从配置中读取所有消息队列系统的服务器信息,轮流向所有服务器发起消息读取请求。
消息队列服务器需要记录每个消费者的消费状态,即当前消费者已经读取到了哪条消息,当收到消息读取请求时,返回下一条未被读取的消息给消费者。
6.业务服务器和消息队列服务器之间的通信协议如何设计?
考虑到消息队列系统后续可能会对接多种不同编程语言编写的系统,为了提升兼容性,传输协用 TCP,数据格式为 ProtocolBuffer。
14高性能数据库集群:读写分离
15搞性能数据库集群:分库分表
16高性能NoSQL
关系型数据库缺点
储存的是行记录,无法储存数据结构
schema扩展很不方便
全文搜索功能比较弱
NoSQL方案
K-V存储:解决无法储存数据结构的问题,redis
文档数据库:解决强schema约束的问题,MongoDB
数据格式:json
新增字段简单、历史数据不会出错
不支持事务、无法实现join操作
列式数据库,解决大数据场景下的I/O问题,HBase
读取多列时效率高、能够一次性完对多个列的写操作、具备更高的储存压缩比,适用于离线的大数据分析和统计
全文搜索引擎:解决全文搜索性能问题,Elasicsearch
17高性能缓存架构
缓存穿透:缓存没有发挥作用
储存数据不存在,可以设置默认值(空值或具体值)
缓存数据生成耗费大量时间或者资源,禁止爬虫或做好监控
缓存雪崩:当缓存过期被清除后,业务系统需要重新生成,会引起系统性能急剧下降
更新锁:对缓存更新进行加锁保护,保证只有一个线程进行缓存更新,集群要采用分布式锁
后台更新:后台线程更新缓存,缓存本身设置为永久,后台定时更新
缓存不够时会踢掉部分缓存,在这部分缓存没有到更新时间,会返回空值
后台线程频繁读取缓存,发现被踢立即更新,读取间隔不能太长
缓存失效后,通过消息队列发送通知后台线程进行更新缓存,后台线程验证缓存是否存在,不存在就更新
缓存热点:对于特别热点的数据,复制多份缓存副本,将请求分散到多个缓存服务器,设置过去时间为指定范围内的随机值
18单服务器高性能模式:PPC和TPC
并发模式关键点:如何管理连接、如何处理请求
I/O模型:阻塞、非阻塞、同步、异步
进程模式:但进程、多进程、多线程
PPC:每次有新的连接就新建一个进程专门处理请求
fork代价高、父子进行通信复杂、支持的并发连接数量有限
prefork:提前创建进程
TPC:共享进行内存空间
prethread:预先创建线程
19单服务器高性能模式:Reactor(反应堆)与Proactor
Reactor:创建进程池,将连接分配给进程,一个进程可以处理多个连接业务
I/O多路复用
当多条连接共用一个阻塞对象后,进程只需要在一个阻塞对象上等待,而无须再轮询所有连接,例如select、epoll、kqueue
当某条连接有新的数据可以处理时,操作系统会通知进程,进程从阻塞状态返回,开始进行业务处理
Reactor负责监听和分配事件,处理资源池负责处理事件
Reactor的数量可以变化
资源池的数量可以变化
实现方案:单Reactor多线程、多Reactor多进程、多Reactor多线程
单Reactor单进程/线程
Reactor对象通过select监控连接事件,收到事件后通过dispatch进行分发
如果是连接建立的事件,则由Acceptor处理,Acceptor通过accept接受连接,并创建一个handler处理连接后续的各种事件
如果不是连接事件,则Acceptor会调用连接对应的handler来进行响应
单Acceptor多线程
主线程中Reactor对象通过select监控连接事件,收到后通过dispatch进行分发,如果是连接事件,则由Accept处理,通过handler进行后续处理
如果不是连接建立事件,则Reactor会调用连接对应的handler来进行响应
handler只负责响应事件,不进行业务处理,handler通过read读取到数据后,会发给processor进行业务处理
processor会在独立的子线程中完成真正的业务处理,然后将响应结构发给主进程的handler处理,handler收到响应后通过send将响应结构返回给client
问题:多线程数据共享和访问比较复杂、Reactor承担所有事件的监听和响应,只在主线程中运行,瞬间高并发时会称为性能瓶颈
多Reactor多进行/线程
父进程中mainReactor对象通过select监控连接建立事件,收到事件后通过Acceptor接收,将新的连接分配给某个子进程
子进行的subReactor将mainReactor分配的连接加入连接队列进行监听,并创建一个handler用于处理连接的各种事件
当有新的事件发生时,subReactor会调用连接对应的handler来进行响应
handler完成read->业务处理->send的完整业务流程
比单Reactor多线程简单
父进程和子进程的职责,父进程只负责接收新连接,子进程负责完成后续的业务处理
父进程和子进程的交互很简单,父进程只需要把新连接传给子进程,子进程无须返回数据
子进程之间是相互独立的,无须同步共享之类的处理
Proactor(主动器)是非阻塞同步网络模型
Proactor Initiator负责创建Proactor和handler,并将Proactor和handler都通过Asynchonous Operation Processor注册内核
Asynchonous Operation Processor负责处理注册请求,并完成I/O操作
Asynchonous Operation Processor完成I/O操作后通知Proactor
handler完成业务处理,handler也可以注册新的Proactor 到内核进程
20高性能负载均衡:分类及架构
DNS负载均衡:根据地区分配
优点
简单、成本低:负载均衡工作交给DNS服务器处理,无须自己开发或者维护负载均衡设备
就近访问,提升访问速度:dns解析时可以根据请求来源ip,解析成距离用户最近的服务器地址,可以尽快访问速度,改善性能
缺点
更新不及时:dns缓存的时间比较长,修改dns配置后,由于缓存的原因,还是有很多用户会继续访问修改前的ip,这样的访问会失败,达不到负载均衡的目的,并且也影响用户正常使用业务
扩展性差:dns负载均衡的控制权在域名商那里,无法根据业务特定针对其做更多的定制化功能和扩展特性
分配策略比较简单:dns负载均衡支持的算法少,不能区分服务器差异,也无法感知后端服务器的状态
硬件负载均衡:通过单独的硬件设备来实现负载均衡功能,类似路由器或交换机
优点:
功能强大:全面支持各层级的负载均衡,支持全面的负载均衡,支持全局负载均衡
性能强大:相比软件负载均衡的10万级并发,硬件负载均衡可以达到100万以上的并发
稳定性高:商用硬件负载均衡,经过了良好的严格测试,经过大规模使用,稳定性高
支持安全防护:硬件负载均衡还具备防火墙、放DDos攻击等安全防护
缺点:
价格昂贵:普通的F5、好的马6,最好的Q7
扩展性能差:邮件设备可以根据业务进行配置,但无法进行扩展和定制
软件负载均衡
Nginx的软件负载均衡
优点
简单:部署和维护都简单
便宜:买个linux服务器,装软件就可以使用
灵活:4层和7层负载均衡可以根据业务进行选择,也可以根据业务进行方便的扩展
缺点
性能一般,大约5万并发
功能没有硬件负载均衡强大
一般不具备防火墙和放ddos攻击等安全功能
DNS适用于地理级别、硬件负载均衡适用于集群级别、软件负载均衡适用于机器级别
21高性能负载均衡:算法
任务平分类:绝对平均或比例平均
轮询:按照顺序轮流分配到服务器上。
加权轮询:根据服务器权重进行任务分配,根据硬件配置进行静态配置,动态计算会更加契合业务,但复杂度更高
负载均衡类:将任务分配给当前负载最低的服务器,根据不同业务类型和业务场景用不同指标来衡量
最小连接数优先的算法、CPU负载最低优先的算法
性能最优类:根据服务器的响应时间来进行任务分配,优先将新任务分配给响应最快的服务器
通过采样统计任务响应时间,需要选择合适的周期
Hash类:负载均衡系统根据任务中的某些关键信息进行hash运算,将相同hash值的请求分配给相同的服务器
源地址Hash:将来源于同一个ip地址的任务分配给同一个服务器进行处理,适合于存在事务、会话的业务。
IDhash:将某个ID标识的业务分配到同一个服务器中进行处理,这里的ID一般是临时性数据的ID,例如sessionid的hash可以实现用户每次访问相同服务器
22想成为架构师,你必须知道CAP理论
一致性、可用性、分区容忍性
23想成为架构师,你必须掌握的CAP细节
CAP关注的粒度是数据,而不是整个系统
CAP是忽略网络延迟的
正常运行情况下,不存在CP和AP的选择,可以同时满足CA
放弃不等于什么都不做,需要为分区恢复后做准备
ACID:数据库管理系统为了保证事务的正确性而提出来的理论。
原子性:事务中的所有操作要么全部完成,要么全部失败。
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏
隔离性:数据库防止多个事务并发执行读提交、可重复读、串行化
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
BASE:基本可用、软状态、最终一致性
基本可用:分布式系统在出现故障时,允许损失部分可用性,保证核心可用
软状态:允许系统存在中间状态,而该中间状态不会允许系统整体可用性
最终一致性:系统中的所有数据副本经过一定时间后,最终能够达到一致的状态
24FMEA方法,排除架构可用性隐患的利器
FMEA故障模式与影响分析
给出初始的架构设计图
假设架构中某个部件发生故障
分析此故障对系统功能造成的影响
根据分析结果,判断架构是否需要优化
分析表:
功能点:用户角度来看
故障模式:系统会出现什么样的故障,包括故障点和故障形式,描述需要精确,量化描述
故障影响:当发生故障模式中描述的故障时,功能点具体会受到什么影响
严重程度:站在业务的角度故障的影响程度,分为“致命、高、中、低、无”五个档次。严重程度=功能点重要程度*故障影响范围*功能点受损程度,以登录系统为例
故障原因:不同的故障原因发生概率不同、不同的故障原因检测手段不一样、不同的故障原因的处理措施不一样
故障概率:某个具体故障原因发生的概率。
硬件:硬件随着使用时间推移,故障概率会越来越高
开源系统:成熟的开源系统bug率低,刚发布的开源系统bug率相比会高一些
自研系统:成熟的低,新开发的高
风险程度:综合严重程度和故障概率判断某个故障的最终等级,风险程度=严重程度*故障概率
已有措施:针对具体的故障原因,系统现在是否提供了某些措施来一堆
检查告警:检查故障,然后告警,人工处理
检查故障后,系统通过备份手段应对
自恢复:检测到故障后,系统能够自己恢复(恢复业务)
规避措施:为了降低故障发送概率而采取的手段
技术手段:为了避免引入的MongoDB丢失数据,在mysql中冗余一份
管理手段:为了降低磁盘坏道的概率,强制统一更新服务器时间超过2年的磁盘
解决措施:解决问题做的技术手段
解决密码暴力破解,增加密码重试次数限制
解决拖库导致数据泄露,将数据库中的敏感数据加密保存
解决非法访问,增加白名单控制
后续规划:针对不足的地方结合风险程序进行排序,给出后续的改进规划
实战:
25高可用储存架构:双机架构
主备复制
实现
备机起备份作用,不承担实际的业务读写操作,切换为主机需要人工操作
优点
对于客户端,不需要感知备机的存在
对于主机和备机,只需要进行数据复制,无须进行状态判断和主备切换
缺点
备机仅仅只是备份,并没有提供读写操作,硬件成本上有浪费
故障后需要人工干预,无法自动恢复
适用于内部的后台管理系统
主从复制:主机负责读写,从机负责读操作
实现
优点
主机发生故障时,读操作业务可以继续运行
从机提供读操作,发挥了硬件的性能
缺点
客户端需要感知主从关系,将不同的操作发给不同的机器
从机提供读业务,如果主从复制延迟比较大,业务会出现不一致
故障时需要人工干预
适用于写少读多的业务:例如论坛、bbs、新闻网站
双机切换
设计关键:增加切换功能
主备间状态判断:状态传递的渠道以及状态检测的内容
切换决策:切换时机(什么情况下切换)、切换策略(故障恢复后的处理)、自动程度(是否需要人工确认切换)
数据冲突解决:故障恢复后,新旧主机数据发生冲突时的处理
互连式:主备机直接建立状态传递的渠道
状态传递通道
客户端的改变
缺点:多通道只能降低通道故障概率,客户端可能收到不同的状态信息
中介式:引入第三方中介,通过中介传递状态信息
连接更简单:主备机无效建立通道
状态决策更简单:主备机无效考虑多种类型的连接通道获取的状态信息如何决策的问题
成熟方案:ZooKeeper
模拟式:主备机之间并不传递任何状态数据,备机模拟成客户端,向主机发起模拟的读写操作,根据读写操作的响应情况判断主机状态
主主复制:两台机器都是主机,互相将数据复制给对方,客户端可以任意挑选机器读写
优点
缺点
适用于临时性,可丢失,可覆盖的数据场景,例如:session数据(可重新生成)、用户行为日志(可丢失)、论坛的草稿数据(可丢失)
26高可用储存架构:集群和分区
数据集中集群:一主多备/从
主机如何将数据复制给备机
主机故障后,如何决定新的主机,ZooKeeper通过ZAB算法解决
适用于数据量不大,集群机器数量不多的场景,5台左右
数据分散集群:多个服务器组成集群,每台服务器都会复制储存部分数据,同时备份部分数据
均衡性:保证数据分区基本均衡
容错性:出现故障时,将原来分配给故障服务器的数据分区分配给其他服务器
可伸缩性:集群容量不够需要扩充时,能自动将部分数据分区迁移到新服务器,并保证扩容后所有服务器的均衡性
适用于业务类巨大,机器机器数量庞大的业务场景
数据分区:将数据安装一定的故障进行分区,不同分区分布在不同的地理位置上
数据量:数据量大小直接决定了分区的规则复杂度
分区规则:通过地理位置进行分区,包括洲际分区、国家分区、城市分区
复制规则
集中式备份:存在一个总的备份中心,所有的分区都将数据备份到中心
扩展容易,成本较高
互备式:每个分区备份到另外一个分区的数据
设计复杂、扩展麻烦、成本低
独立式:每个分区自己有独立的备份中心
设计简单,扩展容易,成本高
27如何设计计算高可用架构
1哪些服务执行任务
每个服务器都执行、主机执行
2任务如何重新执行
失败不处理、任务管理器
3主备
设计
备机状态
使用场景:使用人数不多,频率不高的业务,不适合在线业务
4.主从
方案设计
优缺点
5对称集群:每个服务器角色一样
架构图
设计
选择分配策略:轮询或随机
检测服务器状态:心跳检测
6.分对称集群:不同服务器角色不同
架构示意图
方案设计
复杂度
28业务高可用的保障:异地多活架构
1.活
2.代价
3.架构模式
- 同城同区:将业务部署在同一个城市不同区的多个机房
- 跨城异地:将业务部署在不同城市的多个机房,适用于数据丢失影响也不大的业务,例如用户登录(可重新登录)、新闻网站(一天数据变化少)、微博网站(丢失用户发布的微博或者评论影响不大)
- 跨国异地:业务部署在不同国家的多个机房
4.为不同地区用户提供服务
例如亚马逊中国为中国用户服务,亚马逊美国为美国用户服务
5.只读类业务做多活
谷歌搜索业务,各地搜索结果相同
29异地多活设计4大技巧
1.保证核心业务的异地多活
1.注册问题:一个手机号注册一个账户属于核心业务规则,不建议修改
2.用户信息问题:无法保证机器时间绝对一致
3.解决方法:优先实现核心业务的异地多活结构
2.保证核心数据最终一致性
1.尽量减少机房距离,搭建高速网络
2.尽量减少数据同步,只同步核心业务相关的数据
3.保证最终一致性,不保证实时一致性
3.采用多种手段同步数据
1.消息队列方式:通过消息队列同步到其他业务中心
2.二次读取方式:本地读取失败,读取对端
3.储存系统同步方式:通过数据库的同步机制将数据复制到其他业务中心即可
4.回源读取方式
5.重新生成数据方式
6.综合措施
4.只保证绝大部分用户的异地多活
1.挂公告:说明现在有问题的原因,可以发布“技术给个正在紧急处理”
2.事后对用户进行补偿:送一些业务上可用的代金券
3.补充体验
30 异地多活设计4步走
1.业务分级:按照异地的表中将业务进行分级,挑选出核心的业务,只为核心业务设计异地多活,降低方案整体复杂度和实现成本
访问量大的业务、产生大量收入的业务
2.数据分类:识别所有的数据及数据特征
1.数据量:包括新增、修改、删除的量,数据量越大,同步延迟的几率越高
2.唯一性:数据是否要求多个异地机房产生的同类数据必须保证唯一
3.实时性:实时性要求越高,对同步的要求就越高,方案越复杂
4.可丢失性:例如session数据
5.可恢复性:是否可以通过某种手段进行恢复
3.数据同步
1.储存式同步
2.消息队列同步:常见的有Kafka、ActiveMQ、RocketMQ,适合无视我想或者无时序性要求的数据
3.重复生成:数据不同步到异地机房,每个机房生成数据,适合可重复生成的数据,例如session
4.异常处理
1目的:
2.措施
1.多通道同步:采取多种方式进行数据同步
技术关键点:
2.同步和访问结合:异地机房通过系统的接口进行数据访问
技术关键点
3.日志记录:用于用户故障恢复后对数据进行恢复
服务器保存日志,数据库保存数据
本地独立系统保存日志
日志异地保存
4.用户补偿
31.如何应对接口级故障
1.原因
内部原因:程序bug死循环
外包原因:黑客攻击、促销或者抢购
2.降级:系统将某些业务或者接口的功能降低,可以只提供部分功能,也可以完全停掉所有功能,丢车保帅,保证核心业务
系统后门降级:系统预留降级操作
独立降级系统:将降级操作独立到一个独立的系统中
熔断:应对依赖的外部系统故障
3.限流:限制访问量
1.基于请求限流
限制总量:限制某个指标的累计上限
限制时间量:限制一段时间内某个指标的上限
适用于:负载均衡系统、网关系统、抢购系统
2.基于资源限流
3.排队:让用户等待一段时间
架构图
排队模块:负责用户的抢购请求,将请求以先入先出的方式保存下来
调度模块:负责排队模块到服务模块的动态调度,不断检查服务模块,一旦处理能力有空闲,就从列头上吧用户访问请求调入服务模块,并负责想服务模块分发请求。
32.可扩展架构的基本思想和模式
1.面向流程拆分
1.分层含义
2.架构
3.优势:大部分只需修改一层,不会出现所有层都同时修改
4.典型架构:分层架构
2.面向服务拆分
1.优势:可以直接扩展相关服务,无须修改所有服务
2.典型架构:SOA、微服务
3.面向功能拆分
1.每个服务都可以拆分为更多细粒度的功能
2.架构图
3.可以直接扩展功能,无须修改所有服务
4.典型架构:微内核架构
33.传统的可扩展的架构模式:分层架构和SOA
1.C/S架构、B/S架构:
划分对象:整个业务系统
划分维度:用户交互
2.MVC架构、MVP架构:
划分对象:单个业务系统
划分维度:职责
3.逻辑分层架构
划分对象:单个业务子系统或整个系统
划分维度:职责
特定:层层传递、性能浪费
4.SOA面向服务的架构
1.背景
2.服务:所有业务都是一项服务,当其他系统需要使用这项功能时,无效定制化开发
3.ESB(企业服务总线):将各个不同的服务连接在一起
4.松耦合:减少各个服务间的依赖和互相影响
5.架构图
34深入理解微服务:银弹or焦油坑
1.微服务是SOA的实现方式
2.微服务是去掉ESB的SOA
3.微服务是一种和SOA相似但本质上不同的架构理念
4.服务粒度:粒度较小
5.服务通信:采用统一的协议和格式
6.服务支付:快速交付、自动化测试、持续集成、自动化部署
7.应用场景:适合快速、轻量级、基于web的互联网系统
8.对比
9.大坑:
1.服务划分过细,服务间关系复杂
2.服务数量太多,团队效率急剧下降
3.调用链太长,性能下降
4.调用链太长,问题定位困难
5.没有自动化支撑,无法快速交付
6.没有服务治理,微服务数量多了后管理混乱
35.微服务架构最佳实践-方法篇
1.服务粒度
2.拆分方法
1.基于业务逻辑拆分:将系统中的业务模块按照职责范围识别处理,每个单独的业务模块拆分为一个独立的服务
2.基于可扩展拆分:将系统中的业务模块按照稳定性排序,将已经成熟和改动不大的服务拆分为稳定服务,将经常变化和迭代的服务拆分为变动服务
3.基于可靠性拆分:将系统中的业务模块按照优先级排序,将可靠性要求高的核心服务和可靠性要求低的非核心服务拆分开来,然后重点保证核心服务的高可用
1.避免非核心服务故障游戏核心服务
2.核心服务高可用方案可以更简单
3.能够降低高可用成本
4.基于性能拆分:将性能要求高或者性能压力大的模块拆分处理,避免性能压力大的服务影响其他服务
3.基础设施
4.设施优先级
36.微服务架构最佳实践-基础设施篇
1.自动化测试:完成大部分测试回归的工作
2.自动化部署:包括版本管理、资源管理、部署操作、回退操作
3.配置中心:统一的配置中心管理微服务节点的配置,配置版本管理、增删改查配置、节点管理、配置同步、配置推送
4.接口框架:统一协议和传递的数据格式
5.API网关:负责外包系统的访问操作,包括接口鉴全(是否允许接入)、权限控制(可以访问哪些功能)、传输加密、请求路由、流量控制
6.自理式服务发现:每个微服务自己完成服务发现,统一程序包提供
7.代理式服务发现:服务直接有一个负载均衡系统来完成服务发现
服务注册表记录所有服务节点的配置和状态,服务启动需要将自己的信息注册到服务注册表,需要到服务注册表查询可用服务
8.服务路由:从符合条件的可用微服务节点中挑选出具体的节点发起请求
路由算法:随机路由、轮询路由、最小压力路由、最小连接数路由
9.服务容错:包括请求重试、流控和服务隔离,集成在服务发现和服务路由中
10.服务监控:独立的系统
1.实时搜集信息并分析,避免故障后再来分析,减少处理时间
2.在问题萌芽的阶段发觉并预警,降低问题影响的范围和时间
11.服务跟踪:记录某次请求的发起时间、响应时间、响应错误码、请求参数、返回的json对象等信息
12.服务安全:接入安全、数据安全、传输安全,可以集成到配置中心系统
37.微内核架构详解
1.基本架构
1.核心系统:负责具体业务功能无关的通用功能,例如模块加载、模块间通信
2.插件模块:负责实现具体的业务逻辑
2.设计关键点
1.插件管理:核心系统需要知道哪些插件可用,插件注册表进行实现,包含模块的名字、位置、加载时机(启动加载/按需加载)
2.插件连接:插件如何连接到核心系统。核心系统知道插件和核心系统的连接规范,然后插件安装规范实现,核心系统安装规范加载即可。OSGi、消息模式、依赖注入
3.插件通信:插件之间相互通信
3.OSGi架构
1.模块层:实现插件管理功能
2.生命周期层:实现插件连接功能,提供了执行时模块管理、模块对底层OSGi框架的访问,定义了bundle生命周期的操作(安装、更新、启动、停止、卸载)
3.服务层:实现了插件通信的功能。用于各个插件将自己的服务注册到OSGi核心的服务注册中心,某个服务可以通过搜索服务中心使用其他服务
4.规则引擎架构
1.可扩展:业务实现与业务系统分离,方便扩展
2.易理解:规则通过自然语言描述,业务容易易理解和操作
3.高效率:提供可视化的规则定制、审批、查询及管理,方便业务人员快速配置新的业务
4.架构图
5.使用
6.插件管理:规则类似插件、引擎类似内核
7.插件连接:基于规则语言编写规则文件
8.插件通信:规则通信采用数据流和事件流,规则不需要依赖其他规则,没有主动通信,只需要输出数据或者事件,由引擎传递
38.架构师应该如何判断技术演进的方向
1.潮流派:热衷新技术,紧跟技术潮流
技术不成熟很可能遇到坑,学习成本高,容易造成人力浪费
2.保守派:使用稳定成熟的技术
不能享受新技术带来的收益
3.跟风派:跟着竞争对手的步子走
适用于对手的技术不一定适用于自己
4.技术演进的动力
产品类业务:技术创新推断业务发展
服务类业务:业务发展推断技术的发展
5.技术演进的模式
基于业务发展阶段判断业务当前和接下来一段时间的注意复杂度
39.互联网技术演进的模式
1.业务复杂性
1.初创期:要求快
2.发展期:完善业务,堆功能期->优化期(优化派/架构派)
3.架构期:拆功能、拆数据库、拆服务器
4.竞争期:重复造轮子、系统交互一团乱麻
平台化:储存平台化(淘宝的TFS、京东的JFS)、数据库平台化(百度的DBProxy、淘宝的TDDL)、缓存平台化(豆瓣的BeansDB、腾讯的TTC)
服务化:通过消息队列完成系统间的异步通知,消息队列(淘宝的Notify、MetaO、Kafka、ActiveMQ)、服务框架(当当网的Dubbox、淘宝的HSF)
5.成熟期:找出弱项,逐项优化
2.优化规模
性能、可用性、量变到质变
40.互联网架构模板:“储存层技术”
1.架构图
2.SQL
资源分配、数据备份、迁移、容灾、读写分离
3.NoSQL
4.小文件储存
5.大文件储存
41互联网架构模板:“开发层”和“服务层”技术
1.开发层技术
1.开发框架:优选成熟的框架,避免盲目追逐新技术
2.web服务器:例如tomcat
3.容器:例如docker
4.服务层技术:降低系统间相互关联的复杂度
1.配置中心
好处:
2.服务名字系统
3.服务总线系统
4.对比
5.架构图
6.效果
42.互联网架构模板:“网络层”技术
1.负载均衡
1.DNS
2.Nginx、LVS、F5
3.CDN
2.多机房
1.同城多机房
2.跨城多机房
3.跨国多机房
3.多中心
43.互联网架构模板:“用户层”和“业务层”技术
1.用户层技术
1.用户管理:通过互联网将众多分散的用户连接起来
单点登录(统一登录):CAS
2.授权登录:OAuth2.0
2.消息推送
1.设备管理(唯一标识、注册、注销)
2.连接保活
3.储存云、图片云
4.拆系统
5.合系统
44.互联网架构模板:“平台”技术
1.运维平台
1.职责:配置、 部署(将系统发布到线上)、监控(收集系统运行后的相关数据并进行监控,发现问题)、应急(系统故障后的处理)
2.标准化:定制运维标准,规范配置管理、部署流程、监控指标、应急能力,按标准实现
3.平台化:运维操作集成到平台完成
无须运维容易死记硬背运维标准、平台提供简单方便的操作、平台可复用
4.自动化:将重复操作固化下来,由系统自动完成
5.可视化:提升数据查看效率
只管的看到数据的相关属性、将数据的含义展示处理、将关联数据整合一起展示
6.测试平台:单元测试、集成测试、接口测试、性能测试
1.用例管理:通过基本或代码进行测试
2.资源管理:具体环境执行,包括硬件(服务器、手机、平板电脑)、软件(操作系统、数据库、java虚拟机)、业务系统(被测试系统)
3.任务管理:将测试用例分配到具体的资源上执行,跟踪任务的执行情况,将测试平台各部分串联完成自动化测试
4.数据管理:记录相关数据(执行时间、执行结果、执行期间的CPU、内存占用)
2.数据平台
1.数据管理
1.数据采集:从业务系统搜集各类数据,例如用户行为、日志、业务数据
2.数据储存:将采集的数据储存到数据平台
3.负责对外提供各种协议用于读写
4.数据安全:对部分业务敏感数据加以保护
2.数据分析
3.数据应用:包括推荐、广告等在线业务;包括报表、欺诈检测、异常检测等离线业务
4.管理平台:权限管理
1.身份认证:确认当前操作人员身份
2.权限控制:确认操作人员的操作权限
45.架构重构内功心法:有的放矢
1.架构重构原因
1.业务已经上线,不能停下来
2.关联方众多,牵一发而动全身
3.旧架构的约束
2.系统重构
1.重构前
2.重构后
3.游戏接入系统重构,解决全局单点的可用性
1.重构前
2.重构后
4.系统集中的重构
1.重构前
2.重构后
46.架构重构内功心法:合纵连横
1.合纵:划分精力进行游说和沟通,将技术语言转换为通俗语言
2.连横:与相关或者配好的系统的沟通协调
47.架构重构内功心法:运筹帷幄
1.识别系统关键的复杂度问题,做好相关准备
2.案例
3.分段实施,根据优先级、重要性、实施难度划分阶段
4.制定策略
1.优先级排序:将明显且紧急的事项优先落地
2.问题分类:将问题安装性质分类
3.先易后难
4.循序渐进
48.如何选择、使用以及二次开发
1.聚集是否满足业务
2.聚集是否成熟
3.聚集运维能力
4.如何使用
1.深入研究,仔细测试
2.小心应用,灰度发布
3.做好应急,以防万一
5.二次开发
1.保存纯洁,加以包装
2.发明你要的轮子
49.APP架构的演进
1.web app:包壳架构,业务逻辑web实现,app壳完成安装功能
2.原生app
1.web app的问题
3.Hybrid app:对体验要求高的用原生app,对体验要求不高的用web app
4.组件和&容器化:独立开发、测试、上线
静态发布、动态发布
50.架构设计文档模板
1.备选方案模板
1.需求介绍
2.需求分析
3.消息队列
4.约束和限制
5.复杂度分析
1.高可用
2.高性能
3.可扩展:无须扩展
4.备选方案:直接引入kafak、集群+mysql、集群+自研储存
5.备选方案评估
2.架构设计模板
1.总体方案
2.架构总览
3.设计关键点
4.核心流程:消息发送、消息读取
5.详细设计
1.高可用
1.消息发送可靠性
2.消息储存可靠性
3.消息读取可靠性
2.高性能设计
3.可扩展设计
4.安全设计
1.身份识别
2.队列权限
5.其他设计
6.部署方案:硬件要求、服务器部署方式、组网方式
7.架构演进规划
51.架构师成长之路
1.工程师(1-3年):在别人的指导下完成开发
2.高级工程师(2-5年):独立完成开发,包括需求分析、方案设计、编码实现
1.示例
2.成长指导:表设计、缓存设计、业务流程设计、接口设计
3.技术专家(4-8年)
1.阶段描述
2.成长指导
4.初级架构师(5-10年)
阶段描述
2.成长指导
5.中级架构师(8年+)
阶段描述:
2.成长指导
6.高级架构师(10年+)
1.阶段描述
2.成长指导