导图社区 架构师必备
架构师必备架构师必备架构师必备架构师必备
编辑于2020-04-07 18:18:26架构师必备
java
多线程
多线程与并发相关涉及的整体技能框架
多线程需要学习哪些技能 线程池涉及的技术 线程锁需要掌握的技术 并发工具类需要掌握的技术 并发容器需要掌握的技术
Java线程池相关
为什么需要线程池 线程池的处理流程 线程池相关的核心参数 线程池使用的注意事项
Java 4大常用的线程锁
多线程的缘由 多线程并发面临的问题 4种Java线程锁(线程同步):synchronized、ReentrantLock等 Java线程锁总结
Synchronized
Synchronized介绍 Synchronized的使用 Synchronized的底层实现原理 Synchronized的锁升级顺序 偏向锁、轻量级锁、重量级锁的优劣势比较
容器
什么是同步容器 什么是并发容器 常见的7大并容器介绍:concurrenthashmap copyonwritearraylist等 ConcurrentHashMap的底层实现机制
concurrenthashmap
哈希表以及应用场景 ConcurrentHashMap与HashMap等的区别 JDK1.7版本的CurrentHashMap的实现原理 JDK1.8版本的CurrentHashMap的实现原理
CountDownLatch、Semaphore等4大并发工具类详解
CountDownLatch CyclicBarrier Semaphore Exchanger
AQS并发重要性非常高
AQS的介绍 AQS的数据模型 AQS的资源共享方式 AQS的锁获取与释放原理
ReentrantReadWriteLock
ReentrantReadWriteLock简介 ReentrantReadWriteLock特性 ReentrantReadWriteLock的主要成员和结构图 ReentrantReadWriteLock的核心实现 ReentrantReadWriteLock的锁获取与释放
乐观锁和悲观锁
Semaphore有什么用
架构
架构设计
如何做好架构设计
作为架构师要有的特点
技术好
至少代码容易读,容易扩展,重用性好,这不仅需要学习面向对象和设计模式,还要通过大量的编码实践,不单单是停在纸上谈兵的阶段
懂得业务
不了解业务,就不能设计出贴合业务的架构,而行业的相关知识也不是短时间能积累起来的。
良好的沟通能力
架构师需要沟通确认需求,需要让团队理解架构设计。
有架构思维
懂得用抽象、分治、复用、 迭代等思维降低软件复杂性
架构思维
描述:降低软件复杂性,有几种有效的方式:抽象、分治、复用和迭代,架构思维就是这几个的集合
1.抽象思维
架构是为了满足业务需求而存在,需要通常是一些文字性的描述、原型、UI设计图
先进行抽象,把需求变成计算机能识别的模型
例:抽象出各个用户、订单、内容等模型,划清各个角色的责任以及对象交互的方式,隐藏很多无关紧要的细节。
2.分治思维
对复杂的系统分而治之,分解为小的、简单的部分。
例:针对高并发场景,可以通过设计将流量分到不同的服务器,避免单台服务器过载。
3.复用思维
复用是提升开发效率的最简单有效的方法,通过对相同内容的抽象,让其能复用于不同的场景。
4.迭代思维
好的架构都是演进过来,很少有架构是一步到位,我们需要保证不影响业务正常进度的基础上,逐步迭代成最终合理的架构
什么是架构设计
描述:用最小的人力成本满足需求开发和需求变更,用最小的运行成本来保障软件的运行。
1.使用微服务架构,把复杂系统拆分成一系列小的服务,再拆成功能模块,让人员更好地分工协作
2.前后端分离,让程序员专注某个知识领域,降低开发难度
3.分层设计,隔离业务逻辑,减少需求变更带来的影响
为什么需要架构设计
存在原因
需求让技术变复杂。
小网站与大网站不是一个等级
人员让技术复杂
成员水平不等、擅长技术也不一样,有效协作是考验
技术本身复杂
使用的语言、框架、组件、数据库、大数据等技术,都有学习成本
软件稳定运行也复杂
软件上线后,充满了不确定性。
降低复杂度
降低开发成本
复杂系统拆分成多个相对简单的服务,使得普通程序员都可以完成,降低了人力成本。
帮助组织人员高效协作
通过抽象和拆分,让开发人员可以独立完成功能模块。
组织好各种技术
选择合适的编程语言、协议、框架、组件等,最高效地实现需求目标。
保障服务稳定运行
利用成熟的架构方案,例如负载均衡、限流、降级、熔断等,保障服务的高可用。
如何做好架构设计
分析需求
对产品的需求进行抽象,分析用例,了解各种用户角色和其使用的场景
选择相似的成熟架构设计方案
例如微服务架构、前后端分离,还要根据团队选择合适的开发语言和框架。
自顶向下层层细化
好的实践是自顶向下的,不过早陷入技术细节中,从整体到局部规划,设计好部署架构、分层和分模块、API设计、数据库设计等。
验证和优化架构设计方案
完整的架构设计方案,需要有多次的评审,充分收集各方面的反馈,反复修改后确定,另外,还要考虑架构预期能满足多长时间的业务增长,比如半年还是一年还是三年。
总体架构设计
架构本质
架构的本质就是对系统进行有序化地重构以致符合当前业务的发展,并可以快速扩展。
https://www.toutiao.com/a6675916632612667916/
如何实现无序到有序
基本的手段就是分和合,先把系统打散,然后重新组合。
分:合理定位
分的过程是把系统拆分为各个子系统/模块/组件,拆的时候,首先要解决每个组件的定位问题,然后才能划分彼此的边界,实现合理的拆分。 拆分的结果使开发人员能够做到业务聚焦、技能聚焦,实现开发敏捷
合:有机整合
合就是根据最终要求,把各个分离的组件有机整合在一起,相对来说,第一步的拆分更难。 合的结果是系统变得柔性,可以因需而变,实现业务敏捷。
单体架构
适用场景
适合小项目,用户数,业务处理还比较简单,一两台服务器能支撑起正常的业务处理。
优点
开发简单直接,集中式管理; 基本不会重复开发; 功能都在本地,没有分布式的管理开销和调用开销
痛点和破局
开发效率低、代码维护难、部署不灵活、稳定性不高、扩展性不够
破局见分布式架构拆分
面向服务架构SOA
它是粗粒度、松耦合服务架构,服务之间通过简单、精确定义接口进行通讯,不涉及底层编程接口和通讯模型。
服务架构本质
不仅仅在采用什么样的技术框架实现和塑造,更重要的是在于通过不停地在共创中反问、反思、反省等方式进行对业务的本质的不断追溯、抽象、综合归纳演绎,我们的每一个架构师都是服务化架构的接生婆,我们的使命是建立真正反映业务本质并驱动业务不断向前的架构。
服务架构的构成
子主题
特点、缺点
水平分层架构
微服务架构
网络架构
核心技术
高可用设计
无状态化设计
幂等设计
分布式锁设计
分布式事务设计
服务降级设计
服务限流设计
服务熔断设计
全链路压测设计
并发设计
关键系统
注册中心
配置中心
消息队列
分布式请求跟踪系统
服务管理系统
分布式服务调度系统
个性化推荐系统
搜索引擎设计
ABTest平台设计
数据存储
关系型数据库分库分表设计
关系型数据库性能优化
关系型数据库高可用设计
NoSQL分布式数据库设计
数据库数据无缝迁移
缓存数据一致性设计
开源框架
开发框架选择
微服务网关选型
微服务业务逻辑层、数据访问层开发框架选型
springboot
RPC
RPC框架设计
简介
单体应用时代只有内外网通信,并没有服务间通信的诉求,随着单机服务性能下降,进入多服务分布式的时代后Rpc 框架才应运而生。主要是解决服务间连接及数据交互,但除了通信和数据交互,为适应分布式架构/微服务架构的设计,通常还需要实现增值、增强的附加功能。
RPC通信方式设计
1. 多传输协议支持
跨网络、机房问题 跨语言问题 长连接还是短连接 传输安全 传输性能
HTTP协议
灵活便于管理,可以跨语言,但明文、性能很差
DUBBO协议
性能高、长连接,但跨语言做的不够好,大文件不能传输
RMI
性能差、短连接,但对于单次大数据量传输却比较好
2. 多数据压缩/序列化支持
跨语言/异构平台间交互、性能方面考虑。跟传输协议搭配
有DUBBO序列化、Hessian、Java原生、JSON等
如何找到服务(寻址)并且实现资源合理
描述:消费者如何知道提供者,并且知道当前是否存活,是设计PRC框架需要考虑的第二大问题
1. 多样的注册中心支持
不同的业务系统,对于服务间一致性要求并不同,这里有一个CAP权衡问题。
Zookeeper
支持强一致并能通过Wacher机制主动进行通知,但可用性并不能完全保证
2. 多算法负载均衡、路由和多维度流量控制
负载均衡目的是为了最优使用同一服务间的资源使用,具体到设计中,需要考虑机器情况、服务的负载情况等。 算法主要有随机、轮询、活路情况、一致性Hash等
3. 容错机制
考虑容错机制是系统完整性的一部分,failover、failfast、failback、failsafe 、forking、Broadcast …等,通常和负载均衡搭配。
让业务更方便的使用
支持普通配置的同时,支持集成到Spring等主流框架使用。配置的方式也有很多种,比如支持XML、注解、YAML、Properties、Json配置等。
可跟踪
可以进行依赖分析,数据的调用统计,并能图形、数据化将其显示出来
解决问题
服务调用链路或依赖关系 调用次数及时间,提供容量/机器预算基准数据 预警
实战项目
分布式架构拆分
为什么需要应用拆分
人员角度
百号人同时在一个工程上开发,一旦线上出问题,所有代码都需要回滚,从人员的角度,也基本忍受到了极致。
业务角度
用户、商品、交易、支付…等等,所有的代码早期都在一个工程里,代码已经严重影响到业务的效率,每个业务有各自的需求,需要给自己应用部署,各自开发需求。
架构的角度
从数据库端mysql数据库集中式架构的瓶颈问题,连接池数量限制,数据库的CPU已经到达了极限90%。数据库端也需要考虑垂直拆分了。
公司角度
借鉴的角度
应用拆分
工程代码垂直拆分
把整个工程代码按照业务为单元进行垂直拆分。
应用服务拆分
按照业务为单位,把所有调用相关的接口以业务为单元进行拆分。
拆分需求
组织结构变化
从最初的一个团队逐渐成长并拆分为几个团队,团队按照业务线不同进行划分
安全
这里所指的安全不是系统级别的安全,而是指代码或成果的安全,尤其是对于很多具有核心算法的系统,为了代码不被泄露,需要对相关系统进行模块化拆分,隔离核心功能,保护知识产权。
替换性
有些产品为了提供差异化的服务,需要产品具有可定制功能,根据用户的选择自由组合为一个完整的系统,比如一些模块,免费用户使用的功能与收费用户使用的功能肯定是不一样的,这就需要这些模块具有替换性,判断是免费用户还是收费用户使用不同的模块组装,这也需要对系统进行模块化拆分。
交付速度
单体程序最大的问题在于系统错综复杂,牵一发而动全身,也许一个小的改动就造成很多功能没办法正常工作,极大的降低了软件的交付速度,因为每次改动都需要大量的回归测试确保每个模块都能正确工作,因为我们不清楚改动会影响到什么,所以需要做大量重复工作,增加了测试成本。这时候就需要对系统进行拆分,理清各个功能间的关系并解耦。
技术需求
单体程序由于技术栈固定,尤其的是比较庞大的系统,不能很方便的进行技术升级,或者说对引入新技术或框架等处于封闭状态;每种语言都有自己的特点,单体程序没有办法享受到其它语言带来的便利;对应到团队中,团队技术相对比较单一。
相比于基于业务的垂直拆分,基于技术的横向拆分也很重要,使用数据访问层可以很好的隐藏对数据库的直接访问、减少数据库连接数、增加数据使用效率等;横向拆分可以极大的提高各个层级模块的重用性。
业务需求
由于业务上的某些特殊要求,比如对某个功能或模块的高可用性、高性能、可伸缩性等的要求,虽然也可以将单体整体部署到分布式环境中实现高可用、高性能等,但是从系统维护的角度来考虑,每次改动都要重新部署所有节点,显然会增加很多潜在的风险和不确定定性因素,所以有时候不得不选择将那些有特殊要求的功能从系统中抽取出来,独立部署和扩展。
如何拆分
拆分原则
单一职责 服务粒度适中 考虑团队结构 以业务模型切入 演进式拆分 避免环形依赖和双向依赖
拆分实战
设计module骨架
root web app
网关:api-gateway
webapp
微服务:pom module、 user-service、order-service,...
业务:biz-user、biz-order
框架:framework
工具类:tools
拆分技术commons
第一步:先对整个工程按业务和功能进行了maven多module的拆分。
首先是分离出技术上的commons,感觉这应该是最好拆分的了,把相关的类重构到一个包里,在分离出一个module即可。
拆分entity
子主题
很多在业务代码上都会共享entity类,通常没法也没法把entity类分门别类,最简单就是把所有的entity类放到一个module,谁需要谁依赖的原则。entity类也没有太多jar依赖和业务依赖,也不会形成污染源。
公共业务
同commons和entity方法,不在复述,也被各个业务依赖,这种业务大部分是过渡性的,在未来迭代演进时可以通过其他方式抽象集成。
拆分entity
很多在业务代码上都会共享entity类,通常没法也没法把entity类分门别类,最简单就是把所有的entity类放到一个module,谁需要谁依赖的原则。entity类也没有太多jar依赖和业务依赖,也不会形成污染源。
拆分微服务
有了以上的拆分基础,可以在合适的业务迭代将各个微服务module迁移到不同的代码仓库,完成进一步隔离管理。
拆分业务代码
拆分业务是最痛苦的事情了,这个要看原来的代码整洁度和互相依赖程度。有两种方式
1. 新建业务module,加入基础module的pom依赖,再从源module复制和该业务module相关的代码(包括单元测试代码)过来,解决编译错误和单元测试错误,完成本业务拆分。
2. 从源module复制一个新业务module,保持代码一致,先删除和本义务无关的代码(包括单元测试代码),再删除无关的pom依赖,解决编译错误和单元测试错误,完成本业务拆分。
应用拆分总结
1.明确拆分原则和拆分需求。 2.梳理出业务模块和之间的依赖关联关系。 3.按照业务为单位,拆分实体、以及应用工程单独部署。 4.按照业务为单位拆分应用服务,避免环形依赖和双向依赖。 5.抽离出公用的接口、实体,以及服务单独部署为公用服务。
微服务架构框架
springboot+dubbo
springCloud
系统服务治理设计
技术成长与技术人生
新技术探索
数据库
分库分表
mycat
tddl
描述
数据库设计
描述:数据库选型、范式设计、ACID、事务的隔离
性能优化
索引原理及适用
大表查询优化
缓存
Redis
描述:Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库
优点: 1.速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1) 2.支持丰富数据类型,支持string,list,set,sorted set,hash 3.支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行 4.丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除
持久化
RDB-Redis DataBase
在不同的时间点,将redis存储的数据生成快照并存储到磁盘等介质上;
AOF-Append Only File
将redis执行过的所有写指令记录下来,在下次redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。
适用场景
会话缓存-Session Cache
用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化
队列
提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用
全页缓存-FPC
Magento提供一个插件来使用Redis作为全页缓存后端
排行榜
Redis在内存中对数字进行递增或递减的操作实现的非常好 集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构
高可用策略
高可用
当一台服务器停止服务后,对于业务及用户毫无影响。
主备方式
通常是一台主机、一台或多台备机,在正常情况下主机对外提供服务,并把数据同步到备机,当主机宕机后,备机立刻开始服务。 Redis HA中使用比较多的是keepalived,它使主机备机对外提供同一个虚拟IP,客户端通过虚拟IP进行数据操作,正常期间主机一直对外提供服务,宕机后VIP自动漂移到备机上。
主从方式
采取一主多从的办法,主从之间进行数据同步。 当Master宕机后,通过选举算法(Paxos、Raft)从slave中选举出新Master继续对外提供服务,主机恢复后以slave的身份重新加入。 主从另一个目的是进行读写分离,这是当单机读写压力过高的一种通用型解决方案。 其主机的角色只提供写操作或少量的读,把多余读请求通过负载均衡算法分流到单个或多个slave服务器上。
方案选择
主备(keepalived)方案配置简单、人力成本小,在数据量少、压力小的情况下推荐使用。 如果数据量比较大,不希望过多浪费机器,还希望在宕机后,做一些自定义的措施,比如报警、记日志、数据迁移等操作,推荐使用主从方式,因为和主从搭配的一般还有个管理监控中心。
消息队列
RabbitMQ
Kafka
分布式
Zookeeper
解决分布式应用中经常遇到的一些数据管理问题
统一命名服务 状态同步服务 集群管理 分布式应用配置项的管理等
原理和架构
Zookeeper的角色
领导者
负责进行投票的发起和决议,更新系统状态。
学习者
包括跟随者(follower)和观察者(observer),follower用于接受客户端请求并向客户端返回结果,在选主过程中参与投票。
Observer
可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度
客户端
分布式系统
分布式基础
CAP
分布式系统技术就是用来解决集中式架构的性能瓶颈问题,来适应快速发展的业务规模,一般来说,分布式系统是建立在网络之上的硬件或者软件系统,彼此之间通过消息等方式进行通信和协调。 分布式系统的核心是可扩展性,通过对服务、存储的扩展,来提高系统的处理能力,通过对多台服务器协同工作,来完成单台服务器无法处理的任务,尤其是高并发或者大数据量的任务。
解决问题
单点故障
无状态
CAP
一致性
C
所有的节点同时看到相同的数据。 被称为原子对象
可用性
A
任何时候,读写都是成功的,即服务一直可用
分区容忍性
P
当部分节点出现消息丢失或者分区故障的时候,分布式系统仍然能够继续运行
应用
架构设计中,不要把精力浪费在如何设计能满足三者的完美分布式系统上,而要合理进行取舍。
例
nginx
网关
设计模式
软件设计原则
单一职责原则 开闭原则 接口隔离原则 合成复用原则
结构型模式
动态代理
适配器
组合
装饰
外观
行为模式
策略
观察者
中介者
创建型模式
工厂
抽象工厂
单例
JVM
数据结构和算法
数据结构
数组
链表
堆与栈
哈希表
队列和栈
字符串操作
HASH表
hash函数,冲突解决方法
排序
归并
快排
是否稳定
二叉树
B+树
红黑树
哈夫曼树
KMP算法
10个100M日志文件,如何排序一个文件
思路:可用10个线程,读取文件,读取每个文件第一行,将其10条记录比较,最小的放到新文件中
算法分析计算
时间复杂度
空间复杂度
算法思想
递推
递归
穷举
贪心
迭代
高级算法
贪婪
回溯
剪枝
动态规划
大数据算法
Hash分桶
统计
容器
docker
k8s
实战项目
问题一般是从介绍的项目背景来问 1.介绍项目背景 2.框架、数据库 3.技术,如分布式日志追踪 4.项目遇到问题
控制在1分钟里面,讲出项目基本情况,比如项目名称,背景,给哪个客户做,完成了基本的事情,做了多久,项目规模多大,用到哪些技术,数据库用什么,然后酌情简单说一下模块。重点突出背景,技术,数据库和其他和技术有关的信息。
要主动说出你做了哪些事情,这部分的描述一定需要和你的技术背景一致。
描述你在项目里的角色
可以描述用到的技术细节,特别是你用到的技术细节,这部分尤其要注意,你说出口的,一定要知道,因为面试官后面就根据这个问的。 你如果做了5个模块,宁可只说你能熟练说上口的2个。
这部分你风险自己承担,如果可以,不露声色说出一些热门的要素,比如Linux,大数据,大访问压力等。但一旦你说了,面试官就会直接问细节。
汇桔网
知识产权交易平台
商标、专利、版权等知识产权创造与保护,以及知识产权的交易等
数字版权
项目介绍
数字版权项目,担任架构师与高级工程师主要参于完成了架构设计 1.从分析需求看,了解用户角色,像会员体系、第三方认证体系、运营体系等, 2.使用场景,如门户、中台、合同档案、工单、作件 3.选择成熟架构设计方案,结合公司情况,选用前后端分离 4.自顶向下的细化工作,如分层,分模块、API设计、数据库设计等 5.验证和优化架构设计方案,如满足半年时间的业务增长 用到了开源springboot+dubbo+rabbitMQ+mybatis+redis+es+oss+mongDB+爬虫
业务架构
技术架构
拓扑图
应用业务解决方案
1.数据收集
描述:作品监测收集知名网站数据
收集数据考虑到实时性不高,可能采用异步方案
1.定时任务触发爬虫爬取网站信息。 2.信息推送到MQ存储 3.信息服务下载图片并计算特征值 4.存入阿里云faiss-search
2.特征计算
3.实时分析
子主题
4.日志服务
5.公证计算
6.存证计算
应用技术解决方案
百度配置中心
描述:分布式环境下多台服务实例的配置统一管理问题
设计理念
简单易用、体验良好 支持配置、配置发布、更新统一化 配置更新自动化(用户在平台更新配置,使用该配置的系统会自动发现该情况,并应用新配置)
原理
Disconf通过disconf-web管理配置信息,然后将配置的key在Zookeeper上建立节点,disconf-client启动后拉取自身需要的配置信息并监听Zookeeper的节点。在web上更新配置信息会触发zk节点状态的变动,client可以实时感知到变化,然后从web上拉取最新配置信息。
架构
讲解知识
基于注解
在需要进行配置的类通过DisconfFile注解指名配置从哪个文件获取,在get方法通过DisconfFileItem注解的name属性指定文件中的key,associateField指类的属性,即当前值设置到当前类的哪个属性中。 @DisconfFile(filename = "redis.properties") @DisconfFileItem(name = "redis.host", associateField = "host")
client端
系统启动时Bean初始化前 1.扫描配置文件类和配置项 2.下载配置数据 3.watch监控配置数据变化 4.注册到仓库中 系统启动时Bean初始化后 1.配置仓库容器模块:设置注册回调函数 2.配置仓库容器模块:注入Bean类 系统正常运行时请求配置数据 1.配置仓库容器模块:AOP拦截请求,返回仓库配置数据 系统正常运行时配置更新 1.配置仓库容器模块:接收远程推送配置数据,并注入到仓库和配置类里 2.配置仓库容器模块:调用回调函数进行控制
web端
架构
1. web主要用于管理配置项,当新建配置项后,会保存到DB的config及config-history表,并邮件通知app表对应的邮件地址。 2. 对更新的配置项,会更新config表并新增记录到config-history表,邮件通知,同时添加zk节点(/disconf/app_version_env/file(或item)/配置项),当client端更新配置后,会在此节点下写入client标识,所以就有了web端的“实例列表”。 3. client启动后会从web拉取最新的配置文件信息,并监听相应的zk节点,当有数据变化时,zk会通知client,然后client重新从web拉取最新数据。 4. web的另外一个功能是配置项检查,每30分钟将DB config表中配置值与zk相比,发现不一致会邮件通知。
app: app表,配置以app为核心。 config: 配置表。 config_history: 配置记录表,每更新每新增。 env: 环境表。 role: 角色表,用户有哪些角色。 role_resource: 角色权限对应的功能表。 user: 用户表,登录使用。
优势
1.数据持久化在mysql 2.推拉模型基于ZK,实时 3.容灾:多级 4.配置数据模型:文件和KV
接口鉴权
子主题
服务限流设计
子主题
redis缓存设计、性能、应用
子主题
服务
注意:别太多介绍技术细节
JVM
配置
调优
监控
子主题
广告项目
子主题