背景
平台里面有一些数据会经常被访问,比如:菜单的链接、数据字典、常用配置等,而且不会发生频繁的改动,这些数据都应该考虑加入缓存来优化查询速度,避免频繁地从数据库直接查询获取。那在我们常见的应用中有哪些常见的缓存呢?
常见缓存
EhCache
Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。
Memcache
Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。
Redis
Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
缓存设计
上述介绍的都是几种常用的缓存容器,但是在平台的缓存设计上,我们更倾向于用接口的方式来使用,便于根据不同规模来切换不同的缓存容器。
在设计之前要说一句
无论何时何地,缓存与物理数据必须一致性。--王小七
核心设计
通过采用AOP拦截代理方式,设计实现类似spring cache的方式来实现平台的缓存,支持注解扫描和配置文件解析、以及手动设置缓存的方式。
类说明
CacheValueProcessor
方法拦截处理类,主要用来判定方法是否启用缓存配置,从而进一步确认缓存的读取或设置。此处采用责任链模式,用于对拦截的方法检测是否启用注解或文件配置中的方法。
IKeyParser
缓存key表达式解析类,类似spring的el表达式,一般数据缓存都有一些特别标识,有些可能来源于传入的参数,比如:菜单(menu),组织(unit)、数据字典(dict、dict_xxxx),通过动态运算出某种特征的标识key。
IResultParser
缓存值解析类,不同的方法的返回值可能不一样,比如:map、list、object或者其他自定义类,通过对缓存返回的结果做动态转换为调用者可以接收的返回格式。
CacheAPI
缓存容器类,用来装载缓存、写入缓存、读取缓存和移除缓存的关键缓存操作类,可以接入Encache、Jedis等缓存工具类。