为saiku加入redis缓存
Table of Contents
下面是两个缓存的例子,分别用内存和cdc作为缓存
public class MemorySegmentCache implements SegmentCache {
// Use a thread-safe map because the SegmentCache
// interface requires thread safety.
private final Map<SegmentHeader, SoftReference<SegmentBody>> map =
new ConcurrentHashMap<SegmentHeader, SoftReference<SegmentBody>>();
private final List<SegmentCacheListener> listeners =
new CopyOnWriteArrayList<SegmentCacheListener>();
实现mondrian 缓存的步骤如下:
- 实现接口 SegmentCache
- 修改配置文件mondrian.properties,指定自定义的缓存实现类
############################################################################### # Boolean property that controls whether the data from segments # is cached locally. To create custom caches, look for the # SegmentCache SPI. # mondrian.rolap.star.disableLocalSegmentCache=true ############################################################################### # Property which defines which SegmentCache implementation to use. # Specify the value as a fully qualified class name, such as # org.example.SegmentCacheImpl where SegmentCacheImpl # is an implementation of mondrian.spi.SegmentCache. # mondrian.rolap.SegmentCache=.cache.redis.RedisSegmentCache
基于redis 的 mondrian 缓存实现
实现的思路应该和基于内存的缓存类似,我们需要根据ConcurrentHashMap<SegmentHeader, SoftReference<SegmentBody>>设计出redis的数据结构
如何设计redis的数据结构请参考这篇文章.
public class RedisSegmentCache implements SegmentCache{
private static final Logger log = Logger.getLogger(RedisSegmentCache.class);
private final List<SegmentCacheListener> listeners =
new CopyOnWriteArrayList<SegmentCacheListener>();
public SegmentBody get(SegmentHeader header) {
RedisDao map =
(RedisDao)DashBoardContext.getBean("redisDao");
if(header==null)
return null;
final byte[] ref = map.get(Md5Utils.md5sum(header.toString()));
if (ref == null) {
try {
this.remove(header);
} catch (Exception e) {
log.error("SegmentBody get error:"+e.getMessage());
}
return null;
}
final SegmentBody body = (SegmentBody) SerializeUtil.unserialize(ref);
if (body == null) {
try {
this.remove(header);
log.info("RedisSegmentCache execute body == null,this.remove(header)!");
} catch (Exception e) {
log.error("SegmentBody get error:"+e.getMessage());
}
}else{
Map valuemap = body.getValueMap();
if(valuemap==null||valuemap.size()==0){
this.remove(header);
log.info("RedisSegmentCache execute valuemap==null||valuemap.size()==0,this.remove(header)!");
}else{
log.info("RedisSegmentCache execute get sucess!");
}
}
return body;
}
public boolean contains(SegmentHeader header) {
if(header==null)
return false;
RedisDao map =
(RedisDao)DashBoardContext.getBean("redisDao");
final byte[] ref = map.get(Md5Utils.md5sum(header.toString()));
if (ref == null) {
return false;
}
final SegmentBody body = (SegmentBody) SerializeUtil.unserialize(ref);
if (body == null) {
try {
this.remove(header);
} catch (Exception e) {
log.error("SegmentBody contains error:"+e.getMessage());
}
return false;
}
log.info("RedisSegmentCache execute contains sucess!");
return true;
}
public List<SegmentHeader> getSegmentHeaders() {
return null;
}
public boolean put(final SegmentHeader header, SegmentBody body) {
assert header != null;
assert body != null;
RedisDao map =
(RedisDao)DashBoardContext.getBean("redisDao");
try {
map.put(Md5Utils.md5sum(header.toString()), SerializeUtil.serialize(body));
} catch (Exception e) {
log.error("SegmentBody put error:"+e.getMessage());
}
fireSegmentCacheEvent(
new SegmentCache.SegmentCacheListener.SegmentCacheEvent() {
public boolean isLocal() {
return false;
}
public SegmentHeader getSource() {
return header;
}
public EventType getEventType() {
return SegmentCacheListener.SegmentCacheEvent
.EventType.ENTRY_CREATED;
}
});
log.info("RedisSegmentCache execute put sucess!");
return true; // success
}
public boolean remove(final SegmentHeader header) {
if(header==null)
return false;
RedisDao map =
(RedisDao)DashBoardContext.getBean("redisDao");
boolean result = false;
try {
result = map.remove(Md5Utils.md5sum(header.toString())) != null;
fireSegmentCacheEvent(
new SegmentCache.SegmentCacheListener.SegmentCacheEvent() {
public boolean isLocal() {
return true;
}
public SegmentHeader getSource() {
return header;
}
public EventType getEventType() {
return
SegmentCacheListener.SegmentCacheEvent
.EventType.ENTRY_DELETED;
}
});
}catch (Exception e) {
log.error("SegmentBody remove error:"+e.getMessage());
}
log.info("RedisSegmentCache execute remove sucess!");
return result;
}
public void tearDown() {
RedisDao map =
(RedisDao)DashBoardContext.getBean("redisDao");
map.clear();
listeners.clear();
log.info("RedisSegmentCache execute tearDown sucess!");
}
public void addListener(SegmentCacheListener listener) {
listeners.add(listener);
}
public void removeListener(SegmentCacheListener listener) {
listeners.remove(listener);
}
public boolean supportsRichIndex() {
return true;
}
public void fireSegmentCacheEvent(
SegmentCache.SegmentCacheListener.SegmentCacheEvent evt)
{
for (SegmentCacheListener listener : listeners) {
listener.handle(evt);
}
}
}