上一篇文章初识架构让我们对架构设计的复杂度考虑有了一定了解,主要有个高可用、高性能、可扩展。但仅仅知道是不够用的,接下来,将从高性能来进行详细分享
1. 高性能数据库
从数据库分享高性能,主要是两个方面分别是:
1.1 读写分离
读写分离的主要原理是将读和写分散到不同的节点上
1.1.1 实现方式
数据库搭建主从模式,一主多从或一主一从。主服务器负责写, 从服务器负责读。从服务器通过复制的方式从主服务器同步数据。
在业务域实现分别有两种方式:
- 从代码层面实现。主要是代码封装,通过将读写请求分离出,请求不同的数据源
- 从中间件层实现。如:MysqlProxy等
1.1.2 带来的问题
读写分离将业务读写的压力分开,但是也带来了一些其他问题,如:
- 主从复制可能有延时,主从数据间数据不一致问题
- 将数据的读压力分散开,但是并没有减少数据库的写压力
- 为了区分度读写操作,需要引入中间件或对代码进行改造
1.2 分库分表
通常在数据表有压力的时候,我们会采取分库分表的策略,将数据分在不同的数据区域,减少数据存储压力。
1.2.1 分库
业务分库:按照业务模块将不同的数据存储到不同的数据库服务器
2.1.1 带来的d问题
- 事务问题: 多库间操作无法在一个事务内完成
- 成本问题:分库带来服务器数量增加,从而增加成本
- 数据查询带来复杂问题: 多库不利于 join()操作
1.2.2 分表
分表:单表存储数据过大时,需要对数据进行分表存储,放在不同的表中。分表又分为两种,分别是:垂直分表、水平分表。
垂直分表:把不常用的字段分出去。分表方式如:备注,内容等大字段
水平分表:对单表数据较大的进行分表。分表方式如: ID, 年月
1.2.2.1 分表策略
分表需要把数据分配到不同的表中,这就涉及到了表数据的分配算法。主要的分配算法有:
- 范围路由:如根据ID,1999999,10000009999999
- Hash路由:可以根据某些字段,进化hash计算,如 hash%表数。
- 配置路由:新建一张表,配置路由键与表之间的关系。如log_id,table_num两列。
1.2.2.2 带来的问题
- 数据表聚合操作标的麻烦,如:group by,count等
- 合适的数据路由策略选择,防止数据不均匀
1.3 优化策略
通常,我们在数据库出现瓶颈压力的时候可能优先考虑的是上述方案,这样其实是不对的。对于数据库方面的优化策略主要是:1、从硬件方面优化。2、SQL优化。3、增加缓存。4、分库分表。这样优化的如要目的主要是减少代码的改动量,保证业务的稳定性。
2. 高性能NoSQL
在某些情况下,我们需要根据具体情况选择合适的NoSQL,具体有如下NoSQL。
2.1 Key-Value形式
key-value形式的NoSQL主要解决关系型数据库无法存储数据结构的问题。以Redis为代表。
2.2 文档数据库
文档数据库主要解决关系型数据库强Schema问题。以MongoDB为代表。
2.2.1 优点 & 缺点
优点:1、新增字段简单。 2、对历史数据不会造成影响。 3、容易存储复杂结构数据,如JSON。
缺点:1、不支持ACID
2.3 列式数据库
列式数据库主要解决大数据场景下I/O问题。以HBase,clickhouse为代表
2.3.1 优点 & 缺点
优点:1、数据读取量小,如一行是4K, 某列可能只有4Byte,可以减少I/O。 2、同一列数据高度相似,可以提高压缩比例,易于存储。
缺点:1、对多列数据进行修改,查询多列由于是随机I/O,相对与行顺序I/O,性能较差。
2.4 全文搜索引擎
全文搜索引擎主要解决关系型数据库全文搜索性能问题。以ES为代表。
1 & 2 小结
关于数据库选择方式,我们需要以需求为导向。根据合适的业务场景选择合适的数据库。主要的考量指标有:数据量、并发量、一致性要求、读写分布、安全、运维等。
3. 高性能缓存架构
在应对一些又计算后得出的数据,或者读多写少的场景,一般存储系统无法应对,我们需要引入缓存。如:Redis,MemCache。接下来主要说一下系统引入缓存架构带来的问题。
3.1 缓存穿透
缓存穿透主要是数据的查询直接落在数据库上导致。造成缓存穿透的主要原因有两点,分别是:
- 查询数据不存在。
- 查询数据刚好失效,生成缓存时间较长。
解决策略:
- 缓存空数据
- 使用布隆过滤器
3.2 缓存雪崩
缓存雪崩主要是缓存失效,引起系统性能急剧下降。造成雪崩的主要原因是:
- 新缓存生成耗费时间,多线程同时更新缓存,造成DB压力,从而拖动系统西能。
解决策略:
- 更新锁机制:对缓存的更新进行加锁操作。
- 后台更新机制: 缓存长久有效,通过后台手动更新或缓存失效,触发后台更新等。
3.3 缓存热点
缓存热点主要是同一时间访问量急剧增大导致,如微博上"爆"点。
解决策略:
- 多级缓存:通过实时分析,将预热数据存入本地缓存中,然后才是缓存系统
- 将热点数据进行多副本保存:如key_1, key_2, key..n等,分散查询。
4. 单机高性能
增加单机高性能,则可以通过增加进程或线程的方式,我们一般通过增加线程的方式。主要的方式有两种:分别是:
- IO多路复用, Reactor
- AIO
5. 高性能负载均衡
通常,负载均衡也是高性能的一块,一个合适的负载均衡,对系统的提升也非常明显。从大往小了说,主要分为三类,分别是:DNS负载,硬件负载,软件负载。接下来将一一介绍。
5.1 DNS负载均衡
DNS负载均衡主要是有DNS厂商提供的一种负载均衡算法,其主要逻辑是:通过解析域名,可以返回不同的IP地址。如:解析www.jd.com,上海用户通过DNS解析出来的地址可能是:10.23.12.1; 黑龙江用户解析出来的是:60.111.23.55;这样通过不同的IP,访问就近的地址,加速用户的访问。
5.1.1 优点 & 缺点
DNS负载的优点主要有:1、直接又DNS厂商提供,操作简单,成本低。2、用户访问就近区域,加速用户访问速度。
缺点也比较明细:1、IP缓存时间长,用户可能更新不及时。
5.2 硬件负载均衡
硬件负载均衡主要是通过硬件层面来进行负载均衡,和交换机,路由器类似。主要代表有F5,A10。
5.2.1 优点 & 缺点
优点:1、性能强劲,可以支持百万级并发量。 2、支持在网络各层级进行负载,支持多种负载算法。3、支持安全防火。如:DDOS
缺点:1、价格昂贵,一般公司承受不起。2、可以根据业务配置,但是无法进行扩展和定制
5.3 软件负载均衡
软件负载均衡主要是通过软件来进行负载均衡,主要代表有Nginx(7层)、LVS(4层)等。同硬件想比,软件则无法支持那么大的并发量。但也有自己的优点。
5.3.1 优点 & 缺点
优点:1、部署运维简单,都提供部署方法。2、便宜,多加机器就可以部署。3、灵活,可以在网络7层或4层进行配置,支持扩展。
缺点:1、没有硬件负载那么大并发,如Nginx并发:5W/s。2、不支持网络安全防护,如DDOS攻击。
5.4 负载均衡算法分类
讲完了负载均衡,那接下来就讲解一下负载均衡算法的分类,主要也分为四大类,分别是:任务平分类、负载均衡类、Hash算法、性能最优类。接下来一一分析一下。
5.4.1 任务评分类
任务平分类主要是将任务平均分配,实现比较简单,无状态,和机器无关。如:轮询
5.4.2 负载均衡类
这里的负载均衡不是我们理解的负载均衡,而是通过计算出机器的性能,使用情况,如:CPU,IO,网卡连接数等,然后在分配任务。对机器性能做出平衡。防止差的机器接收大量的任务。如:加权轮询,负载最低优先
5.4.3 Hash类
负载均衡根据任务中的某些信息,进行hash计算,将相同hash值的任务放在同一个服务器上。这样可以满足某些特定业务需求。如:根据机器Ip进行hash计算,或者根据id进行hash计算。
5.4.4 性能最优类
性能最优类和负载均衡类有所不同,性能最优类是站在客户端的角度来看,谁处理任务快,就把任务多分配一些。负载均衡类是站在服务器端的角度来看。
6 总结
以上是总结的关于高性能架构设计时,我们可以考虑的点。在考虑设计时,我们不必拘泥于选择其中一点,而是进行搭配使用。为了满足业务需求,进行最大程度选择组合,这样才可以设计出符合业务的高性能架构。