大型网站技术架构之高可用
服务部署:一般上线之前会合并代码到develop分支上,然后通过打包平台进行编译打包,然后将包通过scp传到服务器上,ssh 服务器ip 然后执行命令重启服务,重启之前,先从ngnix切除到这台服务器的请求(通过命令修改配置删掉对应服务器ip,然后reload nginx),等待1、2秒 等到应用服务处理完正在处理的数据,最后重启服务器,然后检查其端口是否启用,是否有错误日志,如果一切正常则将服务挂到nginx上,再重启其他服务
1、应用服务高可用
通过负载均衡器,对应用服务心跳检测、对失效请求转移到其他正常服务器上
集群上的服务是对等的,无状态的,伸缩更灵活
对于有状态服务,session的管理(当用户登录成功后,用户访问其他页面时,也就是在当前会话执行所有操作都是有效的)
例如用户A加了一件商品到购物车,然后用户A又加了一件商品到购物车,这个时候用户看到购物车要有两件商品,也就是说要有服务器上要保存某个人购物车的数据,等于就是说同个人的请求都需要打到同台机器上。
-
通过对ip或根据客户端cookie计算一个hash值,对机器数取余,将同个客户端请求达到同台机器,但是当增加一台或移除一台机器时,都会导致请求打到其他器上了
-
将session信息存放到cookie上,请求时带上,然后将新的session信息写会客户端,这可以避免上面服务伸缩带来的问题,但是将session信息存放在客户端不安全,由于客户端可能会关闭cookie
-
session存放在数据库中
登录成功后返回给客户端一个token,然后后面会话中带上token,后端进行校验会话是否有效,这种方式就是将session信息存储在数据库或缓存中
- 对于有些业务对session管理要求高的可以将session管理单独做成一个服务器集群,做成单点登录(SSO)、用户服务,对于用户来说在各个网站都是用同一个账号进行登录,这些服务都需要请求session服务校验用户信息
2、服务层(公用服务、其他服务)高可用
应用层服务通过RPC方式调用基础服务,这些基础服务也是集群部署的,无状态的,负载均衡策略在调用端。
- 分级管理
将服务按照重要性划分级别,分配对应配置的机器,保证重要的服务能高效稳定运行
- 异步
通过异步方式(消息队列)解除服务间耦合和提高请求响应,例如注册成功后需要给用户下发邮件,以及分配权限,等一系列操作,可以通过下发一个注册成功消息到队列中,可以让其他服务对此消息进行消费,坐后续逻辑,不要因为发邮件失败了而影响用户注册。让用户能快速注册。
但是对应用户响应请求,或者下一步操作需依然前面响应结果时,不能够使用异步方式
- 服务降级(拒绝请求、关闭功能)
在高并发、高流量时候,为了保证服务不被冲垮,会通过拒绝部分请求,可以随机拒绝用户请求
可以关闭其他不重要功能为其他核心功能腾出资源
- 超时设置
为了避免对方服务岩机或线程死锁,调用端迟迟收不到响应,而此时调用端依然占用资源(线程池资源,调用端公用同个tcp连接,当多个线程同时向同个socket连接写数据时 系统通过给写入缓存区加锁保证线程安全),同时也不能及时将请求转发的其他服务器上。所以通过增加超时时间,超时时间不能过长,根据每个接口执行逻辑预测一个超时时间,过短会导致重试过多增加服务器压力
- 幂等性
无论是服务执行成功了,但是响应数据时因网络慢导致超时,还是服务负载高一直没有响应都会导致调用端重复提交请求,因此就会导致重复调用问题,需要在服务端保证重复调用和调用一次结果一样(幂等性),不管接口是否会重复请求多少次,对业务数据都不会造成影响,例如转转接口需要保证幂等性,否则如果重复请求就会导致多次扣款情况
3、数据层高可用
同样采用冗余的方式,保证数据服务的高可用性,服务A中的分片数据同步一份到服务B中作为一个副本,当服务A down机时会,会选举其他服务节点中分区的副本为主分区,然后将请求转移到该服务上,并将数据同步到其他服务节点作为副本,实现高可用。
- CAP原理:Consistency + Available + Partition
CAP原理对分布式系统设计具有重要指导意义
Consistency: 一致性,所有应用程序都能访问到相同的数据
Availiable: 可用性,无论什么时候都可以进行读和写操作
Partition:分区忍耐性,对于数据量很大时需要对数据根据某个维度,例如根据用户id将数据划分到不同分区,这样系统伸缩性好,通过增加多台机器就可以解决数据量大到不能使用一台机器能存下的难题,对于主从模式,增加从库并不能解决数据量大的问题,因为从库存放的还是全部的数据,需要将数据分散到不同机器进行存放
以上三个条件不能同时满足,必须要牺牲一个条件来换取另外一个条件,例如不能同时保证可用性和一致性,因为如果需要保证可用性就需要将数据备份到多个机器上,然而不能保证在同步数据过程中其他读请求不会读备份机器,这就会出现数据不一致的问题。
在分布式系统中,可用性是最需要保证的,其次是分区忍耐性,最后是一致性,可以通过补偿事务,业务逻辑来保证数据最终一致性
- 一致性
强一致性:无论什么时候读取数据都能读到相同的数据,当更新或插入数据时返回给客户端失败了,那么一定是没有操作成功,不会出现中间状态,这个在单点数据服务是能保证的,但是如果在分布式数据服务中保证强一致性需要牺牲性能,因为当执行一个更新请求时,必须要等到将数据同步到其他机器时才返回结果
用户一致性:实际上数据服务中的各个副本数据并不一致,但是通过一些补偿操能返回给用户正确的数据
最终一致性:多次请求数据服务时,每次请求结果会不一样,但是经过一个窗口期时最终数据会达到一致的。数据不一致性一般出现在高并发写和更新操作或数据的恢复或集群扩容时
数据服务高可用保证
数据服务可用性保证:第一保证数据有备份,第二保证数据服务down机能够将失效请求转移到其他数据服务器上
- 数据备份(数据冗余)
冷备份和热备份:
冷备份:定时对数据进行备份,缺点就是会丢失一部分数据,从备份的数据恢复需要一定的时间,这段时间内不能提供服务
热备份:每次写入数据时都会同步一份数据到其他服务器上,这里同步可以分为两种,同步和异步方式
同步方式:当写入的数据都成功写入到其他备份的服务器上才响应写请求,为了提高性能可用通过多个线程并行的写入到其他机器上,最终以最耗时的请求为最终处理数据
异步方式: 只给一个主服务上发送写请求,写成功后就返回,然后由主服务同步到其他从服务器上
MySQL采用一主多从方式,对数据库操作请求发到主库中,读取数据操作发到从库中,主库和从库采用binlog 进行同步数据
如果主库挂了同样会导致服务不可用,所以需要再起一个主库,同时也需要将另外一个主库数据同步到该主库,用作冷备份,一旦主库挂了就将其升为主库,接受写请求。
- 失效转移
失效确认
失效转移
数据恢复
软件质量保证
-
网站发布(升级服务)
-
自动化测试
-
代码版本控制 (主干上线,分支上开发版本)
-
自动化部署、火车模型,多阶段确认,上线前测试确认、合并分支确认、预上线确认、正式环境部署确认
-
灰度发布(A/B test) 为了避免当升级新版本时导致整体服务异常,而将整体服务回滚带来的不可用性,采用分批次部署服务,将部分流量引入(一般是在网关切流量或在nginx切流量)到新版本服务器上,等check没有问题后再部署到其他服务器上
数据和系统监控
没有监控的系统犹如没有仪表的汽车
用户行为数据的记录可以成为个人性化推荐基础数据
系统运行状态数据收集以及当系统有一定负载是进行报警