架构-千万流量

微服务架构

服务化好处

  • 复用性,消除代码拷贝

  • 专注性,防止复杂性扩散

  • 解耦合,消除公共库耦合

  • 高质量,SQL稳定性有保障

  • 易扩展,消除数据库解耦合

  • 高效率,调用方研发效率提升

  • 潜在问题

    • 系统复杂性上升

    • 层次间依赖关系变得复杂

    • 运维,部署更麻烦

    • 监控变得更复杂

    • 定位问题更麻烦

微服务粒度

  • 统一服务层

  • 一个子业务一个服务(互联网最佳实践)

  • 一个库一个服务

  • 一个接口一个服务

高可用(是分布式系统架构设计必须考虑的因素方法论:集群冗余+故障自动转移)

  • “端”到“反向代理”(keeplived+VIP,故障自动转移)

  • “反向代理”到“站点应用"(站点应用的集群冗余,探测存活性,自动流量转移)

  • “站点应用”到“微服务”(微服务客户端的连接池来自动转移,微服务集群冗余)

  • “微服务”到“缓存"(一般没有高可用需求,只需保证数据库不会雪崩)

  • “微服务”到“读库”(冗余,通过数据库的连接池 实现自动转移)

  • “微服务”到“写库"(相互同步,keeplived+VIP,故障自动转移)

高并发(是分布式系统架构设计必须考虑的因素)

  • 方法:垂直扩展,水平扩展(无限性能)

  • 反向代理层

  • 站点应用层

  • 微服务层

  • 数据层

负载均衡(是分布式系统架构设计必须考虑的因素)

  • 反向代理层,站点应用层,微服务层,数据层如何实施负载均衡

  • 连接池很重要,高可用/扩展性/负载均衡,都和它相关

  • 过载保护不掉底,静态权重,动态权重

    • 连接代表服务,分值代表服务(连接)处理能力

    • 处理成功加小分,处理失败扣大分

    • 临界边界喘小口气

    • 死亡状态喘大口气

连接池

  • 为什么要连接池

    • 频繁的建立连接和销毁连接,在吞吐量提升到一定级别的时候会成为性能瓶颈,所以需要提前建立连接,不用每一次都建立和销毁
  • 两个核心数据结构

    • 连接数组

    • 锁数组

  • 三个核心接口

  • 高可用,故障自动转移

  • 扩展性,服务发现:自动载入新服务节点配置+动态连接池

  • 负载均衡:轮询,随机,静态权重,动态权重

数据库架构

读性能

  • 数据库要设计什么?

    • 依据“业务模式”设计库表结构

    • 依据“访问模式"设计索引结构

  • 读性能提升,常见方法与实践?

    • 增加索引,不用实例不同索引

      • 新增索引代表新建b+树,写入数据时会修改b+树,b+树越多,旋转会越多,写性能越低
    • 增加从库,使用数据库分组架构

    • 增加缓存,注意防止雪崩

垂直拆分与高可用

  • 尽量把:

    • 长度较短

    • 访问频率较高

    • 经常一起访问的属性放在主表里

  • 为何要将字段短,访问频率高的属性放到一个表内?

    • 原因是:数据库缓冲池,逻辑上,以row为单位缓冲数据
  • 高可用

    • 冗余+故障自动转移

主从一致性

  • 主从数据冗余,主从不一致:

    • 忽略

    • 强制读主

    • 借助缓存,选择性读主

  • 主主数据冗余,主主不一致:

    • 数据库不同初始值,相同增长步长

    • 应用层生成不冲突ID

    • 一个主库提供服务

扩展性

  • 扩展性,解决什么问题?

    • 底层表结构变更

    • 水平扩展,分库个数变化

    • 底层存储介质变化

  • 方案一,停服扩展(离线,非高可用)

    • 挂公告,暂停服务

    • 离线迁移数据

    • 恢复服务

  • 方案二,pt-online-schema-change(平滑)

  • 方案三,追日志方案(平滑)

    • 升级服务,记录日志

    • 离线迁移数据

    • 追日志,补充增量

    • 校验数据

    • 迁移流量

  • 方案四,双写方案(平滑)

    • 服务升级,“数据修改”双写

    • 迁移数据小工具,进行数据迁移

    • 数据校验小工具,校验数据一致性

    • 切流量到新库,完成平滑迁移;

水平切分,秒级成倍扩容

  • 互联网大数据量,高吞吐量,高可用微服务分层架构

  • 数据库实现秒级平滑扩容的三个步骤为:

    • 修改配置(双虚ip,微服务数据库路由)

    • reload配置,实例增倍完成

    • 删除冗余数据等收尾工作,数据量减半完成

缓存架构

进程内缓存

  • 优点

    • 节省内网带宽

    • 时延更低

  • 不足:一致性难以保证

  • 保证一致性的方法?

    • 单节点通知其他节点

    • MQ解耦,通知其他节点

    • 放弃实时一致性,定期从后端更新数据

  • 为什么不能频繁使用进程内缓存?

    • 违背了“站点无状态、服务无状态”的设计准则
  • 什么场景适用?

    • 只读数据

    • 并发极高,透传后端压力极大

    • 允许一定程度上数据不一致

  • 再次强调:

    • 不要为了炫技,而使用进程内缓存

    • 大部分场景,请使用缓存集群(redis/memcache)

常见误用与实践

  • 服务与服务之间不要通过缓存传递数据

  • 如果缓存挂掉,可能导致雪崩,此时要做高可用缓存,或者水平切分

  • 调用方不宜再单独使用缓存存储服务底层的数据,容易出现数据不一致,以及反向依赖

  • 不同服务,缓存实例要做垂直拆分,不宜共用缓存

架构实践

  • 互联网缓存最佳实践:Cache Aside Pattern

  • 读实践:先缓存,命中返回,未命中读数据库,再设置缓存

  • 写实践:淘汰缓存而不是修改缓存,先操作数据库,而不是先淘汰缓存

一致性

  • 数据库主从,何时不一致?写后立即读,短时间内,读旧数据

  • 数据库缓存,何时不一致?写后立即读,短时间内,旧数据入缓存

  • 优化思路:如果有旧数据入缓存,应该及时把这个旧数据淘汰掉

  • 优化方法:

    • 二次淘汰法(异步,服务)

    • 设定超时时间,有机会修正

redis还是mc

  • redis

    • 复杂数据结构

    • 持久化

    • 天然高可用

    • 存储内容比较大

  • memcache

    • 纯KV
  • 为什么mc在纯KV能更快呢?

    • 预分配内存池

    • redis的VM机制更慢

    • redis的CPU计算复杂

    • 多线程可利用多核

  • 其他:

    • redis源码可读性好

    • redis和mc都需要手动水平切分

posted @ 2021-09-14 15:36  请务必优秀  阅读(60)  评论(0编辑  收藏  举报