
世界最大混合云的总架构师,4年前,开始作为双11阿里云技术负责人,负责搭建全球最大的混合云结构,把 “双11”的电商业务和技术场景在阿里云上实现,并保障这个混合云在双11当天能够满足全球客户的购物需求。
正文
相信很多研发同学都有过引入缓存进入到应用架构设计中的经历,本文从几个角度阐述一些选型误区和使用误区以及高阶使用技巧等,供开发者参考。
1. 什么情况下开始考虑缓存?
缓存的主要目的是为了挡一些读多写少的用户请求,且数据在一定时间周期内保持不变,再且业务允许一定时间差而导致的脏数据。假设你的业务直接读写持久化存储(比如mysql)的压力不大,换言之持久化存储的水位还较低可控范围内,那么不建议引入缓存,不但增加了一道依赖提高了系统复杂度,而且并没有带来可观的解决问题收益。引入缓存是为了提高系统承载能力且有效减少对后端持久化存储的冲击。遵循架构简单适用的原则,不要为了使用缓存而使用。
2. 确定引入缓存后我该如何设计内部数据结构和缓存服务架构?
先说缓存数据结构,这里往往存在使用误区,不少开发者将大字节key-value型数据写入缓存系统,业务频繁读取,那么问题来了,从普通缓存服务器的网卡能力来看,几K甚至几十K大小的key-value,QPS上不了多少就会打爆网卡,因此数据大小遵循小够用原则,而不是什么都往里面放。
另外内存型缓存更关注整体内存使用量,业务的key数量以及平均key大小跟内存之间的博弈,同时务必合理设置数据过期时间。不推荐复杂数据结构和时间复杂度高的操作,比如redis的执行时间为O(N)的指令集。最后最重要一点切记把内存型缓存当做持久存储对待,从应用系统设计上内存型缓存是要考虑随时丢失的场景。
至于缓存服务架构如何选择,有几种供参考,单master模式,master-slave模式(快速切换),集群模式(有必要进行业务数据分片)等。外加运维管控系统,常见的缓存服务结构:

Figure 3来源阿里云ApsaraDB for Redis
3. 几种高阶使用场景介绍
针对一些常见的缓存大规模使用场景,介绍几例高阶的用法:
一、 大流量下缓存前置架构以提高服务性能。比如APP_A请求APP_B,正常路径从APP_A → APP_B → Cache,前置做法简单的说是APP_A内嵌APP_B的client,以达到直接读取Cache,请求不经过APP_B。这儿也有个问题,APP_B的研发同学需要把控好plugin到APP_A的客户端,比如权限的收放,哪些可以在客户端里做,哪些操作不能在客户端侧做,根据业务实际场景斟酌。
二、 SmartClient智能客户端。客户端可以根据配置变更动态做出变化,比如QPS限流,白名单等等策略,通过配置动态更新通知客户端做相应的预期调整。举个例子,流量突增导致缓存压力过大,通过配置变更使得客户端部分读缓存改为走读mysql,有效分担缓存系统压力。
三、 复杂缓存失效场景如何解?除了根据业务场景主动设置数据过期时间,还有几种情况,比如因数据请求更新mysql完毕,同时应用触发更新cache数据以达到缓存和mysql的数据一致性,此外假设还有跨机房集群而需要多个集群失效保持同步,一般会通过主动失效服务来做多侧的同步失效。如图中的“失效中心”角色:

Figure 4来源阿里巴巴内部业务系统
网友评论