开发框架-缓存架构设计

痛点 :

缓存的痛点在于提供一个机制,保证数据的一致性.即当源数据发生变化时,各级缓存如何同步刷新.

这点看似简单,但是由于业务系统对缓存使用的多样性导致缓存和源数据并非简单的一一对应关系,而是存在大量的多对多关系,这使得缓存更新的操作变得十分棘手.

比如你在用户登陆成功后,会缓存该用户的功能权限清单,这样不必每次都查询数据库,这个缓存涉及到用户角色关联表,角色功能点关联表这两个表.当修改角色的功能清单,或者维护用户所属角色时

你是无法直接得到应该刷新那些缓存的,而是反查该角色关联了那些用户.然后再刷新这些用户的功能权限缓存.

即使你这么做了,还有另外一个问题,即缓存的更新操作与缓存使用的数据结构有了很大的耦合性.你不得不忧心仲仲,因为业务系统每新增或者改变一种缓存的使用方式,你的维护缓存的刷新模块都要做出对应的改变.

当系统的缓存数据越来越多时,如何解耦是个大问题.

另一方面,还要保证各级缓存的平稳刷新.

缓存设计两个方面,缓存的建立,缓存的更新.

实现:

所有字典表(很少修改的类固化数据)都直接缓存到redis中.

cache-api逻辑为:内存无找redis,redis无找数据库

其中内存有还要看redis中版本是否过期,过期使用redis中的缓存刷新内存.

字典维护模块负责刷新redis缓存

  • 进阶:

运维支持工具-缓存管理器:

查询所有缓存及其数据,缓存使用效率等.

提供人工补偿机制手动刷缓存,保证缓存和数据一致性

提供自动校验一致性功能,自动对比缓存和数据库数据的一致性.

缓存定义:

redis:三级缓存

应用内存区:二级缓存

查询结果缓存:一级缓存

查询结果缓存是二级缓存之上的缓存,比如二级缓存中有一个所有医生字典表(所有机构的医生),业务一般会按机构查询该机构下所有医生一级缓存会按机构进一步缓存该机构对应的所有医生,

这样下次还是查询该机构医生时,会直接使用一级缓存,节省遍历查找二级缓存的时间.

针对一级缓存需要提供LRU算法,防止内存爆掉.

问题:

缓存雪崩问题:

当缓存过期时,会大量请求发现缓存过期,会同时要求刷新缓存,从而导致雪崩

解决方案是使用trylock对获取最新缓存动作加锁,一个请求如果获取不到锁立刻返回,然后继续使用旧的缓存先顶着,下一个请求来时再次尝试获取新的缓存数据,(有必要可以设定一个再次尝试时间间隔),直到获取到.

该方案会出现各个应用缓存一致性的延迟为代价.

 

posted @ 2017-03-21 16:03  java林森  阅读(240)  评论(0)    收藏  举报