为saiku加入redis缓存

下面是两个缓存的例子,分别用内存和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 缓存的步骤如下:

  1. 实现接口 SegmentCache
  2. 修改配置文件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);
            }
        }
}

Comments

comments powered by Disqus