高并发请求的缓存设计策略

前几天,我司出了个篓子。当时正值某喜闻乐见的关键比赛结束,一堆人打开我司app准备看点东西,结果从来没有感受到过这么多关注量的该功能瞬间幸福到眩晕,触发了熔断,结果就是大量兴致冲冲打开app准备看该比赛结果的人被迫刷了十分钟三天前的野外跑酷,负责内容的人火大到直接骂娘。

虽然这个业务不是我负责,但是也跟相关的人聊了下情况,感慨了一下,于是有了这一篇文章。

1.为何需要缓存?

在高并发请求时,为何我们频繁提到缓存技术?最直接的原因是,目前磁盘IO和网络IO相对于内存IO的成百上千倍的性能劣势。

做个简单计算,如果我们需要某个数据,该数据从数据库磁盘读出来需要0.1s,从交换机传过来需要0.05s,那么每个请求完成最少0.15s(当然,事实上磁盘和网络IO也没有这么慢,这里只是举例),该数据库服务器每秒只能响应67个请求;而如果该数据存在于本机内存里,读出来只需要10us,那么每秒钟能够响应100,000个请求。

通过将高频使用的数据存在离cpu更近的位置,以减少数据传输时间,从而提高处理效率,这就是缓存的意义。

2.在哪里用缓存?

一切地方。例如:

我们从硬盘读数据的时候,其实操作系统还额外把附近的数据都读到了内存里

例如,CPU在从内存里读数据的时候,也额外读了许多数据到各级cache里

各个输入输出之间用buffer保存一批数据统一发送和接受,而不是一个byte一个byte的处理

上面这是系统层面,在软件系统设计层面,很多地方也用了缓存:

浏览器会缓存页面的元素,这样在重复访问网页时,就避开了要从互联网上下载数据(例如大图片)

web服务会把静态的东西提前部署在CDN上,这也是一种缓存

数据库会缓存查询,所以同一条查询第二次就是要比第一次快

内存数据库(如redis)选择把大量数据存在内存而非硬盘里,这可以看作是一个大型缓存,只是把整个数据库缓存了起来

应用程序把最近几次计算的结果放在本地内存里,如果下次到来的请求还是原请求,就跳过计算直接返回结果

3.本次事故分析

回到本文开始的问题上,该系统是怎么设计的呢?底层是数据库,中间放了一层redis,前面的业务系统所需的数据都直接从redis里取,然后计算出结果返回给app;数据库和redis的同步另外有程序保证,避免redis的穿透,防止了程序里出现大量请求从redis里找不到,于是又一窝蜂的去查数据库,直接压垮数据库的情况。从这个角度讲,其实这一步是做的还可以的。

但是这个系统有两个问题:

1.业务系统需要的数据虽然都在redis里,但是是分开存放的。什么意思呢,比如我前台发起一个请求,后台先去redis里取一下标题,然后再取一下作者,然后再取一下内容,再取一下评论,再取一下转发数等等……结果前台一次请求,后台要请求redis十几次。高并发的时候,压力一下被放大十几倍,redis响应、网络响应必然会变慢。

2.其实做业务的那波人也意识到了这个情况可能发生,所以做了熔断机制,另起了一个缓存池,里面放了一些备用数据,如果主业务超时,直接从缓存池里取数据返回。但是他们设计的时候没想周全,这个备选池的数据过期时间设计的太长了,里面居然还有三天前更新进去的数据,最终导致了一大波用户刷出来三天前的野外生态小视频……

说到这,不知道读者有没有意识到他们最致命的一个问题:这个业务系统完全没有考虑本地缓存(也就是在业务服务器内存里做缓存)。比如像我们这种app,一旦大量用户同一时间涌进来,必定都是奔着少数几个内容去的,这种特别集中的高频次极少量数据访问,又不需要对每个用户做特化的,简直就是在脸上写上“请缓存我”。

这时候,如果能在业务端做一层本地缓存,直接把算好的数据本地存一份,那么就会极大减少网络和redis的压力,不至于当场触发熔断了。

4.浅谈缓存的那些坑

缓存很有用,但是缓存用不好也会埋很多坑:

缓存穿透

缓存穿透是说收到了一个请求,但是该请求缓存里没有,只能去数据库里查询,然后放进缓存。这里面有两个风险,一个是同时有好多请求访问同一个数据,然后业务系统把这些请求全发到了数据库;第二个是有人恶意构造一个逻辑上不存在的数据,然后大量发送这个请求,这样每次请求都会被发送到数据库,可能导致数据挂掉。

怎么应对这种情况呢?对于恶意访问,一个思路是事先做校验,对恶意数据直接过滤掉,不要发到数据库层;第二个思路是缓存空结果,就是对查询不存在的数据仍然记录一条该数据不存在在缓存里,这样能有效的减少查询数据库的次数。

那么非恶意访问呢?这个要结合缓存击穿来讲。

缓存击穿

上面提到的某个数据没有,然后好多请求都被发到数据库其实可以归为缓存击穿的范畴:对于热点数据,当数据失效的一瞬间,所有请求都被下放到数据库去请求更新缓存,数据库被压垮。

怎么防范这种问题呢?一个思路是全局锁,就是所有访问某个数据的请求都共享一个锁,获得锁的那个才有资格去访问数据库,其他线程必须等待。但是现在的业务都是分布式的,本地锁没法控制其他服务器也等待,所以要用到全局锁,比如用redis的setnx实现全局锁。

另一个思路是对即将过期的数据主动刷新,做法可以有很多,比如起一个线程轮询数据,比如把所有数据划分为不同的缓存区间,定期分区间刷新数据等等。这第二个思路又和我们接下来要讲的缓存雪崩有关系。

缓存雪崩

缓存雪崩是指比如我们给所有的数据设置了同样的过期时间,然后在某一个历史性时刻,整个缓存的数据全部过期了,然后瞬间所有的请求都被打到了数据库,数据库就崩了。

解决思路要么是分治,划分更小的缓存区间,按区间过期;要么是给每个key的过期时间加个随机值,避免同时过期,达到错峰刷新缓存的目的。

缓存刷新

说到刷新缓存,其实也有坑的。比如我之前的一份工作里,有一次大活动,正是如火如荼的时候,所有的广告位突然都变空白了。后来追查原因,所有的广告素材都在缓存里,然后起了个程序,专门负责刷新缓存,每次把当前的素材全量刷新。

坏就坏在这个全量上。因为大活动的时候流量极大,广告更新压力也很大,把负责提供更新素材的程序压崩了。刷新缓存的程序在请求时,收到了一个返回结果Null。接下来就喜闻乐见了,刷新程序根据这个null,清空了整个缓存,所有广告素材都失效了。

总之,想要做好高并发系统的缓存,就要考虑到各种边角情况,小心设计,任何细小的疏忽都可能导致系统崩溃。

1、具有1-5工作经验的,面对目前流行的技术不知从何下手,

需要突破技术瓶颈的可以加。

2、在公司待久了,过得很安逸,

但跳槽时面试碰壁。

需要在短时间内进修、跳槽拿高薪的可以加。

3、如果没有工作经验,但基础非常扎实,对java工作机制,

常用设计思想,常用java开发框架掌握熟练的,可以加。

4、觉得自己很牛B,一般需求都能搞定。

但是所学的知识点没有系统化,很难在技术领域继续突破的可以加。

5. 群号:高级架构群 Java进阶群:180705916.备注好信息!送架构视频。

6.阿里Java高级大牛直播讲解知识点,分享知识,

多年工作经验的梳理和总结,带着大家全面、

科学地建立自己的技术体系和技术认知!

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

推荐阅读更多精彩内容