1.架构设计原则:
- 合适原则,合适的架构优先于业界领先的结构。
- 简单原则,简单的架构优于复杂的架构。
- 演化原则,架构需要随着业务的发展而不断演化。
- 真正优秀的架构师是在企业当前人力,条件、业务等各种约束下设计出来的,能够合理地将资源整合在一起并发挥出最大功效,并且能够快速落地。
2.备选方案360度环评
质量属性 | 集群方案 | 拆分方案 | 备注 |
---|---|---|---|
性能 | 中,继续扩展下去,mysql出现瓶颈 | 高,系统拆分为子系统,子系统又可以做成集群 | 拆分优 |
复杂度 | 低,引入nginx做负载 | 高,需要对系统和db做拆分 | 集群优 |
成本 | 中,需要增加web服务器 | 中,增加web服务器和mysql,mysql逻辑上分开 | 集群稍优 |
可扩展 | 低,所以功能在一个系统实现,越来越复杂,扩展越来越难 | 高,系统按照职责才分多个子系统,子系统可单独扩展 | 拆分优 |
可用性 | 中,web服务器是集群,但是db是单点 | 高,系统性是独立的,某个子系统不可用,不会导致整个业务不可用 | 拆分优 |
设计架构的时候,首先要分析出系统的复杂性。
备选方案差异要明显。架构师要对技术的细节和原理有比较深入的了解,避免成为“PPt架构师”。
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