1. 高并发原则
1.1 无状态
如果应用的设计是无状态的,那么应用比较容易进行水平扩展。实际生产环境是:应用无状态、配置文件有状态。
1.2 拆分
访问量大,资源充足,可考虑拆分。几种主要的拆分情况:
-
系统维度:按照系统功能/业务拆分。
-
功能维度:对一个系统按照功能拆分。
-
读写维度:根据读写比例特征进行拆分。读的量太大,可用缓存;写的量太大,可分库分表。聚合读取场景,可考虑数据异构拆分系统,将分散在多处的数据聚合到一处存储,以提升系统的性能和可靠性。
-
AOP维度:根据访问特征,按照AOP进行拆分。
-
模块维度:按照基础或者代码维护特征进行拆分。
1.3 服务化
进程内服务—>单机远程服务—>集群手动注册服务—>自动注册和发现服务—>服务的分组/隔离/路由—>服务治理(限流/黑白名单)
1.4 消息队列
消息队列用来解耦一些不需要同步调用的服务,或者订阅一些自己系统关心的变化。使用消息队列可以实现服务解耦(一对多消费)、异步处理、流量削峰/缓冲等。
1.5 数据异构
1.5.1 数据异构
订单分库分表一般按照订单ID进行拆分,如果要查询某个用户的订单列表,则需要聚合多个表的数据后才能返回,这样会导致订单表的读性能很低。此时需要对订单表进行异构,异构一套用户订单表,按照用户ID进行分库分表。
另外,还需要考虑对订单数据进行归档处理,以提升服务的性能和稳定性。
1.5.2 数据闭环
如商品详情页,因为数据来源太多,影响服务稳定性的因素就非常多。因此,最好的办法就是把使用到的数据进行异构存储,形成数据闭环,基本步骤如下:
-
数据异构:通过MQ机制接收数据变更,然后原子化存储到合适的存储引擎,如Redis或者持久化KV存储。
-
数据聚合:数据异构的目的是把数据从多个数据源拿过来,数据聚合的目的是把这些数据做个聚合,这样前端就可以通过一次调用拿到所有数据。此步骤一般存储在KV中。
-
前端展示:前端通过一次或少量几次调用就拿到所需要的数据。
这种方式的好处是数据闭环,任何依赖系统出问题了,还是能正常工作,只是更新会有积压,但是不影响前端展示。
另外,如果一次需要多个数据,那么可以考虑使用HashTag机制把相关的数据聚合到一个实例,如在展示商品详情页时需要使用商品基本信息”p:productId:”和商品规格参数信息”d:productId:”,此时就可以使用冒号中间的productId作为数据分片的Key,这样相同productId的商品相关数据就在同一个实例。
1.6 缓存银弹
-
浏览器端缓存
-
APP客户端缓存
-
CDN(Content Delivery Network)缓存
-
接入层缓存
-
应用层缓存
-
分布式缓存
对于兜底数据或者异常数据,不应该让其缓存,否则用户会在很长一段时间里看到这些数据。
1.7 并发化
改串行为并行。
2. 高可用原则
2.1 降级
对于高可用服务,很重要的一个设计就是降级开关,在设计降级开关时,主要依据如下思路:
1. 开关集中化管理:通过推送机制把开关推送到各个应用。
2. 可降级的多级读服务:比如服务调用降级为只读本地缓存、只读分布式缓存、只读默认降级数据(如库存状态默认有货)。
3. 开关前置化:如架构是Nginx–>tomcat,可以将开关前置到Nginx接入层,在Nginx层做开关,请求流量回源后端应用或者只是一小部分流量回源。
4. 业务降级:当高并发流量来袭,在电商系统大促设计时保障用户能下单、能支付是核心要求,并保障数据最终一致性即可。这样就可以把一些同步调用改成异步调用,优先处理高优先级数据或特殊特征的数据,合理分配进入系统的流量,以保障系统可用。
2.2 限流
限流的目的是防止恶意请求流量、恶意攻击,或者放置流量超出系统峰值。可以考虑如下思路:
1. 恶意请求流量只访问到cache。
2. 对于穿透到后端应用的流量可以考虑使用Ningx的limit模块处理。
3. 对于恶意IP可以使用nginx deny进行屏蔽。
原则是限制流量穿透到后端薄弱的应用层。
2.3 切流量
对于一个大型应用,切流量是非常重要的,比如多机房环境下某个机房挂了,或者某个机架挂了,或者某台服务器挂了,都需要切流量,可以使用如下手段进行切换:
1. DNS
2. HttpDNS
3. LVS/HaProxy
4. Nginx
2.4 可回滚
版本化的目的是实现可审计、可追溯,并且可回滚。当程序或者数据出错,如果有版本化机制,那么久可以通过回滚恢复到最近一个正确的版本,比如事务回滚、代码库回滚、部署版本回滚、数据版本回滚、静态资源版本回滚等。通过回滚机制可以保证系统在某些场景下的高可用。
3. 业务设计原则
3.1 防重设计
例如防止重复支付、重复扣减内存等。
3.2 幂等设计
一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。
3.3 流程可定义
复用流程系统,提供个性化的流程服务。
3.4 状态与状态机
在设计交易订单系统时,会存在正向状态(待付款、待发货、已发货、完成)和逆向状态(取消、退款)等,正向状态和逆向状态应该根据系统的特征来决定要不要分离存储。状态设计时应有状态轨迹,方便用户跟踪当前订单的轨迹并记录相关日志,万一出问题时可回溯问题。
3.5 后台系统操作可反馈
设计后台系统时,考虑效果的可预览、可反馈。
3.6 后台系统审批化
对于有些重要的后台功能需要设计审批流,比如调整价格,并对操作进行日志记录,从而保证操作可追溯、可审计。
3.7 文档和注释
系统发展的最初阶段就应该有文档库(设计架构、设计思想、数据字典/业务流程、现有问题),业务代码合特殊需求都要有注释。
3.8 备份
包括代码和人员的备份。代码主要提交到代码仓库进行管理和备份,代码仓库至少应该具备多版本的功能。人员备份指的是一个系统至少应该有两名开发人员是了解的。
4. 总结
系统设计不仅需要考虑实现业务功能,还要保证系统高并发、高可用、高可靠等。同时还应考虑系统容量规划(流量、容量等)、SLA指定(吞吐量、响应时间、可用性、降级方案等)、监控报警(机器负载、响应时间、可用率等)、应急预案(容灾、降级、限流、隔离、切流量、可回滚等)。
4.1 高并发原则
1. 缓存
2. 异步并发
3. 连接池
4. 线程池
5. 扩容
6. 消息队列
7. 分布式任务
4.2 高可用原则
1. 通过负载均衡和反向代理实现分流。
2. 通过限流保护服务免受雪崩之灾。
3. 通过降级实现部分可用、有损服务。
4. 通过隔离实现故障隔离。
5. 通过合理设置的超时与重试机制避免请求堆积造成雪崩。
6. 通过回滚机制快速修复错误版本。
参考来源: [1] 亿级流量网站架构核心技术.张开涛著
出处:http://blog.csdn.net/foreverling/article/details/77917174