架构思想
2019-09-03 13:11:22 0 举报
AI智能生成
架构思想
作者其他创作
大纲/内容
架构思想
目的
架构设计主要目的为了解决软件系统复杂度带来的问题
基础架构
高性能
单台计算机内部为了高性能带来的复杂度
升级软、硬能力实现性能的提升
垂直维度的操作,主要针对单台计算机
增加内存减少I/O操作
更换为固态硬盘(SSD)提升I/O访问速度
使用RAID增加 I/O吞吐能力
置换服务器获得更多的处理器或分配更多的虚拟核
升级网络接口或增加网络接口
多台计算机集群为了高性能
利用合理的任务分配与任务分解实现性能的提升。
主要针对集群系统
功能分解:基于功能将系统分解为更小的子系统
多实例副本:同一组件重复部署到多台不同的服务器
数据分割:在每台机器上都只部署一部分数据
SMP
对称多处理器结构,是指服务器多个CPU对称工作,无主次或从属关系。各CPU共享相同的物理内存,每个CPU访问内存中的任何地址所需时间是相同。
对SMP服务器进行扩展的方式包括增加内存、使用更快的CPU、增加CPU、扩充I/O(槽口数与总线数)以及添加更多的外部设备(通常是磁盘存储)。
NUMA
具备多个cpu模块,每个cpu模块由多个cpu(4)组成,并且具有独立的本地内存,I/O槽口等。
由于其节点之间可以通过互联模块(Crossbar Switch)进行·连接和信息交互,因此每个CPU可以访问整个系统内存(NUMA系统与MPP系统的重要差别)。显然,访问本地内存速度将远远高于访问远地内存(系统内其它节点的内存)的速度,非一致存储访问NUMA的由来。
MPP
在MPP系统中,每个SMP节点也可以运行自己的操作系统、数据库等。但和NUMA不同的是,它不存在异地内存访问的问题。换言之,每个节点内的CPU不能访问另一个节点的内存。节点之间的信息交互是通过节点互联网络实现的,这个过程一般称为数据重分配(Data Redistribution)。
但是MPP服务器需要一种复杂的机制来调度和平衡各个节点的负载和并行处理过程。目前一些基于MPP技术的服务器往往通过系统级软件(如数据库)来屏蔽这种复杂性。举例来说,NCR的Teradata就是基于MPP技术的一个关系数据库软件,基于此数据库来开发应用时,不管后台服务器由多少个节点组成,开发人员所面对的都是同一个数据库系统,而不需要考虑如何调度其中某几个节点的负载。
高可用
本质:通过冗余来实现高可用
核心思想:网站高可用的主要技术手段是服务与数据的冗余备份与失效转移。
高性能增加机器目的在于“扩展”处理性能;高可用增加机器目的在于“冗余”的处理单元;
计算高可用架构同存储高可用架构,都需要考虑故障发生时的分发。但是存储高可用架构,还需要考虑如何保证数据的一致性,也就是说有状态的,所以复杂度更高。而无状态计算高可用,机器之间不需交互,只需要考虑分发和重试机制。
存储高可用
存储高可用的难点不在于如何备份数据,而在于如何减少或规避数据不一致对业务造成的影响。
高可用状态决策
基础:状态决策,即系统需要能够判断当前的状态
矛盾:通过冗余来实现的高可用系统,状态决策本质上就不可能做完全正确。
独裁式
协商式
最常用的协商式决策就是主备决策
难点:主备之间信息交换出现问题(比如主备连接中断)
民主式
选举,例如:ZooKeeper
可扩展
两个基本条件
正确预测变化,完美封装变化
预测变化复杂性
不能每个设计点考虑可扩展性
不能完全不考虑可扩展性
所有的预测都存在出错的可能性
第一种应对变化的常见方案:将“变化”封装在一个“变化层”,将不变的部分封装在一个独立的“稳定层”
复杂性
系统需要拆分出变化层和稳定层
需要设计变化层和稳定层之间的接口
第二种应对变化的方案:提炼一个“抽象层”和一个“实现层”
抽象层是稳定的
实现层可以根据具体业务需要定制开发
典型的实践就是设计模式和规则引擎
装饰模式
低成本
引用新技术和创造新技术,才能达到低成本目标。
Nosql的出现是为了解决关系型数据库无法应对高并发访问带来的访问压力
(Sphinx、Elasticsearch、Solr)全文搜索引擎的出现为了解决关系型数据库like搜索的低效问题
hadoop为了解决传统文件系统无法应对海量数据存储和计算的问题。
业界例子
安全
从技术角度,安全分为两类
一类是功能上的安全
常见的XSS攻击、CSRF攻击、SQL注入、Windows漏洞、密码破解等等,本质上系统实现由漏洞。
一类是架构上的安全
防火墙最基本功能就是隔离网络。
互联网系统架构更多依靠运营商或者云服务商强大的带宽和流量清洗的能力
规模
规模带来的复杂度的主要原因就是“量变引起质变“
架构设计三原则
合适原则,简单原则,演化原则
合适优于先进》演化优于一步到位》简单优于复杂
设计备选方案
而恰恰需要把可能性大的变化点一一罗列出来,分维度打分,维度包括 可能性大小?长期还是短期会变化?如果发生变化,目前的组织和系统要花多大成本适应变化。这些变化正是李老师之前说过的各种复杂度上的变化,比如用户量激增带来的性能要求。此外还包括一个业务功能逻辑上的变化。在经过上面分析后往往会给出“上中下”策的设计方案,下策一般考虑的变化少,短视,但迅速,修改小,立竿见影。上策一般看重远期,但成本高很高,也很可能预测不中。最后还要分析,如果决定采用下中策,如果预测的变化发生了,系统修改为中上策的代价有多大,有些代价几乎是无穷大的,比如必须中断服务进行升级。如果代价小,那可以放心采用下策或中策。如果答案是否,可上策当前的代价又真的不可接受,那又要返回头重新分析了实践发现这个方法挺好用,尤其当有人来咨询架构方案时,往往对给出的结果比较满意
高性能架构模式
高性能数据集群
读写分离
其本质将访问压力分散到集群中多个节点,但是没有分散存储压力
实现
数据库服务器搭建主从集群、一主一从、一主多从都可以。
数据库主机负责读写操作,从机只负责读操作
数据库主机通过复制将数据同步到从机,每台数据库服务器都存储了所有业务数据
业务服务器将写操作发给数据库主机,将读操作发给数据从机。
细节
主从复制延迟
简介
MySQL为例,主从复制延迟可能达到1秒,如果有大量数据同步,延迟1秒钟有可能。从机数据不是最新的,读取数据有误。
策略
写操作后的读操作指定发给数据库主服务器
例如:注册账号完成后,登录时读取账号的读操作也发给数据库主服务器。这种方式和业务强绑定,对业务的强侵入和影响较大。
读从机失败后再读一次主机
通常所说的“二次读取”,二次读取和业务无绑定,主需要对底层数据库访问API进行封装即可,实现代价较小,不足之处在于如果很多二次读取,将大大增加主机的读操作压力、
关键业务读写操作全部指向主机,非关键业务采用读写分离
例如:对一个用户管理系统来说,注册+登录的业务读写操作全部访问主机,用户的介绍、爱好、等级等业务、可以采用读写分例,因为影响比较小,可以忍受。
分配机制
将读写操作区分开来,然后访问不同的数据库服务器
代码封装
实现读写分离和数据库服务器连接的管理
实现简单,而且可以根据业务做较多定制化的功能。
每个编程语言都需要自己实现一次,无法通用,多语言重复开发工作量大。
故障情况下,如果主从发生切换,则可能需要所有系统都修改配置并重启。
中间件
中间件对业务服务器提供SQL兼容协议,业务服务器无须自己进行读写分离。对于业务服务器来说,访问中间件和访问数据库没有区别。
能够支持多种编程语言,因为数据库中间件对业务服务器提供的是标准SQL接口
数据库中间件要支持完整地SQL语法和数据库服务器协议(例如,MySQL客户端和服务器连接协议),实现比较复杂,细节特别多,容易出现BUG
中间件性能要求比较高
探测数据服务器主从状态
分库分表
分散访问压力,又可以分散存储压力
海量数据,单台存储瓶颈
数据量太大,读写性能会下降,即时有索引,索引会变得很大,性能同样会下降。
数据文件会变得很大,数据库备份和恢复需要消耗很长时间。
数据文件越大,极端情况下丢失数据的风险越高(例如:机房火灾导致数据主备机都发生故障)。
业务分库
业务模块分散到不同数据库服务器
问题
join
业务分库后原本在同一个数据库中的表分散到不同数据库中,导致无法使用SQL的join查询
事务问题
原本在同一个数据库中不同的可以在同一个事务中修改,业务分库,表分散到不同的数据库中,无法通过事务统一修改。
成本问题
业务分库同时带来成本问题。
分表
单表数据拆分有两种:垂直分表和水平分表
单表进行切分后,是否要切分后多个表分散在不同数据库服务器中,可以根据实际切分效果来确定,并不强制要求单表切分为多表后一定要分散不同数据库中。
垂直
垂直分表适合将表中某些不常用且占了大量空间的列拆分出去。
表操作的数量增加
多次查询
水平
单表千万级别就可以分表
路由
范围路由
范围路由选取有序的数据列(例如,整形、时间戳等)作为路由的条件,不同分段分散到不同数据库表
优点
随着数据增加平滑地扩充新的表。例如:现在的用户是100万,如果增加1000万,只需要增加新的表就可以,原有的数据不需要动
缺点
分段大小选取上,分段太小会导致切分后子表数量过多,增加维护复杂度;分段太大会到单表依然存在性能问题,一般建议分段大小在100万至2000万之间,具体需要根据业务选取合适的分段大小。
Hash路由
选取某个列(或者某几个列的组合也可以)的值进行Hash运算,然后根据Hash结果分散到不同的数据库表中。
表分布的比较均匀
扩充新的表很麻烦,所有数据都要重分布
配置路由
配置路由就是路由表,用一张独立的表记录路由信息。
示例
以用户id为例,新增一张user_router表,这个表包含user_id和table_id两列,根据user_id就可以查询对应table_id。
设计简单,使用起来非常灵活,扩充表的时候,只需要迁移指定的数据,然后修改路由表就可以了。
必须多查询一次,影响整体性能。
如果路由表本身太大(例如,几亿条数据),性能同样可能成为瓶颈,如果我们再次将路由表分库分表,则又面临一个死循环式的路由算法问题选择
count
count()相加
具体做法是在业务代码或者数据中间件中对每个表进行count()操作,然后将结果相加。
性能比较低
记录数表
新建一张表,表名为“记录数表”,包含table_name、row_count两个字段,每次插入或删除子表数据成功后,都更新“记录数表”。
性能优于count方法
数据不一致
业务逻辑有误
事务处理有误
增加数据库写压力
对于一些不要求记录数实时保持精确的业务,也可以通过后台定时更新记录数表。
order by
水平分表,数据分散到多个子表中,排序操作无法在数据中完成,只能由业务代码或者数据库中间件分表查询每个子表中的数据,然后汇总进行排序。
实现方法
和数据库读写分离类似,分库分表具体的实现方式也是“程序代码封装”和“中间件封装”,但实现会更复杂。
判断操作类型外,还要判断SQL中具体需要操作的表、操作函数(count函数)、order by、group by操作等、然后再根据不同操作进行不同处理。
高性能NoSQL
关系数据库
关系数据存储的是行记录无法存储数据结构
关系数据库的schema扩展不方便
关系数据库在大数据场景I/O较高
如果对一些大量数据表进行统计之类的运算,关系数据库的I/O会很高,因为即使只针对其中某一列进行运算,关系数据库也会将整行数据从存储设备读入内存
关系数据库全文搜索功能比较弱
nosql
K-V存储
解决关系数据库无法存储数据结构的问题,以Redis为代表
文档数据库
解决关系数据库强schema约束的问题,以MongoDB为代表。
列式数据
解决关系数据库大数据场景I/O问题,以Hbase为代表。
全文搜索引擎
解决关系数据库全文搜索性能问题,以Elasticsearch代表。
高性能缓存架构
缓存就是弥补存储系统复杂业务场景下的不足
缓存穿透
缓存没有发挥作用
特点
存储数据不存在
缓存数据生成耗费大量时间或者资源
电商分页缓存
缓存雪崩
缓存失效(过期)后引起系统性能急剧下降的情况。
解决
更新锁
对缓存更新操作进行加锁保护,保证只有一个线程能够进行缓存更新
分布式锁
后台更新
子主题
单机服务器高性能模式
PPC与TPC
Reactor与Proactor
高性能负载均衡
分类及架构
算法
高可用架构模式
高可用架构
CAP
FMEA
可扩展架构模式
微服务
基础设施
架构实战
0 条评论
下一页