ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

高并发系统设计思考笔记

2022-08-28 10:01:36  阅读:185  来源: 互联网

标签:负载 请求 笔记 并发 线程 user 思考 超时 节点


一、性能度量的指标

如何衡量系统接口的响应时间?

  • 平均值
    平均值是把统计时间段内所有请求的响应时间数据相加,再除以总请求数。平均值的敏感度差

  • 最大值
    统计时间段内所有请求响应时间最长的值,最大值过于敏感

  • 分位值
    把统计时间段内请求的响应时间从小到大排序,假如一共有100个请求,那么排在第90位的响应时间就是90分位值。一般面向用户的线上系统,看 tp999 或者 tp9999 的响应时间。(99.9%的请求的响应时间在 x 毫秒以内)
    分位值排除了偶发极慢请求对于数据的影响,能够很好地反应这段时间的性能情况,分位值越大,对于慢请求的影响就越敏感。

二、高并发性能优化

要想提高qps(query per seconds),先看示例:假设一次请求任务耗时100ms,一个线程1秒钟能处理10个请求任务。qps=(处理线程数)/(单次任务响应时间ms)/1000。由于单次任务的响应时间是以毫秒计,因此除以1000转化为秒。

  1. 提高处理线程数
    提高处理线程数可以提升 qps,但是一个系统的线程数不可能无限地增加。它受限于阿姆达尔定律(Amdahl’s law)。这可以通过压测方式知道系统的核心线程数到多少时出现性能瓶颈。

  2. 降低单次任务的响应时间
    要完成一次请求执行完所有的业务逻辑的耗时,就是响应时间。而要降低响应时间,这主要靠各种优化,比如:引入缓存、减少系统间的RPC调用、优化代码(减少加锁次数、优化算法)等。这就需要对系统的业务逻辑比较熟悉。

三、高可用

  1. 核心系统一般需要保证4个9的可用性(年故障时间52分钟)。

  2. 发现故障
    业务指标监控打点(业务逻辑失败)、系统指标监控打点(缓存、数据库访问异常)。节点之间则是通过“heartbeat”心跳包检测异常

  3. 处理故障
    对于业务系统而言,一般是无状态的节点,可以无限地扩容。在引入灰度发布和弹性伸缩后,可应对大部分的故障场景。业务系统依赖的底层存储而言,是有状态的节点,当QPS突增时,业务系统机器可借助弹性伸缩无限地扩容,但是当底层存储扛不住时,扩容就比较困难了(可能需要迁移数据、重新部署一套存储……)此时可采取的手段有:限流、降级、调整超时时间的配置。
    对于业务系统之间的 RPC 调用而言,一般会有 thrift 线程池,客户端调用服务端时,会有一个超时时间,若超时时间设置得不合理(比如默认值30秒),当调用的下游服务出现慢查询时,这些慢请求会占用客户端 worker 线程,从而导致调用方没有 worker 线程来处理其他请求了,而如果设置合理的超时时间(比如200ms),那么 200ms 之后请求超时,客户端 worker 线程就释放了,从而能够处理其他请求。
    总结一下:当出现QPS流量突增时,业务系统开始出现一些超时请求的故障了,第一件事就是先扩容。如果扩容达到了底层存储再也扛不住时(默认下游服务能扛住流量。在真实的线上系统中,如果上游系统扩容了能扛住高QPS但是调用的下游服务有可能扛不住高QPS,就需要评估是否保护下游?),这时候就要开始限流、降级了。与此同时,联系DBA申请更多的存储资源。如果扩容未生效,这时候看是否能够适当调大一点超时时间(有风险,因此流量是不断增长的,更大的超时时间可能会占用更多的处理线程,从而导致其他请求无线程可用),需要确保有足够的可用线程且超时时间是合理的。因此,更保险的做法是限流、降级。

  4. failover
    业务系统(无状态)的 failover 就是根据配置的 qps 或者 cpu 使用率等指标自动触发弹性扩容。有状态的系统的 failover 比较复杂,因此有状态的节点一般有 master 和 slave 之分。通过心跳检测到 master 宕机后,需要发起选主,选主需要保证其余节点一致认可 master(需要一致性算法 raft/paxos),然后由新的 master 来负责数据同步并恢复故障。

  5. 路由与负载均衡
    服务之间通过 RPC 调用时,需要选择一台合适的下游机器将请求发送过去。如何选择?
    路由是从下游节点集合中筛选出符合要求的一部分节点;负载均衡是从符合要求的节点中选择出一个节点。通常是先执行路由,再执行负载均衡,路由的输出是负载均衡的输入。
    路由解决:如何从下游选择出一组机器,作为请求候选机器。常见的路由策略有:同机房优先、同地域/城市优先。
    负载均衡解决:从候选集机器中,选择一台,将请求发送过去。常见的负载均衡策略有:按权随机负载(每个机器有个权重,权重高的分配到的请求多,权重一样时,则随机)、RoundRobin负载。

四、读写分离与分库分表

读写分离

访问量变大的情况下,写请求走主库,从请求走读库。

  1. 负载均衡,读能力水平扩展
  2. 避免单点故障
  3. 需要对SQL进行判断,如果是 select 走从库,是 update/insert/delete 走主库
  4. 主从同步延迟
  5. 事务问题,如果一个事务中同时包含了读和写,那么读不从走从库,所有操作都得走主库,避免跨库事务
  6. 高可用性,新增slave节点,需要及时被 client 感知,将读请求发送到此 slave;slave宕机,需要检测出来并隔离,后续读请求转发到其他正常的 slave
  7. master 宕机,需要主从切换,将某个 slave 提升为master,写请求走新的 master

分库分表

数据量变大的情况下,将单表的数据做拆分。

  1. 负载均衡,写能力水平扩展
  2. 单表数据量太大,水平分区(sharding),将一张表的数据分配给N个表维护,有三种分法:只分表、只分库、分库分表。示例如下:
  3. SQL的增删改需要分发到不同的DB上执行。假设有 user 大表,拆分成四张 user 子表:user_1、user_2、user_3、user_4

insert into user(id,name) values (1,"a"),(2,"b"), (3,"c"),(4,"d")

需要改写成:

insert into user_1(id,name) values (1,"a")
insert into user_2(id,name) values (2,"b")
insert into user_3(id,name) values (3,"c")
insert into user_0(id,name) values  (4,"d")

经过分库分表后,原来单表下执行的SQL需要:SQL解析、SQL路由、SQL改写、SQL执行、结果集合并,最终得到执行结果。
4. 分布式事务
分库分表后不可避免地遇到跨库事务的问题,一般使用“柔性事务”来解决。
5. 分布式id
不能再使用mysql的自增主键,需要分布式唯一ID生成器,参考:Snowflake

数据库中间件

  1. 数据库代理
    在DB和应用程序之间单独部署数据库代理。对于应用而言通过一个普通的数据源(c3p0、druid、dbcp等)与代理服务器建立连接,然后由代理服务访问DB

  2. 数据源代理

五、NoSQL 数据库

HBase

淘宝 Tair

标签:负载,请求,笔记,并发,线程,user,思考,超时,节点
来源: https://www.cnblogs.com/hapjin/p/16007599.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有