为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); } } }