未加星标

记录一次缓存设计

字体大小 | |
[数据库(综合) 所属分类 数据库(综合) | 发布者 店小二05 | 时间 2019 | 作者 红领巾 ] 0人收藏点击收藏
缓存设计的意义

当我们在设计系统时,项目的初期一般不会考虑缓存的设计,理由大致是一开始业务增长缓慢,不会有太多的请求量,系统的负载问题没有那么突出。当业务不断增长,服务端请求量激增导致系统对底层存储(SQL or NoSQL等)读写数据压力增加,这时我们缓存的接入就十分必要。一方面缓存可以是in memory的一块存储空间,在单点的服务上缓存获取到请求及对应的响应(当然一套分布式的同步机制也是可以的,这里略过);另外缓存可以是第三方的内存存储,如Redis,通过redis提供的各类数据string、set、hashmap、zset等来缓存需要的数据。

缓存的接入可以有效的保护请求穿透,减轻对底层DB的压力(这里分库分表不合理或者业务存储不分离,很可能是灾难式的全站崩溃);同时对于用户的体验可以得到有效的保障,一个页面每加载多1s,用户的流失就多了x%,超过3s的话基本就只有一半的留存了。

但是缓存的设计与具体的业务息息相关,盲目使用不贴合实际场景的缓存总归不是最理想(比如缓存的数据结构不是最终数据,服务端需要做中间处理,同样会给系统带来不小的计算开销),因此对自身业务的理解对于缓存设计也是至关重要。这里可以看一篇美团团队在 DSP系统中的缓存设计 。

实际场景

这里介绍在实际工作中遇到的一个具体的缓存设计场景,最开始的目标是使得系统更加稳定,不需要因为请求压力天天收各种告警导致神经衰弱,到现在也希望这套系统未来是可适配可插拔的一套业务缓存系统。

先来描述下业务场景,我们需要展示的数据在一段时间内是不断变化的,有时候数据的变化在10s内;当超过一段时间后(一般是1-2天),数据访问的热度会下降,在相当长的一段时间里偶尔会有一些“长尾”的访问(这里指用户会不定时重新访问数据并有可能是一波突增的流量)。同时访问量在热点时期预计是在百万的并发。

方案1 hit + cache

项目开始阶段,我们的设计是直接使用共用的一套小型的redis集群,对于业务请求有一定的预估,架构图如下:


记录一次缓存设计

单点缓存.png

当用户请求进来后,我们从redis中读取,当读取不到时再从DB中读取返回给用户,并将数据做缓存。

优点:开发相对简单,都是CRUD的操作,不需要过度设计

缺点:数据实时性不太好,数据的TTL需要设置比较短,来保障数据过期可以重新获取最新的数据;同时如果是并发访问的场景,有可能在一开始会有大量请求击穿我们的服务到达DB


记录一次缓存设计

缓存击穿.png

方案2 API与缓存层分离

基于方案1中数据实时性和击穿的问题,第二版的缓存我们将API层与缓存层分离开,架构如下:


记录一次缓存设计

缓存解耦.png

API层负责接收请求,读取redis,判断数据是否存在,当数据不存在时,会在本地做随机等待(最多等待300ms)同时告知缓存层需要开启的缓存任务,等待缓存任务完成返回数据并回包,之后的请求再从redis直接取数据回包(这里的完成通知是用golang的sync.Cond来实现的)。这里所有访问相同数据的请求都会进入等待状态,等缓存完成统一通知回包。这样可以防止方案1里的穿透的问题,同时缓存任务来保障数据第一时间更新。

缓存层接收API(这里是抽象设计)传递的缓存请求,针对数据开启缓存任务,这里我们认为有用户访问就是热点数据,会定时刷新数据进入redis。

优点:API层内聚性比之前更好一些,不需要关心缓存实时性;缓存层来管理所有的缓存任务,可以对过时的数据做淘汰(这里我们根据数据的热度判断,一般数据在1-2天后会进入所谓的“长尾”周期)

缺点:缓存层同时启动所有的缓存任务执行,其实某种意义上也是对DB产生大量的读请求;同时缓存层的db连接池内临时连接数增多,内存开销增大。

方案3 缓存层缓存策略优化

先上架构图:


记录一次缓存设计

缓存层优化.png

缓存层对不同类型的数据,会启动不同的随机定时器保证优先级高(更新频繁)的数据能优先执行,不活跃的数据我们降低权重做更新,并且淘汰(停止缓存任务)的权重也更高。任务入口从之前的rpc调用改为从消息队列消费任务,和之前设计成通用可插拔的缓存系统有关系,不同的业务层可以在缓存层配置自己的任务,对应的原始数据DB,如果存储缓存结构,优先级是如何?

cache对应相同类型的数据缓存任务,后续将配合访问频次采用LRU(Least Recently Used)的算法来做淘汰,进而优化配置的(相对固定)缓存任务过期时间。

结束语

缓存的方案多种多样,google一下有很多的架构设计与方案解释。适用于业务的才是最好的,了解缓存在系统演化过程中的角色和各个业务阶段中缓存的设计,对于真实的应用场景个人觉得不需要过度设计,虽说顶层设计看对系统未来的规划能力,但不是一步到位,这样往往会事倍功半。

参考内容:

https://tech.meituan.com/cache_about.html

https://coolshell.cn/articles/17416.html

本文数据库(综合)相关术语:系统安全软件

代码区博客精选文章
分页:12
转载请注明
本文标题:记录一次缓存设计
本站链接:https://www.codesec.net/view/627926.html


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 数据库(综合) | 评论(0) | 阅读(42)