1.架构设计原则:

  • 合适原则,合适的架构优先于业界领先的结构。
  • 简单原则,简单的架构优于复杂的架构。
  • 演化原则,架构需要随着业务的发展而不断演化。
  • 真正优秀的架构师是在企业当前人力,条件、业务等各种约束下设计出来的,能够合理地将资源整合在一起并发挥出最大功效,并且能够快速落地。

2.备选方案360度环评

质量属性集群方案拆分方案备注
性能中,继续扩展下去,mysql出现瓶颈高,系统拆分为子系统,子系统又可以做成集群拆分优
复杂度低,引入nginx做负载高,需要对系统和db做拆分集群优
成本中,需要增加web服务器中,增加web服务器和mysql,mysql逻辑上分开集群稍优
可扩展低,所以功能在一个系统实现,越来越复杂,扩展越来越难高,系统按照职责才分多个子系统,子系统可单独扩展拆分优
可用性中,web服务器是集群,但是db是单点高,系统性是独立的,某个子系统不可用,不会导致整个业务不可用拆分优

设计架构的时候,首先要分析出系统的复杂性。

备选方案差异要明显。架构师要对技术的细节和原理有比较深入的了解,避免成为“PPt架构师”。

3.储存高性能

解决主从延迟常见的办法:

  1. 写操纵后的读操作指定发给数据库的主服务器。这种和业务强绑定。
  2. 读从机失败后再读取主机。大大增加主机的读操作压力。
  3. 关键业务读写主机,非关键业务采用读写分离。

分表:

垂直分表

适合将表中某些不常用的且占了大量空间的列拆分出去。可以提高性能,但是会增加查询次数。

水平分表

适合表行数特别大的表。

常见的路由算法:

  • 范围路由,例如id范围。
  • Hash路由 uid%64。
  • 配置路由 用一张表来记录路由信息。 设计简单,使用起来非常灵活,扩充表市,迁移指定的数据。缺点:多一次查询,路由表本身太大,也会成为瓶颈。

分表带来的问题:

  • join操作,需要做多次join查询,再合并结果。
  • count操作 :count数想加多次count,记录数表:记录表的记录总数。复杂度增加。不一致。
  • order by 操作 分表查询字表中的数据,汇总排序。

Redis的事务只能保证I隔离性和C一致性。无法保证A原子性和D持久性。

4.缓存设计

4.1缓存穿透:

缓存没有发挥作用,业务系统直接去查询了存储系统。

通常是两种情况:

存储数据不存在。

解决办法:

缓存空值,也可以是具体的值。

以及生成缓存数据需要耗大量的时间或资源。

4.2缓存雪崩:当缓存失效(过期)后引起系统性能急剧下降的情况。

请求打到存储系统,对存储系统造成巨大的压力。拖慢整个系统,造成系统宕机,连锁反应,造成整个系统奔溃。

缓存雪崩的解决办法:

  • 加锁更新。分布式锁,zookeeper,redis。go 里的singleflight。
  • 后台更新 缓存设置不过期,后台定时更新。
  • 特殊场景缓存系统内存不足时,会踢掉一些缓存数据。

(1)定时读取,用户体验一版。

(2)消息队列通知 缓存更新及时,用户体验更好。

后台更新还适合进行缓存预热。

4.3缓存热点

特别热点的数据,所有的业务请求都命中都一份数据。对缓存服务器的压力很大。例如大明星发的维度。

解决方案:

复制多分缓存。请求分散到多个缓存服务器上,减轻缓存热点导致的单台缓存服务的压力。

假设分成100份。

缓存key+编号。 读取时随机读取某份的数据。

5.常见的负载均衡算法及优缺点

轮询:

系统收到请求后,按照顺序轮流请求分配到服务器上。无需关注服务器本身的状态。

缺点:

无法感觉系统CPU高负载。无法关注到集群中机器的差异。录入新的机器是32核,老的机器是16核。

加权轮询:

负载均衡系统根据服务器权重进行任务分配。解决了轮询算法无法根据服务器配置差异进行任务分配的问题。

缺点:

无法识别服务器的状态差异。

负载最低优先:

分配任务给当前负载最低的服务器。根据不同的指标。

LVS4层网络负载均衡系统:连接数。Nginx:http连接数。

自己研发的系统:CPU负载,I/O密集型。

优点:

可以感知服务器的当前的运行状态。

缺点:

复杂度大幅度上升。

性能最优类:

从客户端的角度,优先将任务分配给处理速度醉的服务器。

通过统计分析每个服务器的响应时间,可以采样统计,10s,1m,5分

Hash类型:

负载均衡系统根据任务的某些关键信息进行hash运算。

源地址hash

将来源于同一个源Ip地址的任务分配给同一个服务器。

IdHash