零、学习的过程
一、概念
1、系统
- 关联:发动机、地盘和车架组合才能成为汽车
- 规则:发动机产生动力,经过变速器和传动轴到车轮,有规则运作而不是各自为政
- 能力:发动机、变速器和车轮每单独一个都不能走,组合才能产生行走的能力
2、子系统:是不同维度的系统,比如微信有聊天、登录、支付、朋友圈等子系统,朋友圈又分评论、动态、点赞等子系统
3、模块:系统的组成部分,系统的逻辑区分,比如登录注册模块、个人信息模块
4、组件:系统的组成部分,系统的物理区分,比如nginx、mysql、web服务器的层面
5、框架:组件的一种规范,spring框架
6、架构:软件的一种结构,比如 ssh架构,它是子系统、模块、组件的一个集合体
二、架构产生的起因
1、系统规模大,耦合严重,开发效率低,维护扩展困难
三、目的
1、不一定都要架构设计,关键看业务
2、架构设计要适当,而不是约大约好,且不能一味模仿,不然工期延误且难落地
3、目的是解决软件系统复杂度带来的问题
四、解决复杂度
1、高性能:简单系统更容易做高性能,单任务扩展做到高性能
- 单机复杂度:操作系统和硬件的限制,出现了多进程和多线程
- 集群复杂度:任务分配(网络设备、负载均衡、连接方式、分配算法)
2、高可用:基本都是通过“冗余”
- 计算高可用:不同机器都能一样处理业务
- 存储高可用:如何减少或者规避数据不一致的影响
- 状态决策:独裁式、协商式、民主式
3、可扩展
- 预测变化:适当预测,但不能每个点都考虑
- 应对变化:稳定层与变化层、抽象层与实现层
- 扩展标准:可复用和松耦合
4、低成本:硬件的成本,用新技术弥补
5、安全
- 功能安全:防小偷,XSS攻击、CSRF攻击、SQL注入、windows漏洞、密码破解
- 架构安全:防强盗,防火墙
6、规模:功能和数据导致复杂
五、设计3个原则
1、合适原则:人力、积累和业务要合适
2、简单原则:过多组件会导致联系多,出问题难查找
3、演化原则:架构是不断更新迭代的
六、设计流程
七、数据层面
1、读写分离:主从集群,一主一/多从,主负责写,从负责读,主复制数据到从
- 主从复制延迟:①写后的读发给主 ②读从失败再读主 ③关键业务读写都主
- 分配机制:①数据访问层/中间层封装(TDDL) ②中间件技术(mysql proxy、Atlas)
2、分库分表
- 业务分库:如电商系统的数据分用户、商品、订单(join问题、事务问题,成本问题)
- 单表拆分:
- 垂直分表:拆分列,拆分不常用且较大数据的列
- 水平分表:拆分行
- 路由:范围路由、Hash路由、配置路由
- join:业务代码或中间件合并
- count:①分表count后再相加 ②记录数表
- order by:业务代码或中间件排序
3、NoSQL
- K-V存储(存储数据结构):redis,事务只能保证IC,不能保证AD
- string、hash、list、set、sorted set、bitmap、hyperloglog,
- 文档:MongoDB,不支持事务,多用存储一个json
- 列式:HBase,多用于某一列海量数据统计分析,但更新多个列会比较慢
- 全文搜索:Elasticsearch,是一种倒排/反向索引(索引的是单词和文档,关系数据库索引的是键和行)
4、缓存
- 缓存穿透:就是缓存没发挥效果,可能是数据不存在也可能是缓存生成时较久导致访问时失效了
- 缓存雪崩:就是在缓存过期后重新生成时耗时,此时又有多请求,压力导致数据库宕机,连锁反应致使系统崩溃
- 更新锁:更新缓存加锁
- 后台更新:用后台线程更新缓存而不是业务线程,缓存设置永久,但后台线程定时更新
3. 缓存热点
八、服务器层面
1、服务器性能:管理连接和处理请求
- PPC:用新进程处理新连接
- TPC:共享进程,线程处理
- Reactor:反应堆,建立进程池,并用IO多路复用(select/epoll/kqueue),如Netty、Memcache、Nginx
- 单Reactor 多线程
- 多Reactor 多进程/线程
2、负载均衡
- 分类:DNS负载均衡、硬件负载均衡、软件负载均衡:Nginx,LVS
- 算法:轮询、加权轮询、负载最低优先(用连接池的时候不适合)、性能最优、Hash类(同ip访问同服务器)
九、存储架构
1、思考:数据如何复制、节点职责、处理复制延迟、处理复制中断
2、双机架构
- 主备复制:优点是对用户透明、只复制数据不用判断状态,缺点是只做备份浪费硬件、故障后需要人工处理
- 主从复制:主读写从读,优点是主坏从可读、充分发挥了硬件的性能,缺点是客户端需判断读写来选择主从、复制延迟、故障需人工
- 双机切换:主从/主备切换,需要进行状态判断、切换决策(时机、策略、自动程度)、数据冲突解决
- 互连式:主备建立状态传递的渠道
- 中介式:主备间加入中介(Zookeeper和keepalived)
- 模拟式:备模拟请求主来判断主的状态
4. 主主复制:适用于临时、可丢失、可覆盖的数据,比如session或日志,类似用户id或者商品库存复制后可能就出现问题了
3、多机架构
- 数据集群
- 数据集中集群:一主多备/多从
- 数据分散集群:多机集群,每台存储一部分数据
2.数据分区
十、计算高可用
1、任务调度
- 哪些可以执行任务:①所有机器 ②只有主机
- 如何重新执行任务:①失败不处理 ②任务管理器
2、常见架构
- 主备:①冷备:备机系统没启动,需要时再启动切换请求 ②温备:备机系统已启动,需要时直接切换
- 主从:主从执行不同的任务
- 集群:①对称集群(负载均衡集群):不同服务器执行相同任务 ②非对称集群:不同服务器执行不同任务,如Master-Slaver
3、异地多活
- 模式:同城异区、跨城异地、跨过异地
- 设计技巧:
- 保证核心业务异地多活
- 核心数据最终一致性
- 多种手段同步(消息队列、二次读取、存储系统同步、回源读取、重生成数据)
- 只保证绝大部分用户的异地多活(挂公告、事后补偿、补充体验)
3. 异地多活设计思路
- 业务分级(访问量、收入)
- 数据分类(数据量、唯一性、实时性、可丢失性、可恢复性)
- 数据同步(存储系统、消息队列、重复生成)
- 异常处理(多通道同步、同步和访问结合、日志记录、用户补偿)
4、接口级故障
- 原因:程序Bug导致死循环、数据库查询慢、程序逻辑导致内存占用高、外部攻击
- 解决
- 降级:应付内部异常
- 熔断:应付依赖项目异常
- 限流:应付用户访问压力(请求限流和资源限流)
- 排队:由排队模块和调度模块组成
十一、架构可扩展
1、基本思想:拆
- 面向流程拆:如展示层、业务层、数据层、存储层
- 面向服务拆:如注册、登录、信息管理、安全设置等服务
- 面向功能拆:如登录服务拆成手机号登录、账号密码登录、邮箱登录