架构之缓存设计
缓存可以是本地缓存,也可以是分布式缓存;可以自己写个简单的程序,也可以搞个复杂的独立系统作为缓存;可以使用各种复杂的算法,也可以只使用简单的全量缓存;可以使用各种失效机制,也可以只支持人工刷新。缓存重点在于技术,但缓存的难点在于分析哪些数据可以缓存,以什么样的策略缓存。有些数据一看就是可以缓存的,比如参数数据;但如果给参数加个限制条件,比如虽然参数修改很少,但一旦修改就需要在系统调用时实时生效,那这种情况下是否还可以缓存?下面试着选择一些常用的场景来分析是否可以使用缓存。
1、系统参数数据,修改频率非常低,一般由开发人员修改
系统参数是由开发人员修改的参数,开发人员每次修改后,可通过人工刷新缓存参数即可,只需要提供一个手工刷新的页面,让开发人员在更改了系统参数后手工刷新即可。
2、业务参数数据,很少修改,修改后一定时限内生效(比如一小时后生效,或隔日生效等)
这种场景下,除非系统无性能要求,一般都会对参数数据进行缓存。参数数据因为有个特点就是数据量较小,故一般就是全量缓存,一次刷新,无需设置失效时间。缓存的刷新机制也相对比较简单,一般可以通过写一个定时刷新程序每一小时或每天全量刷新一次缓存。或者也可以通过设置失效时间,直接在刷新缓存数据时设置缓存数据的失效时间是一个小时以后或当天23点59分59秒,这样当一小时后或第二天查询参数时发现已经失效就自动刷新一次。
3、业务参数数据,很少修改,修改后必须立即生效
这种场景下,如果没有性能瓶颈,那就不做缓存了,系统设计越简单越好。但如果确实存在性能瓶颈,那就必须做缓存了。这种情况乍一看没法缓存,但我们分析一下,业务参数是会修改且立即生效,但修改的是很少的参数,绝大部分参数还是不会被修改的,在很长时间内是不变的,是可以缓存的。在这种情况下,失效时间和定时刷新机制已经不适合了,需要引入新的实时刷新机制,可以考虑消息机制来通知缓存的刷新。当业务参数改变后,发送消息通知缓存系统或缓存功能立即刷新缓存,这样做当然是侵入了业务代码,但为了提升性能也只能这样了。
4、多个传入参数计算后的结果数据
这些数据一般由多个传入参数经过较为复杂的业务逻辑计算后得到结果,这些结果数据是后续业务的传入参数,比如策略计算结果。这种情景中,如果存在性能问题,则需要对计算结果进行缓存,可以将传入参数组合的hash值或MD5值作为key缓存计算结果,这样当下次同样的传入参数组合就只需要从缓存中获取计算结果即可,这样的缓存一般情况下量会比较大,可以考虑使用分布式缓存系统或者使用在本地使用替换算法来控制缓存的数量。这种缓存数据在计算逻辑不变更的情况下是不需要更新的,只有当计算逻辑变更的情况下,需要刷新缓存,如果全量比较大,可以考虑给这类数据按照计算逻辑编制成组,在计算逻辑变更后刷新此计算逻辑影响到的组的缓存数据即可。还有一种办法就是预热,一般业务计算逻辑变更就需要上线,会有足够的时间预热缓存。
5、部分业务数据的缓存
业务数据要缓存,这个看起来是不可能的。但有时候系统性能硬逼着必须使用缓存,比如并发性非常的高,数据库访问性能已经无法跟上,否则会导致数据库的崩溃。这种情况下,必须对业务数据进行分析,可能对所有的业务数据缓存不太可能,但是否可以缓存部分,这需要细致的分析。比如业务进度查询这个功能,我们来分析一下,进度查询功能对客户来讲,一般是查询最近一段时间内的进件的进度,这种查询量可能占到了查询量的绝大部分,那么我们可以将最近这段时间的进度信息缓存起来,以提升查询的性能。但最近时间的进件,其进度信息也是修改频率最高的,那么如何在这种矛盾下提升这些数据的查询性能?这就是难点所在。业务和数据分析以及对数据分类处理是解决这种矛盾的一个有用手段,通过业务和数据的分析,肯定能找到这个平衡点。