缓存上线之前不做预热,头一个小时全靠数据库硬撑
新系统上线、大促开场、缓存整体重启,这几种时候缓存里是空的。所有请求都要回源,数据库在头几十分钟里承受的,是平时的几倍甚至十几倍。一、什么时候需要预热
不是所有场景都要。访问分散、数据量小的系统,慢慢填也能撑住。访问集中、单条数据又重的系统,不预热就很容易在开场那几分钟卡住。判断的依据是回源量和库的余量。库的余量按峰值算,别看平均值,平均值好看的时候峰值早就顶满了。压测出来的峰值和线上的峰值往往不一样,以前者的七成做判断,留出的余地才够。键的数量增长要按月看,涨得快的业务,容量规划要提前做,别等打满了才申请机器。
重启之后也一样。缓存服务恢复,里面的数据是空的,这时候流量如果全放进来,等于让库独自面对全部请求。恢复流程里必须带上预热这一步。这一步要写进值班手册,夜里重启的人不一定记得住。监控面板上除了命中率,还要放上平均耗时和错误数,三个一起看才知道问题出在哪一段。
二、预热的顺序
按访问量从高到低排,先装靠前的那一批。头部的一小部分键,往往承担了大半的请求,把它们先装进去,命中率很快就上来了。剩下的按需回源,慢慢补齐。排序的依据用上一周的访问日志,别凭感觉挑。
装的时候要控制速率,分成小批,每批之间留间隔。一口气刷几十万条,网络和缓存节点都会被占满,反而影响正常请求。速率按每秒多少条来控制,别按批大小估,批与批之间的间隔也要算进去。缓存是手段不是目的,能把查询本身优化好,需要缓存的数据量自然会少下来。
三、清单从哪儿取
可以从库里的热点表导,也可以从上一轮的访问日志里取。日志更贴近真实,知道哪些键真的被读过;库里导更完整,适合新上线还没有日志的系统。两种结合着用比较稳。
导出来的清单要去重、要过滤。已经下架的商品、已经删除的内容,装进去只会占内存,还会让后续的请求读到不该读的东西。过滤的规则跟业务确认一遍,下架和删除的口径经常不一致。缓存的读写比例要定期看,读多写少才适合放进来,比例反过来的,缓存带来的好处抵不上维护成本。
四、预热和一致性的关系
预热的这段时间,数据可能还在变。装进去的值到了上线那一刻未必准。做法是给预热的数据设一个较短的过期时间,让它在运行中自然刷新,别指望一次装到位。
涉及价格、库存这类字段,宁可少装一点,让它在真实请求里回源取新值。预热的目的是挡流量,不是为了把数据搬完。装多装少都要记一笔,事后才知道预热到底覆盖了多少请求。覆盖的比例可以按访问量加权算,不按键的数量算,头部那批键的权重本来就高。同一个业务的不同接口,缓存时长可以不一样,按各自能接受的旧数据时间来定,别一刀切。
五、怎么确认预热有效
看命中率的爬升曲线。正常情况下一两分钟内就应该到六七成,如果长时间趴在低位,要么是键的规则不对,要么是装进去的键和实际请求的对不上。
再看库的负载。预热做到位,开场时的连接数和查询量应该明显低于不预热的情况。这两个数字对比一次,就知道这一步值不值得做。两次的数字要留在同一个地方,下一次上线还能拿出来比。差别不明显的时候别急着否定这件事,先看预热覆盖的那批键,是不是正好是流量的主体。缓存里放的东西要能重建,丢了不至于影响业务,需要长期保存的数据,源头应该在库里。
六、把它写进流程
预热不该靠人记得,要写进上线的步骤里:什么时候执行、执行多久、失败了怎么办。写进流程的事才会被执行,靠记忆的事迟早会漏。
失败的兜底也要有。预热没跑完就上线,等于没做。宁可延后几分钟开场,也别让库在没有任何缓冲的情况下接住全部流量。压测的时候把缓存关掉跑一遍,知道没有它系统能撑多少,这个数字在出事的时候很有用。
预热是件笨功夫,投入不大,效果直接。愿意在这一步上花时间,后面的很多问题根本不会发生。把这一步做成例行操作,比每次临时安排人去做可靠得多。 看完感觉打开了新思路,以后遇到类似情况知道该怎么处理了。 看完很有启发,也引发了我不少思考,有空也想分享下自己的看法。 讨论氛围很好,大家都在理性交流,这样的论坛环境太舒服了。 很多建议都很接地气,能直接用在生活或工作中,实用性很强。 很多细节都考虑到了,看得出来是真正懂行的人在认真分享。 每一段都很有分量,认真读完全篇感觉整个人都提升了不少。
页:
[1]