在设计高可用的互联网架构要注意什么?


=Start=

缘由:

在答辩的时候被问到的一个问题,当时想的太少,回答的比较磕绊,虽然重点好像都有提到,但是感觉不够系统,觉得可以简单整理一下,常读常新,也方便之后添加更多的内容。

正文:

参考解答:
1、设计层面
如果可能的话,在最初设计层面就应该根据实际并发/响应时间要求来考虑,即便初始的流量比较小(避免后期切换/重做成本高,但是也要考虑前期快速上线的需求)。
# 处理流程设计
简单可依赖
# 底层框架使用(也需要考虑团队的熟悉程度、学习成本)
Redis/Tair
MQ
Thrift/RPC/…
SpringBoot/Netty/…
2、实现层面
重点代码交叉review
上线前性能测试
3、部署层面
异地、多机房、分布式部署
最好能有一键流量切换功能
4、监控层面
日志打点要满足需求(异步&不落盘)
相关监控要到位(请求量、服务器监控、存储监控、业务健康性监控)
5、操作层面
常规操作SOP
异常处理SOP(扩容、降级、回滚)
参考链接:

=END=

,

《 “在设计高可用的互联网架构要注意什么?” 》 有 43 条评论

  1. 小团队互联网项目开发之备忘
    https://blog.devopszen.com/development_notes
    `
    近期Web项目的开发和运营的经验,以下几条适合小型团队在资源和时间都有限的情况下做高效开发:

    1. 快速开发和迭代
    应该在最短时间内验证一个feature或者一个想法行得通还是不容易实现。这样还有时间进行系统的重新设计。最先验证feature中的关键点是否可行,再将所有关键点进行串联,和系统整合。

    2. 提早进入运营和市场
    我们都工作在互联网时间,每天互联网都在发生翻天覆地的变化,不进则退。同样的创意,世界上有很多团队在把它变成产品。

    3. 高效运行
    将现有系统尽可能的做得快速运行,减少数据冗余。以备以后需求增长中执行速度变慢。

    4. 容错和并行化
    每个请求,数据返回都可能失败或成功,需要不定的时间长度。所以系统要尽可能做到并行,容错。互联网项目尤其是这样,网络环境不是可信环境。

    5. 易于维护和管理
    项目中期应该做到容易监控和维护。
    `
    有关开发效率和协作的几点
    https://blog.devopszen.com/team_performance

  2. 互联网系统可靠性基础:正确的异常处理
    https://blog.devopszen.com/exception
    `
    Try catch 的内部实现
    异常必然发生
    异常处理的性能考虑
    几个理念:Fail fast vs Retry vs Let it crash
    异常和错误的类型
    守门员:全局异常处理
    异常处理总结和一些原则
    一些有用的资料
    `

  3. 07 | 准备Plan B:如何设计兜底方案?
    https://time.geekbang.org/column/article/40744
    `
    高可用建设应该从哪里着手?
    具体来说,系统的高可用建设涉及架构阶段、编码阶段、测试阶段、发布阶段、运行阶段,以及故障发生时。接下来,我们分别看一下。
    1、架构阶段:架构阶段主要考虑系统的可扩展性和容错性,要避免系统出现单点问题。例如多机房单元化部署,即使某个城市的某个机房出现整体故障,仍然不会影响整体网站的运转。
    2、编码阶段:编码最重要的是保证代码的健壮性,例如涉及远程调用问题时,要设置合理的超时退出机制,防止被其他系统拖垮,也要对调用的返回结果集有预期,防止返回的结果超出程序处理范围,最常见的做法就是对错误异常进行捕获,对无法预料的错误要有默认处理结果。
    3、测试阶段:测试主要是保证测试用例的覆盖度,保证最坏情况发生时,我们也有相应的处理流程。
    4、发布阶段:发布时也有一些地方需要注意,因为发布时最容易出现错误,因此要有紧急的回滚机制。
    5、运行阶段:运行时是系统的常态,系统大部分时间都会处于运行态,运行态最重要的是对系统的监控要准确及时,发现问题能够准确报警并且报警数据要准确详细,以便于排查问题。
    6、故障发生:故障发生时首先最重要的就是及时止损,例如由于程序问题导致商品价格错误,那就要及时下架商品或者关闭购买链接,防止造成重大资产损失。然后就是要能够及时恢复服务,并定位原因解决问题。

    为什么系统的高可用建设要放到整个生命周期中全面考虑?因为我们在每个环节中都可能犯错,而有些环节犯的错,你在后面是无法弥补的。例如在架构阶段,你没有消除单点问题,那么系统上线后,遇到突发流量把单点给挂了,你就只能干瞪眼,有时候想加机器都加不进去。所以高可用建设是一个系统工程,必须在每个环节都做好。
    `

  4. 从拼多多系统漏洞, 阿里专家谈码农如何防背锅
    https://mp.weixin.qq.com/s/vx61KfZhkiKXHYSsJ52J_w
    `
    处理故障三板斧
    1-止血,止血,止血
    2-复盘
    3-改进

    避免故障三板斧
    1. 发布前,确保有效的数字化监控
    2. 发布时,逐步灰度
    3. 发布后,一键回滚的能力

    理解产品周期与线上故障
    技术故障,在产品的初期,到发展期,到成熟期,到半衰期,是有着不一样的影响效力和重视程度。
    1、产品初期:一切为了快速试错+反馈
    2、产品发展期:故障的快速处理开始被要求
    3、产品成熟期:线上故障几乎是0容忍态度
    4、产品半衰期:既要业务创新,又要技术稳定

    敬畏每一次线上操作变更的风险,落实发布能够灰度、数据大盘监控、业务数据指标是否符合预期。

    加强有效报警,从对敬畏故障的思想做起,在基础能力建设完善的基础基础上,未来实现“无人盯守,发现问题,自动告警,风险预测,自动回滚”,让devOps从经常要搞到凌晨发布,无法安心入睡的困境中解救出来,减少一线拧螺丝人员的背锅次数,减少系统释放处来的背锅HC机会,最终实现已知领域内的线上功能服务的高可用。
    `

  5. 分布式架构知识体系
    https://mp.weixin.qq.com/s/9xINMH9tJlmsjH6QdUPFxQ
    `
    1、何为分布式何为微服务?
    2、为什么需要分布式?
    3、分布式核心理论基础,节点、网络、时间、顺序,一致性?
    4、分布式是系统有哪些设计模式?
    5、分布式有哪些类型?
    6、如何实现分布式?
    `

  6. 互联网架构三板斧之并发
    https://mp.weixin.qq.com/s/87JWlUoc03UZy2ar3p4NlA
    `
    对大流量系统的数据做分层校验也是最重要的设计原则,所谓分层校验就是对大量的请求做成“漏斗”式设计,在不同层次尽可能把无效的请求过滤,“漏斗”的最末端才是有效的请求,要达到这个效果必须对数据做分层的校验,下面是一些原则:
    1、先做数据的动静分离
    2、将90%的数据缓存在客户端浏览器
    3、将动态请求的读数据Cache在Web端
    4、对读数据不做强一致性校验
    5、对写数据进行基于时间的合理分片
    6、对写请求做限流保护
    7、对写数据进行强一致性校验
    `

  7. 如果20万用户同时访问一个热点缓存,如何优化你的缓存架构?【石杉的架构笔记】
    https://mp.weixin.qq.com/s/RqBla4rg8ut3zEBKhyBo1w
    `
    (1)为什么要用缓存集群
    (2)20万用户同时访问一个热点缓存的问题
    (3)基于流式计算技术的缓存热点自动发现
    (4)热点缓存自动加载为JVM本地缓存
    (5)限流熔断保护
    (6)总结
    `

  8. 四种软件架构:Serverless架构、微服务架构、分布式架构、单体架构
    https://mp.weixin.qq.com/s/5CUm44VjXRCoxagYpMRQBQ
    `
    一、单体架构
    单体架构比较初级,典型的三级架构,前端(Web/手机端)+中间业务逻辑层+数据库层。这是一种典型的Java Spring mvc或者Python Django框架的应用。

    单体架构的应用比较容易部署、测试, 在项目的初期,单体应用可以很好地运行。然而,随着需求的不断增加, 越来越多的人加入开发团队,代码库也在飞速地膨胀。慢慢地,单体应用变得越来越臃肿,可维护性、灵活性逐渐降低,维护成本越来越高。下面是单体架构应用的一些缺点:

    复杂性高: 以一个百万行级别的单体应用为例,整个项目包含的模块非常多、模块的边界模糊、 依赖关系不清晰、 代码质量参差不齐、 混乱地堆砌在一起。可想而知整个项目非常复杂。 每次修改代码都心惊胆战, 甚至添加一个简单的功能, 或者修改一个Bug都会带来隐含的缺陷。

    技术债务: 随着时间推移、需求变更和人员更迭,会逐渐形成应用程序的技术债务, 并且越积 越多。“ 不坏不修”, 这在软件开发中非常常见, 在单体应用中这种思想更甚。 已使用的系统设计或代码难以被修改,因为应用程序中的其他模块可能会以意料之外的方式使用它。

    部署频率低: 随着代码的增多,构建和部署的时间也会增加。而在单体应用中, 每次功能的变更或缺陷的修复都会导致需要重新部署整个应用。全量部署的方式耗时长、 影响范围大、 风险高, 这使得单体应用项目上线部署的频率较低。 而部署频率低又导致两次发布之间会有大量的功能变更和缺陷修复,出错率比较高。

    可靠性差: 某个应用Bug,例如死循环、内存溢出等, 可能会导致整个应用的崩溃。

    扩展能力受限: 单体应用只能作为一个整体进行扩展,无法根据业务模块的需要进行伸缩。例如,应用中有的模块是计算密集型的,它需要强劲的CPU; 有的模块则是IO密集型的,需要更大的内存。 由于这些模块部署在一起,不得不在硬件的选择上做出妥协。

    阻碍技术创新: 单体应用往往使用统一的技术平台或方案解决所有的问题, 团队中的每个成员 都必须使用相同的开发语言和框架,要想引入新框架或新技术平台会非常困难。

    二、分布式应用
    该架构相对于单体架构来说,这种架构提供了负载均衡的能力,大大提高了系统负载能力,解决了网站高并发的需求。另外还有以下特点:
    降低了耦合度:把模块拆分,使用接口通信,降低模块之间的耦合度。
    责任清晰:把项目拆分成若干个子项目,不同的团队负责不同的子项目。
    扩展方便:增加功能时只需要再增加一个子项目,调用其他系统的接口就可以。
    部署方便:可以灵活的进行分布式部署。
    提高代码的复用性:比如service层,如果不采用分布式rest服务方式架构就会在手机wap商城,微信商城,pc,android,ios每个端都要写一个service层逻辑,开发量大,难以维护一起升级,这时候就可以采用分布式rest服务方式,公用一个service层。

    缺点 : 系统之间的交互要使用远程通信,接口开发增大工作量,但是利大于弊。

    三、微服务架构
    微服务架构,主要是中间层分解,将系统拆分成很多小应用(微服务),微服务可以部署在不同的服务器上,也可以部署在相同的服务器不同的容器上。当应用的故障不会影响到其他应用,单应用的负载也不会影响到其他应用,其代表框架有Spring cloud、Dubbo等。

    四、Serverless架构
    Serverless架构能够让开发者在构建应用的过程中无需关注计算资源的获取和运维,由平台来按需分配计算资源并保证应用执行的SLA(服务等级协议),按照调用次数进行计费,有效的节省应用成本。

    目前微服务架构在四种架构中处于主流地位,很多应用第一、第二种架构的企业也开始慢慢转向微服务架构。到目前为止微服务的技术相对于二三年前已经比较成熟,第四种架构将是未来发展的一种趋势。如果你喜欢我的文章,欢迎关注我的简书,后续我将教会大家利用spring cloud和docker轻松愉快的构建微服务。
    `

  9. 高并发编程知识体系
    https://mp.weixin.qq.com/s/qaj37YYxz7afD-WfAZeN8Q
    `
    1.问题
    1、什么是线程的交互方式?
    2、如何区分线程的同步/异步,阻塞/非阻塞?
    3、什么是线程安全,如何做到线程安全?
    4、如何区分并发模型?
    5、何谓响应式编程?
    6、操作系统如何调度多线程?

    2.关键词
    同步,异步,阻塞,非阻塞,并行,并发,临界区,竞争条件,指令重排,锁,amdahl,gustafson

    3.全文概要
    上一篇我们介绍分布式系统的知识体系,由于单机的性能上限原因我们才不得不发展分布式技术。那么话说回来,如果单机的性能没能最大限度的榨取出来,就盲目的就建设分布式系统,那就有点本末倒置了。而且上一篇我们给的忠告是如果有可能的话,不要用分布式,意思是说如果单机性能满足的话,就不要折腾复杂的分布式架构。如果说分布式架构是宏观上的性能扩展,那么高并发则是微观上的性能调优,这也是上一篇性能部分拆出来的大专题。本文将从线程的基础理论谈起,逐步探究线程的内存模型,线程的交互,线程工具和并发模型的发展。扫除关于并发编程的诸多模糊概念,从新构建并发编程的层次结构。
    `

  10. 朱晔的互联网架构实践心得S1E9:架构评审一百问和设计文档五要素
    https://mp.weixin.qq.com/s/iRU4NLK9DEHacix1qNX8Yw
    `
    组件选型
    · 为什么选A不选B呢?
    · A不是开源的,出了问题怎么办?
    · B虽然是开源的,但是是Erlang写的,公司没人能看懂怎么办?
    · C我看待解决的Issues还有很多,有没有去了解过?
    · 这个组件在性能方面你是否了解过?
    · 开源的免费版本不支持集群怎么办?
    · 如果彻底要自己写这个组件有没有可能性?

    性能
    · 我们需求的TPS、QPS和RT是多少?
    · 整体设计上会做到的TPS、QPS和RT是多少?
    · 随着数据量的增大系统性能会不会出现明显问题?
    · 系统哪个环节会是最大的瓶颈?
    · 是否打算做压力测试,压力测试方案是怎么样的?
    · 怎么提高前端用户的访问流畅性?

    可伸缩性
    · 每一个环节是否都是可以横向扩展的?
    · 扩容需要怎么做手动还是自动?
    · 数据库不能横向扩展怎么办?
    · 纵向扩展有多少效果?
    · 横向扩展是否是线性的?
    · 扩展后是否可以提高响应速度?

    灵活性
    · 是否有了解过产品层面以后会怎么发展?
    · 模块A是否能拆分出去独立为其它业务服务?
    · 模块B是否可以替换为另一种第三方数据源?
    · 如果流程有变,需要多大的工作量来适应?
    · 业务是否可以做到可配?

    可扩展性
    · 为什么A和B都有差不多的逻辑?
    · 是否考虑到了A业务的实现以后还有B的可能性?
    · 如果现在有两种策略以后扩展到了八种策略怎么做?
    · 以后是否可以把这个业务的H5前端适配到PC?

    可靠性
    · 是否架构中有单点?
    · 故障转移是怎么实现的?
    · 集群内部故障转移需要多久?
    · MQ或存储出现问题的时候系统会怎么样?
    · MQ或存储出现问题又恢复了系统是否会自己恢复?
    · 是否考虑过异地故障转移的方案?
    · 是否考虑过多活的方案?
    · 是否有数据丢失的可能性?
    · 数据丢失后是否可以恢复?
    · 系统彻底挂了对其它业务的影响是什么?
    · 系统彻底挂了是否可以有线下的方式走业务?

    安全性
    · 是否彻底避免SQL注入和XSS?
    · 是否做了风控策略?
    · 是否有防刷保护机制?
    · 数据库拖库了会怎么样?
    · 是否有数据泄露的可能性?
    · 数据的权限怎么控制的?
    · 功能的权限是怎么控制的?
    · 是否做了日志审计?
    · 受到了DDOS攻击怎么办?
    · 数据传输是否加密验签?

    兼容性
    · 老的系统打算怎么办?
    · 怎么进行新老系统替换?
    · 新老系统能否来回切换?
    · 别的系统怎么连接你这套新服务?
    · 上下游依赖是否梳理过,影响范围多大?
    · 上下游改造的难度怎么样?
    · 上下游改造有排期吗?
    · 上下游改造的计划和通知时间确定了吗?
    · 使用了新的数据源数据怎么迁移?
    · 使用了新的技术老项目开发能否适应?

    弹性处理
    · 这个数据重复消费会怎么样?
    · 这个接口重复调用会怎么样?
    · 是否考虑了服务降级?哪些业务支持降级?
    · 是否考虑了服务熔断?熔断后怎么处理?
    · 是否考虑了服务限流?限流后客户端表现怎么样?
    · 队列爆仓会怎么样?
    · 是否考虑了隔离性?

    事务性
    · 这段业务由谁保证事务性?
    · 数据库事务回滚后会怎么样?
    · 服务调用了失败怎么办?
    · 队列补偿怎么做的?
    · 服务调用补偿怎么做的?
    · 数据补偿实现最终一致需要多久?
    · 在数据不完整的时候用户会感知到吗?

    可测试性
    · 测试环境和线上的差异多大?
    · 是否支持部署多套隔离的测试环境?
    · 是否打算做单元测试,覆盖率目标是多少?
    · 测试黑盒白盒工作量的比例是怎么样的?
    · 是否支持接口层面的自动化测试?
    · 是否有可能做UI自动化测试?
    · 压测怎么造数据?
    · 是否可以在线上做压测?
    · 线上压测怎么隔离测试数据?
    · 是否有测试白名单功能?

    可运维性
    · 每一个组件对服务器哪方面的压力会最大?
    · 重新搭建整套系统最快需要多少时间?
    · 系统是否可以完全基于源代码构建?
    · 系统是否有初始化或预热的环节?
    · 系统里哪些环节需要人工参与?
    · 数据是否需要定期归档处理?
    · 会不会有突发的数据量业务量增大?
    · 随着时间的推移如果压力保持不变的话系统需要怎么来巡检和维护?
    · 怎么在容器里进行部署?

    监控
    · 业务层面哪些指标需要监控和报警?
    · 应用层面系统内部是否有暴露了一些指标作监控和报警?
    · 系统层面使用的中间件和存储是否有监控报警?
    · 是否所有环节都接入了全链路跟踪?
    · 出现报警的时候应该由谁来处理?
    · 每一个模块是否有固定的主要和次要负责人?
    · 有没有可能系统出了问题无法通过监控指标体现?
    · 哪些指标需要上大屏由监控进行7*24监控?
    `

  11. 朱晔的互联网架构实践心得S2E6:浅谈高并发架构设计的16招
    https://mp.weixin.qq.com/s/mts-LDlhjACDkvqTU9u9Zw
    `
    标题中的高并发架构设计是指设计一套比较合适的架构来应对请求、并发量很大的系统,使系统的稳定性、响应时间符合预期并且能在极端的情况下自动调整为相对合理的服务水平。一般而言我们很难用通用的架构设计的手段来解决所有问题,在处理高并发架构的时候也需要根据系统的业务形态有针对性设计架构方案,本文只是列出了大概可以想到一些点,在设计各种方案的时候无非是拿着这些点组合考虑和应用。 有很多高并发架构相关的文章都是在介绍具体的技术点,本文尝试从根源来总结一些基本的方法,然后再引申出具体的实现方式或例子。下面是本文会介绍的16个方面的大纲:

    减少请求数量:
      合并请求
      边缘加速
    提升处理性能:
      空间换时间
      任务并行化
      处理异步化
      合适的存储
      更快的网络
    增加处理能力:
      模块拆分
      负载均衡
      分区处理
      纵向扩展
    稳定性和弹性:
      压测
      隔离
      限流
      熔断
      降级

    总结一下,对于高并发应用如何去考虑性能优化,说白了就这么几个思路:

    1、要么是尽可能通过让并发别这么大,有的时候真没必要一拥而上造成人为的大并发。
    2、要么是尽可能优化代码、存储、网络,越简单,操作需要的CPU、IO、内存、网络资源越少在一定的服务器资源下就越可能应对更多的并发。
    3、要么就是通过扩展资源,扩展服务器来提高处理能力。
    4、最后一招就是在因为并发过大不稳定的时候系统需要启用一定的应急手段开启自保,别人工系统被流量压垮彻底挂了。
    `

  12. 混沌工程 – 软件系统高可用、弹性化的必由之路
    https://tech.youzan.com/chaosmonkey/
    `
    混沌工程的定义:
    通过观察分布式系统在受控的故障注入测试中的行为变化发掘系统弱点,并针对性的改进,从而提高系统可靠性,建立系统抵御失控条件的能力的信心。所以,混沌工程并不是一个新概念,常见的异地容灾测试也是混沌工程的一种应用。

    混沌工程的一般实施步骤:
    寻找一些系统正常运行状态下的可度量指标,作为基准的“稳定状态”
    假设实验组和对照组都能继续保持这个“稳定状态”
    对实验组进行事件注入,如服务器崩溃、硬盘故障、网络连接断开等等
    比较实验组和对照组“稳定状态”的差异,推翻上述第2条的假设
    如果混沌工程实施下来两者的“稳定状态”一致,则可以认为系统应对这种故障是弹性的,从而对系统建立更多信心。相反的,如果两者的稳定状态不一致,那我们就找到了一个系统弱点,从而可以修复它,提高系统可靠性。

    混沌工程的理想原则:
    1)根据“稳定状态下系统的特征”做一个假设
    2)事件是现实世界真的可能发生的
    3)在生产环境跑
    4)持续集成
    5)最小化影响范围

    上面是最理想情况下的混沌工程,现实中我们需要根据现有软件成熟度有阶段的实施混沌:
    阶段一:分布式系统弹性化一般
    阶段二:分布式系统弹性化成熟
    `

  13. 这样的高可用,我不要!
    https://mp.weixin.qq.com/s/UQS5Pd6Dvcvm5lVuzsIorQ
    `
    前不久,朋友的公司,出现了比较大的故障。故障引起的原因也比较好解释,因为使用了ActiveMQ的高可用级别(M-S架构,双写完成ACK),结果在高峰期间,造成了生产端消息拥堵,诸多请求无法落地,数据错乱。

    据他说,他们的应用,级别比电信应用还要高(牛皮一定要吹),所以消息系统要求一条消息都不能丢。他做到了,但是服务不能用了。

    高可用是个伪命题,虽然有CAP等耳熟能详的理论支持,还是有很多人陷入了这个误区,包括技术决策人。架构作为全局把控人,能出现这样的错误,纯属低级。下面,是我自己对高可用的一点思考。

    高可用不是组件高可用,是业务高可用
    业务先能用,然后讲可靠
    主要流程不能阻断,可靠性降级
    主要流程不能阻断,可靠性降级
    数据不能丢,我还能找回来

    别把高可用挂在嘴上,那很sb
    分布式系统是个复杂的整体,不要以偏概全,搞定了某个组件并不等于搞定真个系统。领导会认为这样,你不能。
    `

  14. 没有预热,不叫高并发,叫并发高
    https://mp.weixin.qq.com/s/IVFf2B7UPY2XaJUgAM3sjg
    `
    大家都知道,高并发系统有三把斧子:缓存、熔断和限流。但还有一把斧子,经常被遗忘在角落里,郁郁不得志,那就是预热。

    一、DB重启后,瞬间死亡
    一个高并发环境下的DB,进程死亡后进行重启。由于业务处在高峰期间,上游的负载均衡策略发生了重分配。刚刚启动的DB瞬间接受了1/3的流量,然后load疯狂飙升,直至再无响应。

    原因就是:新启动的DB,各种Cache并没有准备完毕,系统状态与正常运行时截然不同。可能平常1/10的量,就能够把它带入死亡。

    二、服务重启后,访问异常
    另外一个常见的问题是:我的一台服务器发生了问题,由于负载均衡的作用,剩下的机器立马承载了这些请求,运行的很好。当服务重新加入集群时,却发生了大量高耗时的请求,在请求量高的情况下,甚至大批大批的失败。

    引起的原因大概可以归结于:

    1、服务启动后,jvm并未完全准备完毕,JIT未编译等。
    2、应用程序使用的各种资源未准备就绪。
    3、负载均衡发生了rebalance。

    这两个问题,都是没有做好预热

    Warm Up,即冷启动/预热的方式。当系统长期处于低水位的情况下,流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过”冷启动”,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。

    通过比较,我们发现,最靠谱的方式还是进行编码,将warmup逻辑集成在客户端。这个工作可能是痛苦的、漫长的,但结局是美好的。
    当然也可以通过“摘除nginx->修改权重->reload nginx”的方式。有时很有效但不总是有效,通常很放心但不总是放心。
    一切随你。毕竟没有前戏直奔主题,那叫鲁莽。
    `

  15. 开发更高质量的服务
    http://vearne.cc/archives/39164
    `
    1.引言
    产品要求的功能都都开发完了,但这并不是终结。怎么样做才能让我们的服务具有更好的质量。
笔者结合自己的遇到的问题和工作中的经验,并以提问的方式,给读者一点点建议
    2. 提问
    重要性不分先后
    2.1 如果服务器重启,服务是否能自动拉起?
    2.2 如果程序异常退出,服务是否能够自动拉起?
    2.3 如果程序异常退出,能够自动拉起,那么你怎么知道服务是否发生了重启?
    2.4 如果是web服务,QPS是多少?每个URL的QPS是多少?
    峰值是多少?一般在什么时间点触发?
每种URL的请求量是否合理?
    2.5 如果是web服务,每个请求的响应时间是多少?TP90?TP99分别是多少?
    2.6 异常请求(比如HTTP非200的比例是多少?)什么样的比例是合理的?为什么?
    2.7 如果是多实例部署,那么整个系统的承载极限是多少?如果达到了极限,瓶颈在哪儿(木桶原理中所谓的短板)
    2.8 服务都有哪些依赖项(微服务/数据库/文件系统)
    其中哪些是无状态的,哪些是弱状态的,哪些是强状态的。这些外部服务和系统,是否已经做到高可用?能否做到快速扩容?
    2.9 服务消耗的带宽多少?是否有可能达到带宽上限
    如果是面向公网的服务,请求是否已经进行了压缩?
    2.10 服务在部署上,是否已经做到了二地三机房
    每个地区的网络线路,是否能做到2套或2套以上
(防止光纤被挖断的情况)
    2.11 DNS服务是否能够对后端服务进行探活,自动修改域名的解析列表
    2.12 部署是否实现了自动化
    如果服务需要紧急扩容,该怎么做?
基于docker的容器化方案,还是ansible脚本?
    2.13 文档是否完整,文档是否能与代码保持一致
    2.14 如果是比较复杂的业务系统,是否有完整的自动化测试脚本
    2.15 如果使用了数据库,比如用到了Redis/MySQL
    Redis连接池和MySQL连接池,是否已经打满(达到最大的poolSize)
打满之后,程序是会等待,还是报错?
    2.16 如果使用了Redis,每次Redis操作的耗时是多少?TP90?TP99?
    有没有慢查询?这些慢查询是否合理?
    2.17 如果使用了MySQL,SQL是否做过审核
    哪些表的操作频率最高?那种类型的操作最多?
有没有慢查询?这些慢查询是否合理?
有没有联表过多的查询?
    2.18 如果使用了cache,cache的命中率是多少?
    cache会不会与数据库存储不一致,不一致是否可以容许
    2.19 如果使用了负载均衡,负载均衡与服务之间是长连接吗?
    如果服务和其它服务有交互,他们之间是长连接吗?
    2.20 服务所在机器CPU负载怎么样?连接数高吗?
    是否有大量的TIME_WAIT和CLOSE_WAIT
    2.21 是否做了tracing
    2.22 是否记录了access log
    2.23 服务是否能够优雅退出?
    2.24 服务如果是异常退出,是否会造成数据不一致?
    如果有可能造成不一致,那么如何发现这种不一致?有没有对应修复的策略
比如在交易系统中的定期对账
    2.25 这个服务中,哪些部分是最核心的,是否能做熔断降级处理
    比如一个新闻客户端,如果出现服务出现故障,可以降级为新闻只读,但是无法评论
    2.26 如果是API服务,有没有对请求做超时处理
    防止请求一直阻塞。
    2.27 如果调用方是APP,那么是否在APP中,埋有探针,以便日后分析排障
    2.28 数据库有没有定期备份?
    如果已经做了备份,是否是备份在异构的数据库中
    2.29 如果是API服务,是否有请求频率限制
    如果有是按照用户维度,还是按照IP维度来限制?
    `

  16. 如何健壮你的后端服务?
    https://www.cnblogs.com/LBSer/p/4753112.html
    `
    “怀疑第三方,防备使用方,做好自己”

    对每一个程序员而言,故障都是悬在头上的达摩克利斯之剑,都唯恐避之不及,如何避免故障是每一个程序员都在苦苦追寻希望解决的问题。对于这一问题,大家都可以从需求分析、架构设计 、代码编写、测试、code review、上线、线上服务运维等各个视角给出自己的答案。本人结合自己两年有限的互联网后端工作经验,从某几个视角谈谈自己对这一问题的理解,不足之处,望大家多多指出。

    我们大部分服务都是如下的结构,既要给使用方使用,又依赖于他人提供的第三方服务,中间又穿插了各种业务、算法、数据等逻辑,这里面每一块都可能是故障的来源。如何避免故障?我用一句话概括,“怀疑第三方,防备使用方,做好自己”。

    1 怀疑第三方
    1.1 有兜底,制定好业务降级方案
    1.2 遵循快速失败原则,一定要设置超时时间
    1.3 适当保护第三方,慎重选择重试机制

    2 防备使用方
    2.1 设计一个好的api(RPC、Restful),避免误用
    2.2 流量控制,按服务分配流量,避免滥用

    3 做好自己
    3.1 单一职责原则
    3.2 控制资源的使用
    3.2.1 CPU资源怎么限制?
    3.2.2 内存资源怎么限制?
    3.2.3 网络资源怎么限制?
    3.2.4 磁盘资源怎么限制?
    3.3 避免单点
    `

  17. 【前端词典】输入 URL 到展现涉及的缓存环节
    https://mp.weixin.qq.com/s/zmUYi1IL_ZJy3t8brHtI-A
    `
    # 不一定都对,但可以当做思路扩展的一种方式方法:

    地址栏网址缓存
    检查 HSTS 预加载列表
    DNS 缓存
    ARP(地址解析协议)缓存
    TCP 发送缓冲区 & 接收缓冲区
    HTTP 请求缓存( CDN 节点缓存、代理服务器缓存、浏览器缓存、后端动态计算结果缓存等 )
    `

  18. 【最佳实践】如何优雅的进行重试
    https://mp.weixin.qq.com/s/GNdCB7QzAtjSKm0-8K1v-w
    `
    本文由浅入深的对多种重试的姿势进行了360度无死角教学,从最简单的手动重试,到使用静态代理,再到JDK动态代理和CGLib动态代理,再到Spring AOP,都是手工造轮子的过程,最后介绍了两种目前比较好用的轮子,一个是Spring Retry,使用起来简单粗暴,与Spring框架天生搭配,一个注解搞定所有事情,另一个便是Guava Retry,不依赖于Spring框架,自成体系,使用起来更加灵活强大。

    个人认为,大部分场景下,Spring Retry提供的重试机制已经足够强大,如果不需要Guava Retry提供的额外灵活性,使用Spring Retry就很棒了。当然,具体情况具体分析,但没有必要的情况下,不鼓励重复造轮子,先把别人的轮子研究清楚再想想还用不用自己动手。

    本文到此就告一段落了,又用了一天的时间完成了完成了一篇文章,写作的目的在于总结和分享,我相信最佳实践是可以总结和积累下来的,在大多数场景下都是适用的,这些最佳实践会在逐渐的积累过程中,成为比经验更为重要的东西。因为经验不总结就会忘记,而总结出来的内容却不会被丢失。
    `

  19. 互联网架构三板斧之并发
    https://mp.weixin.qq.com/s/UFy_FWypcOS_szHTmgsChg
    `
    第一板斧:活下来 [Stability]
    稳定性实践笔者印象比较深的有2篇内容,一是由淘宝小邪在2011年分享的[淘宝稳定性实践]。

    第二板斧:简单可扩展(scalability)
    啥叫可扩展,就是可以不断加资源以达成更大容量,支撑更高的并发、迎接更多用户。这里的资源可以是应用服务器,也可以是数据库服务器,或者是缓存服务器。

    第三板斧:拦河大坝、去并发
    为啥要拦?很简单,用户很热情(感性),但系统必须得理性!就3个苹果手机,凭啥让几十万人都涌入柜台!

    对大流量系统的数据做分层校验也是最重要的设计原则,所谓分层校验就是对大量的请求做成“漏斗”式设计,如上图所示:在不同层次尽可能把无效的请求过滤,“漏斗”的最末端才是有效的请求,要达到这个效果必须对数据做分层的校验,下面是一些原则:
    1、先做数据的动静分离
    2、将90%的数据缓存在客户端浏览器
    3、将动态请求的读数据Cache在Web端
    4、对读数据不做强一致性校验
    5、对写数据进行基于时间的合理分片
    6、对写请求做限流保护
    7、对写数据进行强一致性校验

    将90%的数据缓存在客户端浏览器,将动态请求的读数据cache在web端,还是不够的。在大秒的过程中,存在极端情况,就是请求超过单key所在server的QPS能力。

    解决并发有1种基本办法: 分拆!而分拆有两种拆法,
    1、拆资源
    一是把资源(resource)拆了,著名的比如ConcurrentHashMap,拆成了16个桶,并发能力大大提高。
    2、拆基础数据
    在红包应用中,如果还依赖一个共同的基础数据,也可以把这个基础数据拆成多个cell。

    在第三板斧中又有分层拦截、多级缓存、数据近端、分拆锁、预处理、异步化及队列等pattern。学习原则:灵活运用,不尽信经验。
    `

  20. 18个最可能限制系统扩展能力的瓶颈,警惕!!!
    https://mp.weixin.qq.com/s/YqP07IxeM2K8BEeT76JzmA
    `
    1. 二阶提交
    2. 串行处理
    3. 内存不足
    4. 监控和指标不足
    5. 日志不足
    6. 数据库单点
    7. 把数据库当作队列
    8. 使用数据库全文检索
    9. ORM
    10. 没有仪表盘
    11. 没有代码仓库或者版本控制
    12. 单点问题
    13. 预览模式缺失
    14. 缺少沟通
    15. 缺乏文档
    16. 缺少故障演练
    17. 鲁莽行为
    18. 日益增长的技术债
    `
    http://highscalability.com/blog/2013/8/28/sean-hulls-20-biggest-bottlenecks-that-reduce-and-slow-down.html

  21. 注意!开发可伸缩系统必须遵守这11个软件设计原则
    https://mp.weixin.qq.com/s/jhruPpGCdT5VYx-ZHCPrpg
    `
    01简单
    02低耦合
    03DRY-不要重复自己
    04基于约定的编程
    05画架构图
    06单一职责
    07开闭原则
    08依赖注入
    09控制反转
    10为伸缩而设计
    11自愈设计

    # 总结
    不管你是软件工程师、开发组长、技术经理、架构师等,软件设计原则对你都是非常重要的!
    本文简要讲述了:简单、低耦合、不要重复自己DRY、基于约定编程、画架构图、单一职责、开闭原则、依赖注入、控制反转、为伸缩而设计、自愈设计等11个软件设计原则。
    以上11个软件设计原则,会帮助你更好的开发出一个可伸缩的系统。
    `

  22. 容错,高可用和灾备
    http://www.ruanyifeng.com/blog/2019/11/fault-tolerance.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io
    `
    # 容错(fault tolerance)指的是, 发生故障时,系统还能继续运行。
    容错的目的是,发生故障时,系统的运行水平可能有所下降,但是依然可用,不会完全失败。

    # 高可用(high availability)指的是, 系统能够比正常时间更久地保持一定的运行水平。
    汽车的备胎就是一个高可用的例子。如果没有备胎,轮胎坏了,车就开不久了。备胎延长了汽车行驶的可用时间。
    注意,高可用不是指系统不中断(那是容错能力),而是指一旦中断能够快速恢复,即中断必须是短暂的。如果需要很长时间才能恢复可用性,就不叫高可用了。上面例子中,更换备胎就必须停车,但只要装上去,就能回到行驶状态。

    # 灾备(又称灾难恢复,disaster recovery)指的是, 发生灾难时恢复业务的能力。
    灾备的目的就是,保存系统的核心部分。一个好的灾备方案,就是从失败的基础设施中获取企业最宝贵的数据,然后在新的基础设施上恢复它们。注意,灾备不是为了挽救基础设置,而是为了挽救业务。

    容错:发生故障时,如何让系统继续运行。
    高可用:系统中断时,如何尽快恢复。
    灾备:系统毁灭时,如何抢救数据。
    `

  23. 设计高性能高并发网络系统需考虑哪些因素(万字长文)
    https://mp.weixin.qq.com/s/aE0Q0syOO0mThn2_pBBKHw
    `
    本文主要从如何实现高并发、高性能系统角度,剖析网络应用架构演进过程中,解决的那些关键点,并找到一些规律。也可指导我们构建高并发、高性能系统时,应该注意哪些环节。

    – 如何更有效的利用单机资源?开源软件在高性能、高并发中做了哪些实践。
    – 如何在高并发前提下,利用跨机器远程调用提升并发及“性能”。分布式服务如何拆分,怎么拆分才能达到高性能高可用,并不浪费资源?
    注:太多的调用链路,性能是有很大损耗的。
    `

  24. 为什么基础服务不应该高可用 · Why’s THE Design?
    https://draveness.me/whys-the-design-unstable-infrastructure
    `
    为什么这么设计(Why’s THE Design)是一系列关于计算机领域中程序设计决策的文章,我们在这个系列的每一篇文章中都会提出一个具体的问题并从不同的角度讨论这种设计的优缺点、对具体实现造成的影响。如果你有想要了解的问题,可以在文章下面留言。

    想要让服务达到高可用并不是一个容易的事情,不仅服务运行过程中出现的事故会影响可用时间,用于维护的计划停机和更新其实也会影响服务整体的可用时间,如果一个服务要求可用性为 99.95%,那么全年不工作的时间可能只有 4.38 小时,每个月只能宕机 21.9 分钟。

    99.999%(可用性) 5.26min(1年中不可用的时间) 26.3s(每个月不可用的时间)

    在这一节中,我们将从以下的三个方面依次分析『为什么基础服务不应该高可用』:
    1. 凡是可能出错的事情就一定会出错;
    2. 成本因素有时是技术决策的最关键因素;
    3. 只有使用更多异构的副本才能保证更高的可用性;

    简单总结一下,基础服务不需要保证高可用的几个原因:
    1. 在足够长的时间中,任何服务都没法保证 100% 可用,100% 可用更像是一个危险的承诺,一旦默认了这个假设就不利于我们构建高可用的服务;
    2. 边际成本是提升可用性时必须要考虑的因素,作为服务提供商必须要衡量提升可用性的成本和收益,而过高或者过低的可用性都会降低总体的收益;
    3. 服务的高可用从来都不来源于单一的依赖,只有使用更多异构的副本和组件才能尽可能保证服务的稳定;
    `

  25. 灰度发布、滚动发布、蓝绿部署和两种测试方法
    http://www.bewindoweb.com/231.html

    1、《蓝绿部署、A/B测试以及灰度发布》
    https://www.v2ex.com/t/344341

    2、《蓝绿部署、金丝雀发布(灰度发布)、A/B测试的准确定义》
    https://www.cnblogs.com/lijiaocn/p/9986880.html

    3、《微服务部署:蓝绿部署、滚动部署、灰度发布、金丝雀发布》
    https://www.jianshu.com/p/022685baba7d

    4、《金丝雀发布、滚动发布、蓝绿发布到底有什么差别?关键点是什么?》
    https://mp.weixin.qq.com/s?__biz=MzI4MTY5NTk4Ng==&mid=2247489100&idx=1&sn=eab291eb345c074114d946b732e037eb&source=41#wechat_redirect

  26. Failover 故障转移
    https://en.wikipedia.org/wiki/Failover

    https://www.techopedia.com/definition/27075/automatic-failover
    https://searchdisasterrecovery.techtarget.com/podcast/What-you-need-to-know-about-automatic-failover-and-disaster-recovery-automation

    Failover机制
    https://blog.csdn.net/ZuoAnYinXiang/article/details/78328031
    `
    Failover 失效转移 
    通俗地说,即当A无法为客户服务时,系统能够自动地切换,使B能够及时地顶上继续为客户提供服务,且客户感觉不到这个为他提供服务的对象已经更换。 

    这里的A和B可以存在于各种领域,但一般failover特指计算机领域的数据库、应用服务、硬件设备等的失效转移。
    `

    failover机制的小讨论
    https://www.cnblogs.com/Creator/p/3189758.html

    深入理解redis cluster的failover机制
    https://yq.aliyun.com/articles/638627

  27. 《软件架构设计:⼤型⽹站技术架构与业务架构融合之道》
    https://book.douban.com/subject/30443578/
    《架构即未来:现代企业可扩展的Web架构、流程和组织》
    https://book.douban.com/subject/26765979/

    《架构即未来》&《架构真经》读书笔记
    https://www.jianshu.com/p/fe7eb8691b99

    架构即未来
    https://notes.shenfq.com/book/the-art-of-scalability.html

    《架构即未来》之可扩展性组织的人员配置(上)
    https://juejin.im/post/5e64ade05188254935092f01

  28. 3+1保障:高可用系统稳定性是如何炼成的?
    https://mp.weixin.qq.com/s?__biz=MzIzOTU0NTQ0MA==&mid=2247502072&idx=1&sn=36b6139a9e109140a202c813105e2c93&scene=58&subscene=0
    `
    阶段性总结下我从团队技术负责人视角做好稳定性建设的实践性思考和简要思路,为感兴趣的技术同学提供一个实践指南。

    我的团队稳定性建设思路包括了3大技术要素:良好的系统架构和实现、完备的团队研发运维流程机制、技术同学良好意识和能力,以及1个业务要素:良好的研发项目管理。

    二、良好的系统架构和实现

    1. 架构设计
    * 消除单点
    * 数据一致性
    * 强弱依赖梳理和降级
    * 热点或极限值处理
    * 资金交易类系统要仔细考虑资损的风险
    * 离线数据流
    * 其他异常情况处理

    2. 容量评估设计

    3. 运维方案设计
    系统要考虑持续迭代发布变更以及线上运维的诉求,做到可灰度、可监控、可回滚。

    4. 安全设计
    数据以及应用安全问题一旦出现可能很致命,一定要加以考虑。安全是一个比较专业领域,常规在针对业务系统经典安全场景做好考量的同时,尽量引入专业安全技术同学评估。所有资源访问需要合适鉴权,避免越权访问;防Sql注入等攻击,做参数合法性校验;资源消耗频次管控,如短信资源等;用户防骚扰,设置用户通知、弹屏等触达阈值和频次;敏感信息过滤或脱敏等。

    5. 高质量的代码实现
    合适实现和经典性实践是非常重要代码质量保障的方式,大量线上问题还是由少量代码细节考虑不周全和经验不足引发的。这方面考量不同语言都会有自己一些最佳的实践,例如Java,可以参考《Java开发手册》。比较通用保障方式是分支覆盖完备的单元测试 、线上引流回归测试、完备回归测试用例等测试质量保障措施。

    三、团队研发运维流程机制

    稳定性涉及团队所有不同水平同学、所有系统、研发所有环节、线上时时刻刻,单个同学是无法保障好的,必须建立团队流程机制来可持续保障。

    四、技术同学意识和能力

    人的意识是最重要的,专业能力可以锻炼培养。如果意识不足或松懈,好的能力以及机制流程也会形同虚设。

    永远要对敬畏线上,敬畏客户体验。面向线上的稳定性战术上可以基于专业度锻炼后自信,但战略和思想上必须持续如履薄冰、三省吾身。线上稳定性保障是作为技术人自己专业度的追求和必须保持初心,始终保持敬畏。不因为业务繁忙、个人心情状态、团队是否重视而有变化,只要职责在,就要守护好。技术主管以及系统owner要有持续感知稳定性隐患和风险,保持锐度,集中性以及系统性查差补漏。

    五、良好的研发项目管理

    从经验看,线上系统大部分故障是由新的变更引入和触发的,变更是业务和产品迭代演进方式,因此不可能没有变更,但我们可以对变更项目做合适质量管理,进而有效提高线上稳定性。

    项目管理的四要素:工作范围(需求)、时间(交付时间)、质量、成本(人 & 机器资源等),简称STQC,这四个要素是相互关联的和制约的,形成一个项目管理质量管理铁三角,一个要素变动就会影响到其他要素,因此要保障好质量就必须要考虑怎么管理好其他三个要素。

    此外,我们可以进一步理解项目成功的要素,以终为始聚焦考虑如何提升实际影响成功的质量,成功的项目不仅取决于项目本身从开始到结束的执行过程,还取决于开始前和结束后的努力。成功的项目应该取决于三个阶段的努力:
    * 项目开始前必须 “了解什么是客户的成功”,只有客户成功了项目才能成功;——理解客户真正的需求。
    * 项目执行中能够“担负客户成功的责任”,按要求完成承诺的工作。
    * 项目结束后能“帮助客户实现价值”,只有客户说项目成功了才是真正的成功。——帮助客户实现业务目标、用户价值目标、商业价值目标。

    互联网产品迭代速度很快,推崇快速推出、快速试错、快速占据市场先机,交付时间的快是互联网产品、业务同学对于研发团队显性的要求,而交付质量和线上持续稳定则是一个隐性需求,产品业务默认研发团队应该做到,但往往在时间、成本等方面没有给予显性考虑,这一块就需要研发项目管理同学主动评估考量进来,有自己专业判断和坚持。

    理解好真正的客户需求和交付后客户价值的实现,可以帮助在四要素冲突的时候合适取舍需求来保障时间和质量,以及和业务产品&客户基于客户价值实现争取时间、资源来保障质量。项目管理角度稳定性保障基本动作包括确定和充分理解帮助客户成功的需求范围、控制好需求变更、预留质量保障环节时间、动态管控交付预期时间、争取充足人力以及机器等成本资源。进阶动作:在提前了解和理解甚至共同参与制定业务战略和策略基础上提前规划需求范围和研发节奏&人员排兵布阵&架构布局、深入理解业务基础上协助做需求取舍和优化。
    `

  29. 我做系统架构的一些原则
    https://coolshell.cn/articles/21672.html
    `
    工作 20 多年了,这 20 来年看到了很多公司系统架构,也看到了很多问题,在跟这些公司进行交流和讨论的时候,包括进行实施和方案比较的时候,都有很多各种方案的比较和妥协,因为相关的经历越来越多,所以,逐渐形成了自己的逻辑和方法论。今天,想写下这篇文章,把我的这些个人的经验和想法总结下来,希望能够让更多的人可以参考和借鉴,并能够做出更好的架构来。另外,我的这些思维方式和原则都针对于现有市面上众多不合理的架构和方案,所以,也算是一种“纠正”……(注意,这篇文章所说的这些架构上的原则,一般适用于相对比较复杂的业务,如果只是一些简单和访问量不大的应用,那么你可能会得出相反的结论)

    原则一:关注于真正的收益而不是技术本身
    原则二:以应用服务和 API 为视角,而不是以资源和技术为视角
    原则三:选择最主流和成熟的技术
    原则四:完备性会比性能更重要
    原则五:制定并遵循服从标准、规范和最佳实践
    原则六:重视架构扩展性和可运维性
    原则七:对控制逻辑进行全面收口
    原则八:不要迁就老旧系统的技术债务
    原则九:不要依赖自己的经验,要依赖于数据和学习
    原则十:千万要小心 X – Y 问题,要追问原始需求
    原则十一:激进胜于保守,创新与实用并不冲突
    `

  30. 【超赞】技术架构的战略和战术原则
    https://mp.weixin.qq.com/s/NIu95lFJszpXcoIw6h3Lyg
    `
    技术架构,是将产品需求转变为技术实现的过程。技术架构解决的问题包括了如何进行纯技术层面的分层、开发框架选择、语言选择(这里以 JAVA 语言为主)、涉及到各自非功能性需求的技术点(安全、性能、大数据)。技术架构是确定组成应用系统实际运行的技术组件、技术组件之间的关系,以及部署到硬件的策略。

    技术架构面临最大的挑战是“不确定性”。在技术架构上,很多时候就会面临这种选择。是要选择业界最新的技术?还是选择团队最熟悉的技术?如果选择最新的技术,遇到新技术出了问题怎么解决?如果选择目前熟悉的技术,后续技术演进怎么办?这些都是架构师在做技术架构过程中需要考虑的。

    业务在千变万化、技术在层出不穷,没有一套通用的技术架构模式来适用所有的系统。那么,我们如何保证在做技术架构时,能够实现一个稳定、出色的系统。面对这些“不确定性”时的架构设计问题,这里从战略和战术两个层面来提供一些设计原则。战略层提供的是技术架构的方法和思路,属于顶层设计;战术层提供的是技术架构的技术实践方式,更偏向详细设计。

    # 战略层设计原则
    战略层的设计原则就是:合适原则、简单原则、演化原则。

    # 战术层设计原则
    战术层的设计原则分为 3 部分:高并发原则、高可用原则、业务设计原则。

    设计高并发的系统,需要考虑以下几个方面的设计:无状态、拆分、服务化、消息队列、数据异构、缓存。

    高可用原则:1.降级;2.限流;3.可回滚

    业务设计原则
    * 防重设计
    * 幂等设计
    * 流程定义
    * 状态与状态机
    * 后台系统操作可反馈
    * 后台系统审批化
    * 文档注释
    * 备份
    `

  31. 高并发下如何防重?
    https://mp.weixin.qq.com/s/3dkfG9hbivYuLC1mk4UqSQ

    高并发下如何保证接口的幂等性?
    https://www.cnblogs.com/12lisu/p/14639651.html

    微服务 接口 高并发 幂等 防重 高并发扣减
    https://blog.csdn.net/fzy629442466/article/details/85340050
    `
    # 方案选型
    1.同步锁(单线程,集群可能会失效)
    2.分布式锁如redis(高并发 实现复杂)
    2.业务字段加唯一约束(简单)
    3.令牌表+唯一约束(简单推荐)
    4.mysql的on duplicate key update(简单 联合唯一索引 防重)
    5.共享锁+普通索引(简单)
    6.利用MQ或者Redis扩展(排队)
    7.其他方案如多版本控制MVCC 乐观锁 悲观锁(select for update) 状态机等。。。

    对客户端请求排队或者单线程都可以处理幂等问题,需要根据具体业务选择合适的方案但必须前后端一起做,前端做了可以提升用户体验,后端则可以保证数据安全。

    # 编程中常见幂等
    select查询天然幂等
    delete删除也是幂等,删除同一个多次效果一样
    update直接更新某个值的,幂等
    update更新累加操作的,非幂等
    insert非幂等操作,每次新增一条

    # 产生原因
    由于重复点击或者网络重发 eg:
    点击提交按钮两次;
    点击刷新按钮;
    使用浏览器后退按钮重复之前的操作,导致重复提交表单;
    使用浏览器历史记录重复提交表单;
    浏览器重复的HTTP请;
    nginx重发等情况;
    分布式RPC的try重发等;
    `

  32. 高并发是一种架构思维模式
    https://mp.weixin.qq.com/s/apUVMfAI52uvc7U-iOVvKg
    `
    什么是高并发,从字面上理解,就是在某一时刻产生大量的请求,那么多少量称为大量,业界并没有标准的衡量范围。原因非常简单,不同的业务处理复杂度不一样。

    而我所理解的高并发,它并不只是一个数字,而更是一种架构思维模式,它让你在面对不同的复杂情况下,从容地选择不同的技术手段,来提升应用系统的处理能力。

    但是,并不意味应用系统从诞生的那一刻,就需要具备强大的处理能力,这种做法并不提倡。要知道,脱离实际情况的技术,会显得毫无价值,甚至是一种浪费的表现。

    言归正传,那高并发到底是一种怎样的架构思维模式,它对架构设计又有什么影响,以及如何通过它来驱动架构演进,让我们接着往下读,慢慢去体会这其中的精髓。

    # 性能是一种基础

    性能在软件研发过程中无处不在,不管是在非功能性需求中,还是在性能测试报告中,都能见到它的身影。那么如何来衡量它的高低呢,先来看看常用的性能指标。
    每秒处理事务数(TPS)
    每秒能够处理的事务数,其中T(Transactions)可以定义不同的含义,它可以是完整的一笔业务,也可以是单个的接口请求。
    每秒请求数(RPS)
    每秒请求数量,也可以叫做QPS,但它与TPS有所不同,前者注重请求能力,后者注重处理能力。不过,若所有请求都在得到响应后再次发起,那么RPS基本等于TPS。
    响应时长(RT)
    从发出请求到得到响应的耗时,一般可以采用毫秒单位来表示,而在一些对RT比较敏感的业务场景下,可以使用精度更高的微秒来表示。
    并发用户数(VU)
    同时请求的用户数,很多人将它与并发数画上等号,但两者稍有不同,前者关注客户端,后者关注服务端,除非每个用户仅发送一笔请求,且请求从客户端到服务端没有延迟,同时服务端有足够的处理线程。

    以上都是些常用的性能指标,基本可以覆盖80%以上的性能衡量要求。但千万不要以单个指标的高低来衡量性能。比如:订单查询TPS=100万就认为性能很高,但RT=10秒。
    这显然毫无意义。因此,建议同时观察多个指标的方式来衡量性能的高低,大多数情况下主要会关注TPS和RT,而你可以将TPS视为一种水平能力,注重并行处理能力,将RT视为一种垂直能力,注重单笔处理能力,两者缺一不可。
    性能是高并发的基础能力,是实现高并发的基础条件,并且你需要有侧重性地提升不同维度的性能指标,而非仅关注某一项。

    # 限制是一种设计

    思考一下,追求性能是为了解决什么问题,至少有一点,是为了让应用系统能够应对突发请求。换言之,如果能解决这个问题,是不是也算实现了高并发的目标。
    而有时候,我们在解决问题时,不要总是习惯做加法,还可以尝试做减法,架构设计同样如此。那么,如何通过做减法的方式,来解决应对突发请求的问题呢。让我们来讲讲限制。
    限制,从狭义上可以理解为是一种约束或控制能力。在软件领域中,它可以针对功能性或非功能性,而在高并发的场景中,它更偏向于非功能性。
    限制应用系统的处理能力,并不代表要降低应用系统的处理能力,而是通过某些控制手段,让突发请求能够被平滑地处理,同时起到应用系统的保护能力,避免瘫痪,还能将应用系统的资源进行合理分配,避免浪费。
    那么,到底有哪些控制手段,既能实现以上这些能力,又能减少对客户体验上的影响,下面就来介绍几种常用的控制手段。
    第一招:限流
    第二招:降频
    第三招:降级

    # 取舍是一种权衡

    在架构设计的过程中,你是否经常会听到“取舍”的这个词,它是通过牺牲一种能力来换取另外一种能力的方式,这些能力可以是性能、可用性、数据一致性或是其他能力。
    等等,你是不是突然有意识到,提升性能并不只有投入成本这种方式,至少是在硬件资源方面,我们还可以通过牺牲一种能力去换取。那到底选择牺牲哪种能力呢,牺牲可用性,一般不会第一时间考虑,那是不是可以考虑牺牲数据一致性。
    但在考虑前得先声明一下,所谓牺牲数据一致性,并不是完全不要,而是将数据强一致性降级为最终一致性。而对于数据最终一致性的理解,就是在数据更新后,要过一段时间后才能看到,而时间的长短就代表着牺牲了多少。
    但并不是说,所有情况都必须牺牲数据一致性来提升性能,有些时候也可以考虑牺牲其他能力。但在取舍前,得先弄清楚当前要什么,但更需要弄清楚当前可以失去什么,不合理的取舍,不但无法换取收益,反而还会引来更多的问题。
    情况1:数据缓存
    情况2:单机限流
    以上,只是简单列举了两种不同情况下的取舍,而在高并发架构上,可取舍的地方远不止这些。你得知道,高并发的每一处设计或每一份设计方案的背后,都曾是通过不断地取舍所获得的,而没有取舍的高并发架构决策,将会显得毫无说服力。

    取舍不但可以作为高并发架构决策的有力武器,也将是驱动架构演进最合理的一种方式。但要切记,取舍的方向并不是一成不变的,而是会随着外界环境的变化而变化,它将是一种独特的艺术。

    # 写在最后

    高并发的魅力之处,就在于它没有唯一的答案,而答案是需要我们以不同的业务场景作为线索去不断地寻找,这种寻找的过程也是一种不断思考的过程,这就是我为什么说高并发是一种架构思维模式。

    本文从浅到深依次讲述了性能是实现高并发的基础条件,控制是实现资源最大化利用的方式,以及如何通过取舍来换取当前应用系统更所需的能力,但这些仅仅只是高并发世界里的一个角落。因篇幅有限,今天就暂告一段落。

    最后想说,高并发其实并不可怕,可怕的是你知其然而不知其所以然。对于追求技术的你,需要不断地拓宽你的技术深度与广度,才能更好地掌握高并发,以及运用高并发的思维模式来提升应用系统处理能力。
    `

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注