一个基于 Groovy 闭包实现的低侵入缓存设计

缓存技术是目前很常用的一种技术,当你的系统的并发访问到达一定数量级后,后台的数据库就难以应付了,需要考虑缓存技术,但缓存又会涉及到如何跟数据库保持数据同步的问题。这篇文章介绍一个基于 Groovy 闭包技术实现的低侵入方案。

基本设计思路

读取数据时优先从缓存读取,缓存没有时从数据库读取,同时写到缓存中,隔一定时间后触发缓存刷新。

实现说明

定义一个统一的服务方法

这个服务方法能同时完成基本设计思路里的几个方面,这个服务方法名字为 getLazyCache,参数分别是:

cacheKey:缓存 key 名;
refreshClosure:获取对应数据的闭包方法;
closureParams:闭包方法需要的参数,是 Map 类型;
expireSeconds:缓存超时时间,单位是秒,缓存服务器会自动清除超时的缓存;

使用示例

1
2
3
4
5
6
7
8
9
10
//先定义一个闭包方法,方法里写读取数据库数据的代码,下面的例子是根据传参 appId 通过 Grails 的 GORM 方法查询数据,
//并转成 JSON 格式,以 String 类型返回(这是为了方便保存到 Redis 缓存里,采用 JSON 格式序列化数据)。
def refreshClosure = { paramsMap ->
def appId = paramsMap.appId
return String.valueOf(AppInfo.findAll('from AppInfo where id = ?', [appId]) as JSON)
}

def closureParams = ['appId': 'test_app_001']

def cacheValue = getLazyCache('CACHE_' + closureParams.appId, refreshClosure, closureParams, 300)

上面就是使用方法,很简单,而且能自己定义读取数据库数据的方式,getLazyCache 会先根据 cacheKey 去缓存中查是否存在,存在就直接返回,不存在就调用 refreshClosure 这个闭包方法重新读取,读取后写到缓存并返回。

getLazyCache 实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def getLazyCache(cacheKey, refreshClosure, closureParams, expireSeconds) {
//getCache 是一个已有的读取缓存的方法,这里直接调用
def cacheValue = getCache(cacheKey)

//如果查不到缓存就调用刷新缓存的闭包方法读取数据,并写到缓存
if (cacheValue == null) {
//调用闭包方法
cacheValue = refreshClosure.call(closureParams)
//putCache 是已有的方法,写缓存,并设置超时时间
putCache(cacheKey, cacheValue, expireSeconds)
}

return cacheValue
}

总结

以上就是整个实现方案,清晰易懂,而且对已有代码影响比较小,能够快速实现缓存功能,大大提高系统的并发容量。