python面试之高并发

高并发优化方案,可从以下几个角度进行优化

  • 存储角度
  • 缩短链路长度角度
  • 减少请求次数角度
  • 资源复用角度
  • 异步编程

从存储角度

数据库

sql优化

索引优化

分库分表

读写分离

读写分离数据不一致的解决方案

  • 通过第三方软件给修改的数据做标记
    如redis,在每次修改之后,往redis添加一个该记录的修改了的标记,并设置一个过期时间(一般要求大于主从同步的时间即可),当查数据的请求到来时,先从redis中取标记,如果能取到,说明还没完成主从同步,从主库取数据;如果不能取到,说明主从同步已完成,从从库里取数据
  • 通过客户端标记
    通过服务端的第三方做标记,那么所有的sql请求都会先走一遍第三方,会把压力都给到服务端,在实时性要求不高的应用场景,可以通过客户端cookie标记。比如,发博客,当用户发完博客后,会去查看自己发布的博客,这时候客户端带标记过来,直接从主库里读数据。而其他客户端并不要求立马查看到发布的博客,照样还是从从库里读数据

缓存

适用场景

  • 读多写少的场景
    读多写少: 比如电商里的商品详情页面,访问频率很高,但是一般写入只在店家上架商品和修改信息的时候发生。如果把热点商品的信息缓存起来,这将拦截掉很多对数据库的访问,提高系统整体的吞吐量。 因为一般数据库的 QPS 由于有「ACID」约束、并且数据是持久化在硬盘的,所以比 Redis 这类基于内存的 NoSQL 存储低不少。常常是一个系统的瓶颈,如果我们把大部分的查询都在 Redis 缓存中命中了,那么系统整体的 QPS 也就上去了。

  • 计算耗时大,且实时性不高的场景
    比如王者荣耀里的全区排行榜,一般一周更新一次,并且计算的数据量也比较大,所以计算后缓存起来,请求排行榜直接从缓存中取出,就不用实时计算了。

缓存更新策略

cache-aside

image.png

这应该是最容易想到的模式了,获取数据时先从缓存读,如果 cache hit 则直接返回,没命中就从数据源获取,然后更新缓存。

写数据的时候则先更新数据源,然后设置缓存失效,下一次获取数据的时候必然 cache miss,然后触发回源。即缓存的更新,只通过查询,查询没命中的时候再更新

cache-as-sor

image.png

从字面上来看,就是把 Cache 当作 SoR,也就是数据源,所以一切读写操作都是针对 Cache 的,由 Cache 内部自己维护和数据源的一致性

这样对于使用者来说就和直接操作 SoR 没有区别了,完全感知不到 Cache 的存在。

Cache-As-SoR 又分为以下三种方式:

  • Read Through:这种方式和 Cache-Aside 非常相似,都是在查询时发生 cache miss 去更新缓存,但是区别在于 Cache-Aside 需要调用方手动更新缓存,而 Cache-As-SoR 则是由缓存内部实现自己负责,对应用层透明。
  • Write Through: 直写式,就是在将数据写入缓存的同时,缓存也去更新后面的数据源,并且必须等到数据源被更新成功后才可返回。这样保证了缓存和数据库里的数据一致性
  • Write Back:回写式,数据写入缓存即可返回,缓存内部会异步的去更新数据源,这样好处是写操作特别快,因为只需要更新缓存。并且缓存内部可以合并对相同数据项的多次更新,但是带来的问题就是数据不一致,可能发生写丢失。

从链路长度角度

微服务 + 消息队列

将微服务单独出来讲,实际上并不能算做减少链路长度的一种方案,需要配合消息队列。

如以下场景:

一个论坛网站,当用户成功发布一条帖子有一系列的流程要做,有积分服务计算积分,推送服务向发布者的粉丝推送一条消息

常规实现方案:

image

会有两个问题:

  1. 那么一个完整的流程,需要完成:发布 + 增加积分 + 推送消息给粉丝 + 会员服务,整个链路就变的很长,势必会导致响应不够及时。
  2. 且一旦后续要再加一个数据分析的服务,就又得回头修改发布服务,让发布服务去调用数据分析服务,这违背了依赖倒置原则,即上层服务不应该依赖下层服务

消息队列方案

image

引入消息队列作为中间层,完美解决上述两个问题。

  1. 当帖子发布完成后,发送一个事件到消息队列里,而关心帖子发布成功这件事的下游服务就可以订阅这个事件,这样即使后续继续增加新的下游服务,只需要订阅该事件,然后在各自的服务内完成对应功能即可。
  2. 发布服务只管发布,不需要关心其业务下游以后再加什么别的服务,以后增加了新服务,订阅消息队列的这个事件就可以了

流程异步处理

有些业务涉及到的处理流程非常多,但是很多步骤并不要求实时性。那么我们就可以通过消息队列异步处理。比如淘宝下单,一般包括了风控、锁库存、生成订单、短信/邮件通知等步骤。但是核心的就风控和锁库存, 只要风控和扣减库存成功,那么就可以返回结果通知用户成功下单了。后续的生成订单,短信通知都可以通过消息队列发送给下游服务异步处理。大大提高了系统响应速度
这就是处理流程异步化

预处理(减少服务间调用)

支付宝联合杭州市政府发放消费劵,但是要求只有杭州市常驻居民才能领取,那么需要在抢卷请求进入后台的时候就判断一下用户是否是杭州常驻居民。
而判断用户是否是常驻居民这个是另外一个微服务接口,如果直接实时的去调用那个接口,短时的高并发很有可能把这个服务也拖挂,最终导致整个系统不可用,并且 RPC 本身也是比较耗时的,所以就考虑在这里进行优化。
那么该怎么做呢?很简单的一个思路,提前将杭州所有常驻居民的 user_id 存到缓存中, 比如可以直接存到 Redis。大概就是千万量级,这样,当请求到来的时候我们直接通过缓存可以快速判断是否来自杭州常驻居民。如果不是则直接在这里返回前端。这里通过预先处理减少了实时链路上的 RPC 调用,既减少了系统的外部依赖,也极大的提高了系统的吞吐量。

延后处理

一些对于实时性要求不高的场景,可以将业务结果延后反馈给用户。
如:
一些活动,会在活动结束的时间节点,给用户反馈类似“结算中”,“稍后到账”等等,目的就是为了将海量的计算,海里的网络IO拆开,防止系统满足不了这么高的并发量。

减少请求次数角度

批处理

在涉及到网络连接、IO等情况时,将操作批量进行处理能够有效提高系统的传输速率和吞吐量

在前后端通信中,通过合并一些频繁请求的小资源可以获得更快的加载速度

比如我们后台 RPC 框架,经常有更新数据的需求,而有的数据更新的接口往往只接受一项,这个时候我们往往会优化下更新接口,使其能够接受批量更新的请求,这样可以将批量的数据一次性发送,大大缩短网络 RPC 调用耗时

从资源复用角度

池化

内存、连接、线程这些都是资源,创建线程、分配内存、数据库连接这些操作都有一个特征, 那就是创建和销毁过程都会涉及到很多系统调用或者网络 IO。 每次都在请求中去申请创建这些资源,就会增加请求处理耗时,但是如果我们用一个容器(池) 把它们保存起来,下次需要的时候,直接拿出来使用,避免重复创建和销毁浪费的时间。

内存池

线程池

连接池

mysql连接池

一次 SQL 查询请求会经过哪些步骤:

  1. MySQL server 建立 TCP 连接: 三次握手
  2. MySQL 权限认证:
    2.1 Server 向 Client 发送 密钥
    2.2 Client 使用密钥加密用户名、密码等信息,将加密后的报文发送给 ServerServer
    2.3 根据 Client 请求包,验证是否是合法用户,然后给 Client 发送认证结果
  3. Client 发送 SQL 语句
  4. Server 返回语句执行结果
  5. MySQL 关闭
  6. TCP 连接断开:四次挥手

可以看出不使用连接池的话,为了执行一条 SQL,会花很多时间在安全认证、网络IO上。如果使用连接池,执行一条 SQL 就省去了建立连接和断开连接所需的额外开销。还能想起哪里用到了连接池的思想吗?我认为 HTTP 长链接也算一个变相的链接池,虽然它本质上只有一个连接,但是思想却和连接池不谋而合,都是为了复用同一个连接发送多个 HTTP 请求,避免建立和断开连接的开销。

异步编程

思想是,一个完整的请求主要瓶颈是IO,不管是网络IO还是磁盘IO,读写速度往往不能及时响应,这时候可以使用异步编程,在程序遇到IO操作导致程序阻塞时,将cpu切换到别的程序或者请求,当之前的IO操作完成时,再切换回去,处理后续功能
具体异步编程可看:https://www.jianshu.com/p/beb147e27041

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容

  • 本篇是读《亿级流量网站架构核心技术》的一些总结;可以作为在实际项目搭建过程中架构核心点实施的扩展发散或是作为一个项...
    lotusfan2018阅读 1,329评论 0 12
  • 前面整理了Java基础、Mysql、Spring的高频面试题,今天为大家带来Java并发方面的高频面试题,因为并发...
    庸人视角阅读 11,307评论 1 46
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,531评论 28 53
  • 信任包括信任自己和信任他人 很多时候,很多事情,失败、遗憾、错过,源于不自信,不信任他人 觉得自己做不成,别人做不...
    吴氵晃阅读 6,187评论 4 8
  • 怎么对待生活,它也会怎么对你 人都是哭着来到这个美丽的人间。每个人从来到尘寰到升入天堂,整个生命的历程都是一本书,...
    静静在等你阅读 4,967评论 1 6