dryr

系统中的缓存设计

    系统架构设计中有一个很重要的要素,就是缓存设计。纵观目前流行的框架和系统,可以说基本都有缓存设计,通过缓存来解决性能、一致性等问题已经成为基本设计理念了。一个较为庞大的系统中如果没有任何的缓存设计,那是一件让人吃惊的事情。
    缓存设计的本质是用空间换时间,如果空间足够,将所有数据缓存在内存中都是可以考虑的,比如内存数据库。但在实际情况中,往往是需要权衡取舍的,需要分析出最需要缓存的数据(比如使用频率较高的数据,查询速度较慢的数据,对性能影响较大的数据等),虽然有难度,但这也正是设计魅力所在,所谓不取舍就无设计啊。
    缓存设计的主要目的是提升性能,这个就无需多说了;有时候也可能是为了保持数据一致性和完整性方面的考虑,比如在一个批处理程序中,为了在处理任何一笔数据时都能使用相同的参数,则需要在每次批次开始阶段将参数缓存起来,以确保批次处理过程中参数保持不变。
    缓存设计的基本前提是被缓存数据在一个时间段内是不变的,只有时间段内不变的数据才有缓存的必要(为保持一致性和完整性的缓存除外)。
    在缓存设计时需要对缓存数据进行分类,每一类数据的缓存策略可能是不同的,最简单的缓存过期时间可能是不同的,比如系统参数是每天更新一次的,而业务参数则是每小时更新一次,甚至有些业务数据是10分钟更新一次的,设计时相应的缓存过期时间也是不同的。
    缓存作为暂时存储的数据,必然需要有一个刷新机制,而缓存是否需要刷新则取决于缓存是否已经过期,所以缓存的过期时间是一个非常关键的属性。过期时间的设计需要考虑很多方面,比如需考虑数据更新频率(是每天更新一次还是每小时更新一次),也需要考虑各类参数刷新时间的错开,防止雪崩效应(在大规模数据缓存的系统才需要考虑此问题,在一般系统中不会出现),另外还要考虑是否有特殊事件,比如有些参数有一个发布机制,只有参数发布后参数才生效,对于这类数据可考虑在发布等特殊事件时刷新缓存,这是最简单有效的办法。
    缓存是个系统工程,在大数据量和多层结构的系统中,可考虑使用多层缓存技术,即在系统的每个层次结构上都可能缓存数据,上层结构的系统通过缓存的过期时间来判断缓存是否过期,没有过期则不访问下层系统更新数据,过期后再访问下层系统来更新缓存(对类似特殊事件触发刷新的缓存数据,不大适合使用这种方法多层缓存),这样可以大大降低上下层系统间的交互和通讯频率,从而提高性能。
    缓存刷新方式也可以分为主动式和被动式。主动式是在使用缓存时判断缓存是否过期,如果过期则主动刷新缓存,主动式刷新控制比较精准,但只能刷新自身,从管理角度看比较分散;而被动式则通过另一个线程轮询各类缓存,通过判断各类缓存是否过期来确定是否刷新缓存,被动式刷新因为是轮询,故肯定存在时间上的偏差,理论上存在使用到过期缓存数据的情况,但此方式可以将所有缓存集中统一管理,这是它的优点。
    缓存设计中,还有两个必须考虑的问题,就是缓存穿透和雪崩效应。针对缓存穿透问题,可以通过罗列所有缓存数据类的方式来解决,比如系统中缓存了两类参数,一类是产品参数,一类是销售人员参数,那么当客户端来刷新除这两类参数外的其他参数比如门店参数时,系统可以判断出门店参数并不在缓存的类别列表中,故无需去刷新缓存,直接返回空或错误即可。雪崩效应前面也说了,只有较大数据规模缓存的系统才有可能出现此问题,一般系统不会出现,针对此问题,只有在设计各类缓存数据过期时间时考虑时间上岔开,不要在同一时间多类参数同时刷新,从而避免导致后台系统或数据库的崩溃。
    说了很多,但最重要的是动手做,在系统设计时实现缓存,这才是王道。


参考文章:《淘宝应对"双11"的技术架构分析》

评论