从0开始学架构 -- 整理

从0开始学架构


什么是架构

  • 系统与子系统
    • 系统: 多个个体组成的一个群体
    • 子系统: 与系统概念一致,但是隶属于更大的系统, 如朋友圈系统是微信系统的子系统
  • 模块与组件
    • 模块:业务拆分来说,具有登入模块,筛选模块
    • 组件:物理拆分来说,具有MySQL,Nginx
  • 框架与架构
    • 框架: 业界实现某种功能的标准,或者实现标准的产品
    • 架构: 完成标准的方案,包括模块关系,功能运作规则

架构目的

  • 架构设计的主要目的是为了解决软件系统复杂度带来的问题
  • 案例: 学生管理系统
    • 性能: 一个学校的学生大约1 ~ 2万人,学生管理系统的访问频率并不高,平均每天单个学生的访问次数平均不到1次,因此性能这部分并不复杂,存储用MySQL完全能够胜任,缓存都可以不用,Web服务器用Nginx绰绰有余。
    • 扩展性: 学生管理系统的功能比较稳定,可扩展的空间并不大,因此可扩展性也不复杂。
    • 高可用: 宕机对于学生管理影响不大,只要及时修复就好了,难点在数据恢复,所以要MySQL跨机房同步方案,以防丢失数据无法恢复。
    • 安全性: 并无隐私,金融涉及,只要保证三点足够: Nginx提供ACL控制、用户账号密码管理、数据库访问权限控制。
    • 成本: 架构简单,成本不高,大学足以支持。

复杂源

  • 高性能
    • 提高性能,除了物理加机器外,还需要考虑业务逻辑优化,加集群需要额外考虑集群稳定性,负载均衡,网络等问题,并且由于网络损耗,原来1台 5k的qps, 加到两台可能只有 8k (保守打8折)
  • 高可用
    • 指在出现异常时,系统仍可以使用
    • 高可用本质是冗余,但是冗余导致的复杂性包括多机器间的交互和数据同步时候的不一致性。其中多种策略的衡量
      • 独裁式: 有一个决策者决定主从。 决策者出现问题,系统崩溃。
      • 协商式: 所有设备参与协商讨论出主从。 连接问题导致各自为主。
      • 民主式: 所有人进行投票选出主从。 可能脑裂,票数大于一半的为主,解决脑裂,但是降低可用性。
  • 可扩展
    • ”唯一不变的就是变化“ -> 提前做好系统预测,有利于未来的扩展。
    • 扩展思考:
      • 思考于两年内可能的变化。
      • 拆分 稳定层 和 变化层
      • 拆分 抽象层 和 实现层
      • 1写2抄3重构原则: 第一次直接写确定业务,第二次按照第一次思路继续写, 第三次改变思考重构。
  • 低成本,安全,规模
    • 考虑降低成本同时保证系统正常,需要有创造力,仔细思考问题
    • 防火墙是一半的防御手段,但是成本高,且在不被攻击时形同虚设。 所以大部分还是依靠运营商了。
    • 在数据规模上由量变引起质变时,需要考虑系统的架构升级,数据库分库分表,查询性能等。

架构的过程

  • 最初设计
    • 简单原则 + 合适原则 => 演化原则
      • 一开始只需要思考简单的架构,以及符合当前需求即可,当量上去了,就开始考虑架构的演化了。 毕竟十万级的架构和千万级的架构绝对不同
    • 识别复杂度
      • 不同系统复杂的点不同,比如金融考虑安全性,微博考虑内容审核法律安全。 识别出系统的关键业务
        • 系统排出:查看当天流量,考虑峰值为平均流量的3X,预留未来业务扩张可能导致流量上升4x,考虑当前架构时候合适。
    • 设计方案
      • 3~5个备选方案:只有1个容易致盲,太多浪费精力。
      • 方案选择按优先级: 合适->简单->符合未来扩展
      • 方案选择后,需要细化细节,如果使用Kafka时候集群配几个,分区怎么做等等 [有可能发现方案在细节上难以实现,则需要果断放弃]
    • 主从问题
      • 复制延迟 - 主写入但分未同步,查询数据会有问题,对于敏感业务需要多查一次主库保证数据正确。
      • 分配机制 - 读写分离,可能需要额外的程序支持,自研或者中间件
    • 分库分表
      • 分库
        • 业务查询: 不同库的数据需要联合查询
        • 事务问题: 不同库需要保持原子性
        • 成本问题: 新业务可能不需要这样的操作,因为量级没那么快达到。
      • 分表
        • 垂直切分
        • 水平切分
        • 路由问题: 切分后,数据该如何查询 {主键HASH / 路由表配置}
    • NoSQL
      • 代表
        • Redis: K-V存储结构,支持多种操作方式
        • MongoDB: 文档型,支持复杂数据结构,不支持事务
        • HBase: 列式存储,单列操作快,因为在连续的空间内;场景:离线数据统计
        • ES: 全文搜索,倒排索引,对全文搜索支持良好。 倒排:文章区分出单词,以单词搜时,用单词关联到文章。
      • 问题
        • 缓存
          • 缓存穿透: 缓存中没有数据导致需要去数据库查一次
            • 解决 缓存中没有值情况: 如果查询存储系统的数据没有找到,则直接设置一个默认值
            • 解决 缓存大对象(分页数据)慢导致查询DB: 只能按情况分类了,如果是爬虫就禁ip
          • 缓存雪崩: 大批量失效的缓存数据,导致都去数据库查询
            • 缓存更新加锁: 本地锁|分布式锁
            • 后台更新:后台线程小间隔(1s/100ms)去查询并更新缓存 || 业务线程发现缓存失效,发送消息给后台线程去更新,发现存在就不更新了。 [可以实现缓存预热]
          • 缓存热点
            • 场景:微博里明星的消息,访问量巨大
            • 解决:将信息缓存多分到不同的缓存服务器中,key中设置编号,过期时间离散。 减少单台缓存服务器的压力。
  • 服务器设置
    • 高性能优化要从:服务器连接管理,IO模型,进程模型等考虑
    • PPC[Process Per Connection] : 父进程接受连接 -> 父进程“fork”子进程 -> 子进程处理连接的读写请求 -> 子进程关闭连接
      • 缺点:并发数有限,子进程创建耗资源
    • prefork: PPC 优化,提前创建子线程,主线程fork时直接用就好,避免创建资源
      • 缺点:如PPC一样,惊群:所有进程都会唤醒,但只有一个可以用[Linux 2.6版本后内核已经解决了accept惊群问题]
    • TPC[Thread Per Connection]: 父进程接受连接 -> 父进程创建子线程 -> 子线程处理连接的读写请求 -> 子线程关闭连接
      • 优点: 线程创建消耗的资源比进程小
      • 缺点: 1.有死锁可能 2.某个线程异常退出可能导致进程退出,所以大部分还是用PPC
    • prethread:优化TPC,提前创建出Thread资源
      • 优点: 并发量提高
      • 缺点: 如TPC, 为了防止的缺点2,服务器会创建多个进程,进程下面多个线程以防止某个线程异常退出可能导致进程退出
    • reactor 模型选择
      • 单Reactor单进程/线程: acceptor接收 -> handler处理请求
      • 单Reactor多线程: acceptor接收 -> handler处理请求 -> processor 处理具体业务 [创建子线程]
      • 多Reactor多进程/线程: 主线程acceptor接收连接 -> 通知子reactor去监听事件并处理响应
    • 服务器负载均衡
      • 方式
        • DNS: 基于地域来划分请求,以减小流量
        • 硬件:地域下,区分不同集群可用,但价格贵 F5,A10; 可扩展选Haproxy/LVS
        • 软件:集群内部,多个服务之间的负载使用 => NGINX,LVS
      • 算法: 加权 | HASH(ip/sessionId) | 最优分配(感知服务器状态,如cpu,连接数等,复杂度高)
    • CAP原理
      • C: 一致性 [Consistency]
        • 对某个指定的客户端来说,读操作保证能够返回最新的写操作结果。
      • A:可用性 [Availability]
        • 非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)。
      • P: 分区容忍性 [Partition Tolerance]
        • 当出现网络分区后,系统能够继续“履行职责”。
      • 虽然CAP原则只能 CP 或者 AP,但是这只是对于与场景来说的,并不是针对系统级别的设计,如用户账户信息用CP,用户其他数据可以考虑AP。
      • CP和AP二选一只有在分区发生时,如果不存在分区的情况,可以考虑CA都要。 在分区发生后,要考虑补数据的问题。
      • ACID:数据库事务的四大特性,原子性,数据完整性,隔离性,持久性
      • BASE:基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency);
        • 保证核心的情况下,允许系统存在中间状态,但是要保证最终的一致性
    • 设计思考
      • 使用 FMEA(Failure mode and effects analysis,故障模式与影响分析)方法: 分析异常情况,并且其产生的影响,来思考优化架构设计
  • 高可用存储架构
    • 存储高可用
      • 双机
        • 主备: 备机只是备份,如果主机故障,需要手动将备机切换成主机
        • 主从: 从节点从主节点同步数据,如果主从之间相互无法感知导致会出现双主问题
        • 模拟: 从/备机模拟客户端,所有请求都从其流入主机,让它可以感受到请求是否成功,从而决定数据是否更改
        • 双主: 双主皆可读写,但是数据要相互同步,这样需要保证A插入1,B不能插入1,否则同步有问题
      • 集群
        • 数据集中型
          • 一主多从/备
            • 单要考虑数据同步问题,主机要将数据同步给多个从,压力变大。
            • 主机宕机后,如果选举新的主节点
        • 数据分散性
          • 每个节点存储一部分数据,由一个总节点来汇总并返回给客户端
            • 数据分配要均衡
            • 节点故障,要重新选举,并且将故障节点的数据同步到其他节点
            • 扩充服务器后,要将数据重新分配,保证均衡
        • 数据分区
          • 为了防止数据中心被破坏(地震,火宅,断电),需要考虑为数据异地备份
            • 集中式: 将所有数据备份到一个数据中心。
            • 互备式: 将A的数据备到B,B的备到C,C的备到A,会影响其他区的数据和服务
            • 独立式: 每个区域的数据都单独备份到其他区。

      不用远距离集群来做备份是因为: 远距离耗时增加,还需要保证备份成功的复杂度。

    • 计算高可用 (本质是通过冗余来规避部分故障的风险)
      • 主备
        • 主负责处理所有计算任务,主机故障,需要手动切换成备机,不然系统不可用
          • 备机分 冷备和温备,冷备是备机的业务系统没有启动(不占资源,但启动有风险), 温备是业务系统启用了,但是没有对外服务,需手动处理。
        • 适合与内部管理系统、后台管理系统这类使用人数不多、使用频率不高的业务
      • 主从
        • 主机处理部分任务,从机处理部分任务,主机故障了,也不会把任务分给从机,需要手动切换
      • 集群
        • 对称集群
          • 集群内机器不分主从,均处理部分任务
          • 难点:任务分配,存活检查
        • 非对称集群
          • 根据机器的角色来分配任务,如主从,主负责写,从负责读。
          • 难点:任务分配策略,选举策略
    • 业务高可用的保障:异地多活架构: 根据业务的规模决定是否采用
      • 同城异区
        • 同城不同区,可以防止某个机房受灾导致系统不可用
        • 相比异地,复杂度降低,两个机房使用一个高速通道相连,可以保证一致性,就当成本地机房一样去设计
      • 跨城异地
        • 距离很远的地方配置不同机房
        • 难以保证一致性,因为距离远,可能发生的变故多
        • 场景
          • 博客/新闻/微博类网站,数据暂时不一致也没事
      • 跨国异地
        • 高延时,难一致
        • 场景
          • 为不同地区用户提供服务 (亚马逊中国,亚马逊美国)
          • 只读类业务做多活 (谷歌搜索)
      • 设计技巧
        • 保证核心业务的异地多活
          • 如 登入/注册, 日活多的网站优先考虑登入就好
        • 保证核心数据最终一致性
          • 尽量减少异地多活机房的距离,搭建高速网络
          • 尽量减少数据同步,只同步核心业务相关的数据
          • 保证最终一致性,不保证实时一致性
            • 几分钟不一致,对用户影响不大,因为他的服务器也不会换来换去
        • 采用多种手段同步数据
          • 消息队列方式
          • 二次读取方式
            • A中心没有,再去B取一次
          • 回源读取方式
            • 判断用户的session服务器,取特定中心获取数据
          • 存储系统同步方式
            • 更新不频繁的可以直接使用数据库等存储系统的自带同步方式
          • 重新生成数据方式
            • 回源 | 二次读取失败,则返回失败,让用户在登入一次
        • 只保证绝大部分用户的异地多活
          • 转账业务,难以保证异地一致性,可以牺牲用户体验性来实现,如用户提交申请转账,可能一个小时|一天后才成功,成功给用户发个短信。
            • 过程中,转账申请请求保存下来,然后异步去申请转账,失败会重试。

        异地多活设计的理念可以总结为一句话:采用多种手段,保证绝大部分用户的核心业务异地多活!

      • 设计步骤
        • 业务分级(轻重) -> 数据分类(重要性) -> 数据同步(系统间同步) -> 异常处理(出现异常怎么处理)
    • 接口高可用
      • 降级: 自身问题,马上返回结果
      • 熔断: 外部问题,马上返回结果
      • 限流: 每分钟最大请求量。 [算法:时间窗口,滑动窗口,令牌桶]

架构设计

  • 架构模式

    • 面向流程:
      • 分层架构: B/S, C/S, MVC三层。 只能一层层走下去
    • 面向服务:
      • SOA: 服务+EBS+松耦合, 由于EBS需要关心所有系统的协议并做转化,使用较少。
      • 微服务:比SOA的服务更细,不需要EBS总线管理,但是由于服务更细,对维护和部署的成本也更大。
        • 服务粒度: 基数(3)人维护(1)服务, 保证有交流
        • 拆分方式: 根据业务|可靠性|性能去考虑拆分
        • 基础设施:需要有配套的基础设置,如监测,路由,发现等[spring cloud]
    • 面向功能:
      • 微内核架构:OSGi {插件式[Bundle],可拔插的实现方式}
  • 架构的远见

    • 三种架构师
      • 潮流派:有新的就用,可能当小白鼠,白费成本
      • 保守派:能用就行,有可能新技术可以提高业务增长,却不去做
      • 跟风派:别人用的不错,我们也用,如果没有风可以跟,那么可能当无头苍蝇
    • 影响一个企业业务的发展主要有3个因素:市场、技术、管理
    • 技术创新推动新业务发展:产品类业务,如uc随着网络3G 4G而提供更高效的速度
    • 业务发展推动技术的发展:服务类业务,如微信用户规模变大,而引发的技术更迭
    • 每一个阶段所面对的场景不一样,作为架构师要预测未来的业务发展,判断合适的技术方案
    • 产品不同时期复杂性不同,所以关注点也不同。 阶段可以分为: 初创 -> 发展 -> 竞争 -> 成熟
  • 架构通用图
    system

    • 存储层
      • SQL: MySQL,oracle
      • NoSQL: Redis,Memcache
      • 小文件存储: HBase、Hadoop、Hypertable、FastDFS,淘宝的TFS、京东JFS、Facebook的Haystack
      • 大文件存储: Hadoop系列
    • 开发层
      • 开发框架
      • Web服务器
      • 容器
    • 服务层
      • 配置中心
      • 服务中心
      • 消息队列
    • 网络层
      • 负载均衡: DNS, Nginx, LVS, F5
      • CND
      • 多机房: 同城多机房 | 跨城多机房 | 跨国多机房
      • 多中心
    • 用户层
      • 用户管理: SSO |
      • 消息推送
      • 存储云/图片云
    • 业务层
      • 化整为零、分而治之
    • 平台技术
      • 运维平台: 配置、部署、监控、应急
        • 运维平台的核心设计要素是“四化”:标准化、平台化、自动化、可视化
      • 测试平台: 单元测试、集成测试、接口测试、性能测试等
        • 任务管理 获取用例(用例管理), 分配用例到资源管理, 把数据存储到 数据管理
      • 数据平台
        • 数据管理:数据采集 | 数据存储 | 数据访问 | 数据安全
        • 数据分析:数据统计 | 数据挖掘 | 机器学习、深度学习
        • 数据应用:包括在线业务,也包括离线业务。例如,推荐、广告等属于在线应用,报表、欺诈检测、异常检测等属于离线应用。
      • 管理平台
        • 身份认证
        • 权限控制
  • 架构心法

    • 有的放矢

      架构师的首要任务是从一大堆纷繁复杂的问题中识别出真正要通过架构重构来解决的问题,集中力量快速解决,而不是想着通过架构重构来解决所有的问题

      • 难点
        • 业务上线了,无法等重构好了再上
        • 关联方众多,牵一发动全身
        • 旧架构的基础上做重构,选择性少
      • 常见问题:
        • 解决不合理的耦合
        • 解决全局单点的可用性问题
        • 解决大系统带来的开发效率问题
    • 合纵连横
      • 合纵: 在跟非技术人员沟通时,将专业术语转换成共同语言
      • 连横:重构需要其他团队配合时需要思考 其他团队的回复 (“这对我有什么好处”和“这部分我这边现在不急”)- 即换位思考
    • 运筹帷幄
      • 优先级排序
      • 问题分类
      • 先易后难
      • 循序渐进: 评估耗时,并做计划,太大了就再拆分任务

架构的话题

  • 开源项目
    • 如何选择
      • 聚焦是否满足业务
      • 聚焦是否成熟 [社区活跃,成功案例等]
    • 如何使用
      • 深入研究,仔细测试
      • 小心应用,灰度发布
      • 做好应急,以防万一
    • 如何二次开发
      • 保持纯洁,加以包装
      • 没有合适的就发明你要的轮子
  • 前端App的架构演进
    • 当移动互联网不发达时,基本都是Web App的天下
    • 随着无线的发展,手机应用程序发展起来了,但是每一个端[android,ios,window phone]都要写一套一样的代码
      • 为了维护好庞大的业务的应用程序,开发时候就会将每个业务组件化,以便复用。
    • 随着大家想减少成本,跨平台App方案出来了: React Native、Weex、Flutter
  • 如何画出优秀的软件系统架构图
    • 从多个方面去设计视图
      • 业务架构图:描述系统对用户提供了什么业务功能
      • 客户端和前端架构图: 描述客户端和前端的领域逻辑架构,关注的是从逻辑的角度如何分解客户端或者前端应用
      • 系统架构图:描述后端的逻辑架构
      • 应用架构图:描述后端系统由哪些应用组成
      • 部署架构图:描述后端系统具体是如何部署的,主要包含机房信息、网络信息和硬件信息等
      • 系统序列图:描述某个业务场景下,系统各个角色如何配合起来完成业务功能
  • 如何高效地学习开源项目
    • 安装,看看文件结构
    • 运行,看看解决什么问题
    • 原理研究, 如何解决这些问题的
    • 测试,是否适合自己的场景
    • 源码研究,看看解决问题的相关实现
  • 26
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值