高并发原则
1.1无状态
如果应用设计成无状态的,应用比较容易水平扩展。但是在实际的生产环境中,应用是无状态的,但是配置文件是有状态,例如不同的机房需要访问不同的数据源,此时就需要通过配置文件或配置中心进行指定。
1.2拆分
在系统成立初期,是做一个大而全的系统还是按照功能模块拆分系统,这个根据环境进行权衡,比如在线私塾用户量和订单量不会特别大,开发少,资源有限,这样的情况下,可以考虑做一个大而全的系统;秒杀一类的系统,投入量通常比较大一些,访问量也比较大,我们可以考虑按照功能进行拆分。
拆分主要有如下几种情况:
系统维度:按照系统功能/业务分析进行拆分:如购物车,结算,订单系统等。
功能维度:对一个系统再进行拆分:如优惠劵系统可以拆分成后台劵创建系统,领劵系统,用劵系统等。
读写维度:一个系统中往往有些模块的读大于写,我们此时可以将拆分成读系统和写系统,读的时候我们可以使用缓存提高系统,当写比较大的数据时,我们可以考虑分库分表。
AOP维度:根据访问特征,按照AOP进行拆分,比如,商品详情页可以拆分成CDN,页面渲染系统。CDN本身属于一个AOP系统。
模块维度:比如按照基础或者代码维护进行拆分,基础分库分表,数据库连接池等;代码通常按照三层架构(web,service,dao)进行划分。
1.3服务化
进程内服务--》单机远程服务--》集群手动注册服务--》服务自动发现与注册--》服务的分组/隔离/路由--》服务治理如限流/黑白名单等。
1.4消息队列
消息队列用来解耦一些不需要同步调用的服务或订阅系统自己关注的东西。使用消息队列可以实现服务解耦(一对多消费),异步处理,流量削峰/缓冲等,但是订阅者过多时,单个的消息队列就会成为瓶颈,此时,需要考虑对消息队列进行多个镜像复制。
使用时需要注意生产消息失败,消息消费顺序,消息的重复,事务消息等等。
1.5缓存银弹
浏览器缓存:设置请求的过期时间,如对响应头Expires,Cache-control进行控制,这种机制适用于对实时性要求不高的数据,实时性要求高的不适用,如库存等。
APP客户端缓存:在大促是为了防止流量冲击,可以提前下发(js/css/image等)到客户端进行缓存。
CDN缓存:有些页面,图片,活动页等可以考虑推送到离用户较近的CDN节点,用户获取时就近获取,有两种机制:推送机制和拉取机制等。
1.6数据异构
数据异构:订单分库分表一般按照订单id进行分,如果要查询某个用户的订单列表,则需要聚合多个表的数据才能返回,这样会导致订单表的读性能降低,此时需要异构一套订单表。对于数据异构意义不大的可以考虑使用异步加载,或者合并并发请求。
数据闭环:数据来源太多,影响服务稳定性的因素很多,因此最好的办法就是把使用到的数据进行异构存储,形成数据闭环,通常分为三个步骤:数据异构,数据聚合,前端展示。
数据异构和数据闭环其实是一个概念,目的都是实现数据的自我控制,当其他系统出现问题时不影响自己,或自己出现问题时不影响其他系统,一般通过消息队列来实现数据分发。
1.7并发化
将串行化数据交于多线程并发执行,此时要考虑线程的安全性
高可用原则
2.1降级
对于高可用服务很重要的一个设计就是降级开关,在设计降级开关时,主要依据思路:
1.开关集中化管理:通过推送机制把开关推送到各个应用。
2.可降级的多级读服务:比如服务调用降级为只读本地缓存,只读分布式缓存,只读默认降级数据(如库存状态默认有货)。
3.开关前置化:如架构时Nginx→tomcat,可以将开关前置到Nginx接入层,在Nginx层做开关,请求流量回源后端应用或者只是一小部分流量回源。
4.业务降级:当高并发流量来袭,可以讲一些同步调用改成异步调用。优先处理高优先级数据或特殊特征的数据,合理分配进入系统的流量,以保证系统可用。
2.2限流
限流的目的是防止恶意请求流量,恶意攻击,或者防止流量超出系统峰值
1.恶意请求流量只访问到cache。
2.对于穿透到后端应用的流量可以考虑使用Nginx的limit模块处理。
3.对于恶意ip可使用Nginx deny进行屏蔽。
2.3切流量
1.DNS:切换机房入口
2.HttpDNS:在客户端分配号流量入口,绕过运营商LocalDNS并实现更精准流量调度。
3.LVS/HaProxy:切换故障的Nginx接入层。
4.Nginx:切换故障的应用层。
2.4可回滚
当程序或数据出现问题时,可以通过版本化回滚到最近一版正确的版本,保证程序的正确性
内容来源《亿级流量网站架构核心技术 跟开涛学搭建高可用高并发系统》