Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

系统架构----高并发 #142

Open
AlexiaChen opened this issue Sep 18, 2021 · 0 comments
Open

系统架构----高并发 #142

AlexiaChen opened this issue Sep 18, 2021 · 0 comments
Labels
WIP Work in Progress 分布式系统 分布式理论,分布式系统 架构设计 软件架构的一切

Comments

@AlexiaChen
Copy link
Owner

AlexiaChen commented Sep 18, 2021

系统架构之高并发

场景分类

侧重于高并发读的系统

  1. 搜索引擎

拿熟悉的百度举例,在搜索框里面搜索关键词,展示结果网页列表,这个过程中,用户只是浏览,没有修改网页内容。

  • 数量级。读的一端,C端用户,各种手机,电脑,其他App调用搜索引擎的接口,数量级是上亿,或者数十亿。写的一端(把网页数据纳入搜索引擎的存储系统中),数量级绝对是远远低于读的。

  • 响应时间。读的一端通常要求在毫秒级别,最差情况为1-2s内返回结果,写的一端可能是分钟或者小时甚至天。一些网页结果甚至都不会被搜索引擎检索到。

  • 频率。 读的频率远比写的高,显而易见。

  1. 电商的商品搜索,描述,价格

与百度搜索之类的类似,发布商品本来频率就更低,搜索浏览淘宝之类的更多。

侧重于高并发写的系统

典型的就是广告计费系统,现在各种App都有广告,点击浏览计费,就会在数据库中扣除广告主的余额。Update很多。相当于就是读多写少的大流量转化成了点击量,最终导致写多。

高并发读写二者兼备的系统

  1. 电商的库存和秒杀系统

库存系统和秒杀系统的一个典型特征是:C端用户要对数据库同时进行高并发读写,我买了这件衣服,那么库存中只能在另一个用户看着一定是少了一件,信息要近乎实时的更新。12306的系统也是这样,春运买火车票,想想都可怕。

  1. 支付系统和微信红包

支付系统也是高并发读写,查询余额和转入转出,并且查询余额也要很实时准确,钱这一类的信息是金融相关的数据,对数据一致性要求很高,也不能延迟。从支付扩展到红包,业务场景会更复杂,一个用户发红包,群里多个人墙。全国那么多群。一个账号发生扣减,多个人的账号加钱,并且这个过程大部分人还会查看哪些人抢到了红包。

  1. IM,微博和朋友圈

QQ,微信消息,微博,朋友圈这些都是,收消息是读,发消息是写,几乎是对半分。用户规模在亿级别,读写处理都需要非常及时。

高并发读

这样的系统在互联网应用中占大部分,大部分的业务系统都是读多写少。大部分数据库的内核设计都是读多写少,尽可能提高查询效率,Google的有个PPT也是说到,写的优化会比读更难。

加缓存,主从,CDN

本质是以空间换时间。

  1. 本地缓存或Redis等这些集中式缓存

这里得小心,能尽量不用缓存就不用缓存,以免增加维护成本。《有些上古程序员一直坚持反对使用Redis怎么办?》

缓存一般是KV结构,更新缓存一般也有两种策略,一种是主动更新(推),当数据库中的数据发生变更时,主动地删除或更新缓存中的数据。另一种是被动更新(拉),当用户的查询请求到来,如果缓存过期,再更新缓存。

对于缓存,需要考虑几个问题:

  • 缓存血崩。即缓存的高可用问题,如果缓存发生宕机,所有请求全部查询数据库,是否会压垮数据库?
  • 缓存穿透。缓存没有宕机,但是某一时段,某些Key发生了大量查询,这些Key都不在缓存中,导致短时间内大量请求压往数据库。比如大量的热Key过期,就会导致这样的情况
  • 缓存与数据库的一致性,这个策略网上有,文章满天飞,提到只是为了说明有成本的
  1. MySQL的Master/Slave

这样的方式主要是为了分担主库的读压力,加一个或者多个Slave,简单有效。

  1. CDN静态文件加速(动静分离)

图片,HTML,CSS文件这样不变的数据一般用CDN。一个静态文件缓存到了全网的各个节点,当第一个用户访问的时候,离用户最近的节点还没有缓存数据,CDN就会去源系统抓取文件缓存到该节点,等第二个用户访问的时候,只需要从这个节点访问即可。

并发读,串行改并行

  1. 异步RPC

现在的RPC框架基本都支持了异步RPC,对于用户的一个请求,如果需要调用3个RPC接口分别需要耗时T1,T2,T3。如果是同步调用总耗时就是T = T1+T2+T3。如果是异步调用,则所消耗的总时间是T = MAX(T1,T2,T3)。这里有个前提条件就是这三个接口没有耦合关系,不能有结果依赖,需要是可以并行的。

  1. Google的冗余请求(Hedged Request)

Google的顶级基础架构师Jeff Dean在The Tail at Scale的论文中讲过这样一个案例:假设一个用户的请求需要100台服务器同时联合处理,每台服务器有1%的概率发生调用延迟(定义相应时间大于1s为延迟),那么对于C端用户来说,响应时间大于1s的概率是63%。

从这个结果上有点反直觉?但是对于分布式系统,就是这样的,结果是这样计算出来的。假设有100台机器,每一台发生非延迟的调用是99%,因为延迟是1%,如果用户的请求响应时间小于1s,意味着100台机器任何一台都不可以小于1s,这个概率是比较低的也就是99%的100次方。反过来看,用户的请求响应时间大于1s的概率就是:

1 - (99%)^100 = 63%

这个概率是很高的,注意这里是100台联合协同处理,不是负载均衡的那样单独处理,也就是这100台服务器功能独立负责各自的。机器数越多越严重,在分布式系统上,不出问题是不可能的,即使每台的故障率很低。Google的数据中心的规模,据说已经算是无时无刻都有问题故障不断。

怎么解决以上问题?

其中最重要的一个就是服务间调用控制。首先需要说明个前提,在分布式系统中,为了解决数据的可靠性,通常会将数据复制到多台机器上,同时为了实现服务的高可用,又会有多个服务器提供同样的功能,防止部分服务器出现故障。

为了解决响应时间的突刺,调用者需要将请求“同时”发送给多台服务器,并在收到最快的响应后,马上终止其他服务器的处理(或将其他服务器的返回结果直接丢弃,不需要等待)。采用这种方法,可以大大降低某个调用出现的突刺。同时我们也可以看到,这样会让整个系统的请求调用数量(流量)翻几倍。

论文中给出了一个更好的做法:

  • Client调用方首先发送一个请求给服务端,并等待服务端返回的响应
  • 如果Client在一定的时间(95%的请求响应时间)内没有收到服务器端的响应,则马上发送同样的请求到另一台(或者多台)服务器上
  • Client等待第一个响应(最快那一个)到达后,终止其他请求的处理

Google的测试数据表示,,采用这种方案,可以仅用2%的额外请求,将系统的99.9%的请求响应时间从1800ms降低到74ms:

For example, in a Google benchmark that reads the values for 1,000 keys stored in a 
BigTable table distributed across 100 different servers, sending a hedging request after 
a 10ms delay reduces the 99.9th-percentile latency for retrieving all 1,000 values from 
1800ms to 74ms while sending just 2% more requests.

重写轻读

To be continued

@AlexiaChen AlexiaChen added 分布式系统 分布式理论,分布式系统 架构设计 软件架构的一切 labels Sep 18, 2021
@AlexiaChen AlexiaChen added the WIP Work in Progress label Jun 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WIP Work in Progress 分布式系统 分布式理论,分布式系统 架构设计 软件架构的一切
Projects
None yet
Development

No branches or pull requests

1 participant