缓存使用
一、本地缓存
1.说明
本地缓存 LocalCache,即 JVM 缓存,适用于存储访问频率高,缓存数据集又不是很大的场合,缓存类定义在 localcache.xml 里。
本地缓存又分为本地只读缓存、本地读写缓存两类。
本地只读缓存,要求缓存数据一次性全量加载,确保缓存 100% 命中。[推荐]
本地读写缓存,适合那些没法一次性全量加载的场合,采用按需加载方式,即先看缓存有没有,没有再查数据库或读文件,再将数据缓存起来。
2.本地只读缓存
业务级缓存类要求继承 AbstractReadOnlyCache,实现 loadData 接口,返回一个 Map
示例代码:
配置示例:
<localcaches>
<!-- 只读缓存,数据需要一次性全量加载。-->
<readonly>
<!--
className: 缓存实现类 (必配参数)
cronExpr: 缓存清理时间 (可选参数,默认不自动清空。)
init: 系统初始化时是否立即初始化缓存 (可选参数, 默认不初始化)
-->
<cache className="com.ailk.biz.cache.CacheTablesCache" cronExpr="30 1 * * ?" init="true" />
</readonly>
<readwrite>
......略
</readwrite>
</localcaches>
缓存定义示例:
public class CacheTablesCache extends AbstractReadOnlyCache {
@Override
public Map<String, Object> loadData() throws Exception {
Map<String, Object> rtn = new HashMap<String, Object>();
IDataInput input = new DataInput();
IDataOutput output = ServiceFactory.call("SYS_CacheTables_GetList", input);
IDataset datas = output.getData();
for (int i = 0, size = datas.size(); i < size; i++) {
IData data = datas.getData(i);
String tableName = data.getString("TABLE_NAME");
String version = data.getString("VERSION");
// 版本号只取"日时分", 格式:(DDHHMI),够用的情况下越短越好。
version = StringUtils.replaceChars(version, ":- ", "").substring(6, 12);
rtn.put(tableName, version);
}
return rtn;
}
}
使用示例:
// 获取版本号缓存
IReadOnlyCache cache = CacheFactory.getReadOnlyCache(CacheTablesCache.class);
String version = (String) cache.get(tableName);
3.本地读写缓存
配置示例:
<localcaches>
<readonly>
......略
</readonly>
<!-- 读写缓存,数据按需加载,采用LRU淘汰机制。 -->
<readwrite>
<!--
name: 缓存名 (必配参数)
maxSize: 最大缓存记录数 (可选参数,默认10000条)
cronExpr: 缓存清理时间 (可选参数,默认不自动清空。)
-->
<cache name="COMMON_CACHE" maxSize="10000" cronExpr="29 10 * * ?" />
</readwrite>
</localcaches>
使用示例
IReadWriteCache cache = CacheFactory.getReadWriteCache("COMMON_CACHE");
String cacheValue = cache.get(cacheKey);
if (null == cacheValue) {
cacheValue = ... // 查数据库或读文件
if (null != cacheValue) {
cache.put(cacheKey, cacheValue);
}
}
4.备注
CacheFactory类简介:本次缓存工厂类 。初始化时候,通过static静态块,自动加载localcache.xml配置文件,读取本地化的只读缓存和读写缓存配置。然后执行initReadOnlyCaches和initReadWriteCaches方法,获取缓存。代码如下:
public final class CacheFactory {
private static List<ReadOnlyCacheItem> readonlyCacheItems;
private static List<ReadWriteCacheItem> readwriteCacheItems;
static {
try {
CacheXml cacheXml = CacheXml.getInstance(); // 读取localcache.xml配置文件
readonlyCacheItems = cacheXml.getReadOnlyCacheItems();
readwriteCacheItems = cacheXml.getReadWriteCacheItems();
initReadOnlyCaches(readonlyCacheItems); // 初始化本地只读缓存
initReadWriteCaches(readwriteCacheItems); // 初始化本地读写缓存
} catch (Exception e) {
e.printStackTrace();
}
}
}
二、分布式缓存
1.说明
缓存数据是基于集群的异构分布式存放,一份数据只会存放在一个节点;
客户端通过 Key 的一致性 hash 算法唯一确定缓存节点,并按段存取;
当缓存节点退出或新增时,只会影响故障节点的数据,并将按需重新加载;
支持定时与实时的数据增量刷新;
自定义 Memcached 客户端,采用 Hessian 序列化 Java 对象;
通过客户端心跳线程对 MC 长连接做健康检测;
支持超大对象(>1M)的数据压缩(Gzip)存储。
注:这里着重介绍memcache
2.配置说明
配置示例:
<?xml version = '1.0' encoding = 'UTF-8'?>
<memcache>
<datacenter name="center1" >
<!-- 默认一中心的APP只连一中心的CCD,备节点在二中心 -->
<cluster name="codecode_cache">
<heartbeat-second>2</heartbeat-second>
<pool-size>5</pool-size>
<address master="IP1:11301" slave="IP3:11311" />
<address master="IP1:11302" slave="IP3:11312" />
<address master="IP2:11301" slave="IP4:11311" />
<address master="IP2:11302" slave="IP4:11312" />
</cluster>
<!-- 默认一中心的APP只连一中心的STATIC CACHE,备节点在二中心 -->
<cluster name="staticparam_cache">
<heartbeat-second>2</heartbeat-second>
<pool-size>5</pool-size>
<address master="IP1:11401" slave="IP3:11411" />
<address master="IP1:11402" slave="IP3:11412" />
<address master="IP2:11401" slave="IP4:11411" />
<address master="IP2:11402" slave="IP4:11412" />
</cluster>
</datacenter>
<datacenter name="center2" >
<cluster name="shc_cache">
<heartbeat-second>2</heartbeat-second>
<pool-size>5</pool-size>
<address master="IP1:11101" slave="IP3:11111" />
<address master="IP2:11101" slave="IP4:11111" />
<address master="IP3:11101" slave="IP1:11111" />
<address master="IP4:11101" slave="IP2:11111" />
</cluster>
</datacenter>
<!-- 指明服务连接的中心。注: 只支持后模糊匹配 -->
<server name="app-node01-*" connect="center1" />
<server name="app-node02-*" connect="center2" />
</memcache>
注:通过server的模糊匹配,找到配置节点。然后通过cluster的name,找到对应的一组缓存的地址和端口。
3.使用实例
IMemCache memCache = null;
memCache = MemCacheFactory.getCache("codecode_cache");
IDataset datas = (IDataset) memCache.get(cacheKey);
if (null != datas) {
// 如果memcache里面有,则直接返回
return datas;
} else {
// 如果没有,查询数据库获取,并放置到memcache中以便下次直接获取
IDataset datas = ccdao.queryList(sql, param, pagination);
memCache.set(cacheKey, datas);
}
注:文档来源于Wade官网缓存文档说明