标签 架构 下的文章

一、CAP理论

    准确的定义是:在一个分布式系统中(互相连接并共享数据的节点的集合)中,涉及到读写操作时,只能保证一致性C(客户端读保证得到最新的写结果)、可用性A(返回noerror notimeout)、分区容错性P(出现分区后系统可以继续履职)三个中的两个,必须牺牲另一个。在实际中,无论如何都要满足P,因为如果没有P,在网络故障时,要保重C就必须停止写入,但A要求返回noerror和notimeout,所以A也不满足。网络分区错误类似脑裂、数据同步中断,最坏的情况是主从连接断开,各自成为了独立个体。

二、CAP细节:

    1、CAP:

        (1)CAP关注的是数据,而不是整个系统。比如账号信息是CP,而用户资料是AP。

        (2)CAP是忽略网络延迟的。数据复制是有延迟的,即时在内网也有几毫秒,对于金钱和秒杀类的场景,一致性C是无法完美实现的。但并不是说这类业务不能做分布式,可以把同一用户、同一商品放在同一个机器,同一用户做不了分布式,但是整个业务是个做的,比如根据uid分布在不同机器。

        (3)正常情况下,是可以同时满足CAP的。P强调的是网络分区错误时,CA二选一。但是在网络正常情况下,CAP就可以同时满足。分区故障时,选择CP的,节点1可以注册,节点2不可以注册,可以节点1打日志,恢复注册后同步到节点2,CA同时存在。选择AP的,节点1和节点2是用户两次不同的修改,恢复后可以根据时间优先来进行覆盖,最终达到同时满足AP。

    2、ACID:原子性、一致性(食物开始前和结束后,数据库完整性没有被破会)、隔离性(隔离级别)、持久性(事务提交后就是永久的哪怕发生故障)、和CAP中的AC完全不是相同含义,ACID的C是数据库完整性,A是原子性,指事务要么都完成或都回滚;ACD的C是节点数据一致性,A是读写可用性。

    3、BASE:BA(基本可用)和S(软状态)和E(最终一致性)。是对CAP理论的AP的补充。AP分区时放弃的是网络分区这段时间的一致性,但恢复后最终会一致。

        (1)基本可用:允许损失部分可用性,保证核心可用。如可以不注册,但是要保证登陆,否则影响更大。

        (2)软状态:允许出现中间状态,不影响整体可用性。这种中间状态就是CAP理论的数据不一致。

        (3)最终一致性:数据同步一定是有延迟的,只要保证最终一致性即可。如注册后不超过一分钟可以在各个节点登陆。明星发微博后可以三十分钟内同步到所有用户  

    

三、FMEA方法论:故障模式与影响分析

四、高可用存储-双机架构

    1、主备:简单,但是浪费资源,手动扶正。

    2、主从:主挂后可以继续读,但客户端调用时需要知道谁主谁从。故障后需要人工扶正。

    3、双机切换:在主备和主从上加入了切换功能,数据库自己做还是加入第三方、状态如何传递、如何判定故障、自动还是半自动、是否切换角色。

    4、互链式:主备之间除了数据同步,还要状态同步,可以是网络连接和有线连接等VIP自动飘移。但是这个链接管理是难点,可能出现两个都是主。

    5、中介式:引入第三方,弥补互链式缺点。

    6、模拟式:备机当作客户端访问主机。

    7、主主:客户端任写其一,主主互相同步,不做状态和切换。缺点是主键和数据冲突,如用户id商品库存等无法这么做。

五、高可用存储-集群和分区架构

    1、集群:

        (1)、一主多从多备,多备机都要检测主机状态,通常引入第三方如zookeeper,复杂度变高。

        (2)、多主,数据分散写在不同集群,要考虑均衡性、容错性、伸缩性。

    2、分区:分散在地域机房及以上的级别。如果备份要提供服务,则距离不可太远,否则网络不可靠。

        (1)集中式:北京分区上海分区都备份在西安机房。

        (2)互备式:北京备份在上海,上海备份在广州,广州备份在北京

        (3)独立式:各个分区有各自独立的备份机房。

六、高可用计算

    分为主备。主从。集群。集群分为对称和非对称。对称是执行相同任务,非对称则需要区分任务。非对称集群需要处理分发策略和主机选举策略。计算高可用就是通过冗余来解决单点问题,但存储高可用还有数据一致性、对机器之间同步和状态心跳等问题,更为复杂。

七、业务高可用:异地多活

    1、多活复杂度较高,规模以下企业多备即可

    2、方案:

        (1)同城异区主要应对机房故障。

        (2)异地(北京广州)多活复杂度很大,网络延迟,光缆中断等原因导致金钱等敏感业务是做不了多活的。多活为了高可用,但是数据不一致肯定不可用,这是矛盾的。

        (3)跨国多活:通常只有只读业务,和不同地区为不同客户数据不互通。复杂度不高。

八、异地多活技巧

    同城跨区可以将两机房连起来就像内网一样。跨国面向不同用户提供不同服务复杂度不高。这里主要讨论跨城。复杂度来源主要还是网络延迟和机房异常

    1、保证核心业务和高收入业务:比如登陆,核心业务方案简单。而注册是主要任务,同时异地多活复杂度极高。高收入业务会影响财报和广告主口碑等

    2、最终一致性:同步完成之前,B可以路由回A请求。

    3、对手段同步:mysql只有单线程,redis需要全量rdb文件重新做。同步方式有:异步队列、二次读区、存储系统同步、回源读、重新生成等方式。

    4、只保证大部分用户:异地多活方案无法做到100%。

九、接口级故障:限流

    核心思想是保障核心业务和大部分用户。

  1. 降级:指服务内部处理方案,如关闭注册、看帖不能发帖、应用日志接口。有内部提供URL和独立模块实现的方式。

  2. 熔断:指依赖的其他服务异常。实现的机制是要对对方服务采样统计,设计阈值。

  3. 限流:基于流量限流如1分钟超过一万就丢弃;基于资源限流如负载高低和队列容量等。

  4. 排队:借助队列系统。一号店秒杀方案:排队模块,一个商品一个队列;调度模块,业务服务空闲时出队一个交给业务服务处理;业务模块,真正处理业务的。 

一、数据库集群:读写分离

二、数据库集群:分库分表

三、NoSQL = not only sql

四、缓存

    1、用户请求发现缓存不存在则自行查库并生成缓存。并发下可能会同时很多请求同时生成,造成雪崩。

    2、用户请求发现缓存不存在,通过队列后台生产缓存,并发下,消费者应判断缓存是否已存在,不存在时在生成。

    3、热点数据后台脚本生成,在内存紧张时新生成一个就会淘汰一个,脚本应不断检测若缓存不存在则重新生成。

    4、全网热点数据,如明星官宣,这时应生成多份缓存,以集群来分散单机压力。

五、单机高性能:PPC和TPC

    1、PPC:每来一个链接就创建一个进程。优化版是启动时预创建多进程。

    2、TPC:同PPC,进程换线程。

六、单机高性能:Reactor和Proactor

    1、Reactor:就是IO多路复用,也叫Dispatcher,同步非阻塞模型。如epoll、kqueue等。单reactor单进程有redis,多reactor单进程没任何优势,多reactor多进程有nginx和memcache。通俗讲:来了事件操作系统通知应用程序,应用程序来处理。

    2、Proactor:异步非阻塞。Reactor需要用户进程同步做read write等IO操作,如果改为异步可以提高性能,这就是Proactor。通俗讲:来了事件操作系统来处理,处理完通知应用程序。虽然性能更好,但是Linux下的AIO并不完善,真正实现了异步非阻塞的操作系统是windows的IOCP。

    3、IO操作分两个阶段

        1、等待数据准备好(读到内核缓存)

        2、将数据从内核读到用户空间(进程空间)

        一般来说1花费的时间远远大于2。

        1上阻塞2上也阻塞的是同步阻塞IO

        1上非阻塞2阻塞的是同步非阻塞IO,这就是Reactor就是这种模型 

        1非阻塞2上非阻塞是异步非阻塞IO,这讲说的Proactor模型就是这种模型

七、复杂均衡的分类和架构

    1、最上层DNS:针对地域。就近访问。缺点更新缓存慢,不可定制化。

    2、硬件层F5:性能最好,价格昂贵,便宜的也要一台马六。qps两百万到八百万。

    3、软件层LVS:性能始终,qps八十万。在三层网络  

    4、软件层nginx:性能最差,qps五万左右。

八、负载均衡的算法

    1、轮询:简单,但由于简单,也是缺点。宕机也无法知道。

    2、加权轮训:根据机器性能等权重不同,其他缺点同轮询。

    3、最小负载:LVS四层可以根据最小连接数,Nginx七层可以根据最少HTTP请求数(默认不支持)。 自研的话可以根据CPU IO等来判断,但是复杂度太高,是1、5、15分钟的负载?太短波动太频繁,太长峰值来临时感知太晚。

    4、性能最优:同最小负载,都是要感知服务器状态,复杂都高。如果收集量太大影响性能,如果采样,又需要合理的采样率,否则不准确。

    5、Hash:根据id hash、根据ip hash。如银行业务,请求都要落在同一台机器上。


一、概述

1、架构是顶层设计;框架是面向编程或配置的半成品;组件是从技术维度上的复用;模块是从业务维度上职责的划分;系统是相互协同可运行的实体。

2、架构是为了应对软件系统复杂度而提出的一个解决方案。个人感悟是:架构即(重要)决策,是在一个有约束的盒子里去求解或接近最合适的解。这个有约束的盒子是团队经验、成本、资源、进度、业务所处阶段等所编织、掺杂在一起的综合体(人,财,物,时间,事情等)。架构无优劣,但是存在恰当的架构用在合适的软件系统中,而这些就是决策的结果。

需求驱动架构。在分析设计阶段,需要考虑一定的人力与时间去"跳出代码,总揽全局",为业务和IT技术之间搭建一座"桥梁"。

架构设计处于软件研制的前期,一方面,越是前期,如有问题,就能够越早发现,修改的代价也就越低;另外一方面,也意味着,软件实施后期若有架构上的修改,也需要付出更多的代价。

    1)架构是为了应对软件系统复杂度而提出的一个解决方案。

    2)架构即(重要)决策

    3)需求驱动架构,架起分析与设计实现的桥梁

    4)架构与开发成本的关系


二、架构复杂度来源

3、系统复杂度来源:高性能。从单机到集群的服复杂度来源:

    1)任务分配:F5、交换机、LVS、Nginx、HAProxy等

    2)任务分解:拆成服务。业务本身不变的情况下性能有上限,系统拆封可以逼近这个极限,但不能达到。过多的服务调用会降低性能。

4、系统复杂度来源:高可用。复杂度通常高于高性能,因为涉及到知识点更多。

    1)计算高可用:冗余。

    2)存储高可用:难点不是如何备份,而是如何减少数据不一致带来的影响。分布式领域里有CAP理论,即一致性,可用性,分区容错性只能取其二。

    3)状态决策:

        (1)独裁式,仍有单点问题;

        (2)协商式,两台备,然后自行决策选出主,在主备连接中断后变成两主,不符合预期;

        (3)民主式,如zookeeper,节点自行投票,为解决脑裂问题,需要投票过半数。但在1、2、3节点故障后,4、5仍可用,但投票不过半数,无法选主,系统不可用。

5、系统复杂来源:可扩展性。应对变化的适应能力。不能不做预测,预测也可能出错,也不可以过度预测。封装变化,隔离可变性。

6、系统复杂度来源:成本。高性能高可用意味着更多的机器,当规模达到一定程度后,成本却就是考虑因素之一了。低成本的架构方案意味着引入新技术或开发新技术。开发新技术复杂度更高,如HHVM,kafka等。

7、系统复杂度来源:安全。分为功能安全如windows漏洞SQL注入等,和 架构安全如防火墙ACL等。防火墙性能低,目前没有很好的办法,更多是靠运营商清洗。

8、系统复杂度来源:规模。分为功能规模和数据规模。数据规模是数据量越来越大发生质变,比如mysql,超过五千万行后要开始分库分表。


 三、架构设计原则

1、三大原则:合适 > 演化 > 简单 这个优先级。

    1)合适原则:合适优于业界领先。没那么多人、没那么多积累、没那么卓越的业务场景。

    2)简单原则:简单优于复杂。结构的复杂性、逻辑的复杂性。

    3)演化原则:演化优于一步到位。首先要满足当前的业务需求,不贪大贪全,照搬大厂架构。要遵循演化原则。

高性能网站架构方案,本文谈了七点网站架构方案,用以优化网站响应时间,实现大型网站技术架构方案。无论是电子商务或者其他网站且可使用。
一、优化网站响应时间的架构方案:
网站能不能留的住用户,一方面是看内容,另一方面是看响应时间。通常有以下几个方式来降低网站响应时间:
1、减少HTTP请求。包括合并css和javascript。减少图片数量,比如利用css的偏移技术来在一个图片中选择不同的位置内容。利用浏览器的Cache功能,我们可以在头中声明是否被浏览器缓存。
2、动态内容静态化。比如永久生成HTML文件。生成静态文件并设定生存时间,到期后查询新的动态内容进行替换。
3、优化数据库。数据库的性能对于项目整体性能中是重中之重。设计良好的Mysql比乱糟糟的Mysql性能高出N个数量级,更别论再引入NOSQL了,比如Redis,MongoDB。
4、使用负载均衡。将请求合理的分发到更多服务器。
5、使用缓存。把花费时间和资源成本高昂的计算结果取出缓存起来,避免重复计算。比如在Mysql前面挡一层Memcached。比如生成一个文件,使用的时候include进来。再比如PHP中的OPCACHE等。

二、压力测试的架构方案:
吞吐率是指单位时间内处理的请求数,单位reqs/s。最大吞吐率是指单位时间内能够处理的最大请求出。模拟足够多的人数和并发请求来测试最大吞吐率的方法叫做压力测试。比如Apache自带的ab(Apache Bench)。ab的参数很多,常用的有请求数(-n),并发用户数(-c),超时时间(-t),长连接(-k),附件一个Cookie(-c name=value)

$ab -c 10 -n 1000 http://localhost/

三、长连接的架构方案:
每次请求都需要TCP的三次握手,握手完比表示连接正式联通,之后再发送数据。那么,把N个请求,就需要3N次握手,传递N次数据,得到N次响应,总共5N。如果把N个请求合成一个请求,就是3次握手,1次传递数据,1次返回响应,共5次。但是,有时候我们需要上一次响应的返回结果来发送新一轮的请求,在这个时候,合并请求并不好实现,这就需要长连接。使用起来很简单,在头中包含如下:

Connection: Keep-Alive

客户端和服务器端都可以设置长连接的最大时间,当两者不统一时以小的一方为准。开启长连接后进行压力测试:

$ab -c 10 -n 1000 http://localhost/

发现提升不止三五倍。本机是提升了8倍的性能。

四、提高Mysql的响应速度的架构方案:
Handlerocker是日本的一位架构师开发。Mysql的一种插件。Handlerocker实现了绕过Mysql的SQL解析层。在Mysql5.1以上版本可以使用,详情可以查看Mysql手册。这里就不在阐述。

五、Mysql主从复制的架构方案:
在分布式部署中,1台主库,N台从库。主库只写,从库只查。主库从库数据需要实现统一,这就是主从复制。优点是:
1、从库备份时,主库可以继续处理更新。
2、优化响应时间。
3、增加健壮性。主库挂了可以切换到从库作为备份。
主从复制的实现过程有三步,1个在主库,2个在从库:
1、主库服务器将用户对数据库更新的操作以二进制格式保存到Binary Log日志文件。然后Binlog Dump线程将Binary Log日志文件传输给从库服务器。
2、从库服务器通过一个I/O线程将主库服务器的Binary Log日志文件中的更新操作复制到一个叫做Relay Log中的中继日志文件中。
3、从库服务器通过另一个SQL线程Relay Log中继日志文件中的操作依次在本地执行,从而实现主从数据库之间数据的同步。
本篇只是简单的列出方案,详细的配置和实现步骤将在另一篇中写到。

六、代理的架构方案:
读取内存的速度是读取硬盘的100000-1000000倍。把访问过的页面缓存在内存中,下次直接从内存中读取,可以有效加速。
1、传统代理。客户端发送请求给代理服务器,代理服务器向WEB服务器取到数据并返回给浏览器。代理服务器就是一个有大的存储空间的Cache。
2、反向代理。和传统代理原理类似,只是使用对象不同。传统代理的使用对象是客户端,反向代理的使用对象是服务器。用户通过反向代理访问Web服务器,Web服务器是隐藏起来的。不过用户不关心这些,权把代理服务器当作真实的Web服务器。反向代理有Vamish。

七、异步计算的架构方案:
比较耗时的比如将用户上传的文件分发到多台机器,比如裁剪图片,视频转码等。可以使用异步方案。让用户无须等待计算结束而是先行返回结果。代表产品有和Memcache同一家的Gearman。关于Gearman的使用可以查看PHP手册。