2013-07-08 4 views
0

Я пытаюсь реализовать Mondrian SegmentCache. Кэш должен делиться несколькими JVM, работающими с библиотекой Mondrian. Мы используем Redis в качестве хранилища резервных копий, однако для целей этого вопроса любое постоянное хранилище ключей должно быть прекрасным.Реализация Mondrian shared SegmentCache

Будет ли сообщество stackoverflow помочь выполнить эту реализацию? Документация и поисковые запросы Google не дают достаточного уровня детализации. Здесь мы идем:

new SegmentCache { 

    private val logger = Logger("my-segment-cache") 
    import logger._ 

    import com.redis.serialization.Parse 
    import Parse.Implicits.parseByteArray 
    private def redis = new RedisClient("localhost", 6379) 

    def get(header: SegmentHeader): SegmentBody = { 
     val result = redis.get[Array[Byte]](header.getUniqueID) map { bytes ⇒ 
      val st = new ByteArrayInputStream(bytes) 
      val o = new ObjectInputStream(st) 
      o.readObject.asInstanceOf[SegmentBody] 
     } 
     info(s"cache get\nHEADER $header\nRESULT $result") 
     result.orNull 
    } 

    def getSegmentHeaders: util.List[SegmentHeader] = ??? 

    def put(header: SegmentHeader, body: SegmentBody): Boolean = { 
     info(s"cache put\nHEADER $header\nBODY $body") 
     val s = new ByteArrayOutputStream 
     val o = new ObjectOutputStream(s) 
     o.writeObject(body) 
     redis.set(header.getUniqueID, s.toByteArray) 
     true 
    } 

    def remove(header: SegmentHeader): Boolean = ??? 

    def tearDown() {} 

    def addListener(listener: SegmentCacheListener) {} 

    def removeListener(listener: SegmentCacheListener) {} 

    def supportsRichIndex(): Boolean = true 
} 

Некоторые немедленные вопросы:

  • является SegmentHeader.getUniqueID соответствующий ключ для использования в кэше?
  • как должен быть реализован getSegmentHeaders? Текущая реализация выше просто выдает исключение и, кажется, никогда не называется Mondrian. Как заставить SegmentCache повторно использовать существующие записи кеша при запуске?
  • как addListener и removeListener предназначенный для использования? Я предполагаю, что они имеют какое-то отношение к координации изменений кэша между узлами, использующими кеш. Но как?
  • что должно supportsRichIndex возвращение? В общем, как кто-то, внедряющий SegmentCache, знает, какую ценность вернуть?

Я чувствую, что это основные проблемы, которые должны быть освещены в документации, но они не являются (насколько я могу найти). Возможно, мы можем исправить отсутствие доступной информации здесь. Благодаря!

ответ

2

является SegmentHeader.getUniqueID соответствующим ключом для использования в кеше?

Да и нет. UUID удобен в таких системах, как memcached, где все сводится к сочетанию клавиш/значений. Если вы используете UUID, вам нужно реализовать поддержку RichIndex() как false. Причина этого в том, что исключенные регионы не являются частью UUID. Это по дизайну по уважительным причинам.

Что мы рекомендуем это реализация, которая сериализует SegmentHeader (он реализует сериализуемый и Hashcode() & Equals()) и использовать непосредственно в виде двоичный ключа, который вы распространяющиеся, так что он сохранит недопустимые области и держать все красиво в синхронизации.

Вы должны посмотреть, как мы реализовали его в default memory cache.

Существует также implementation using Hazelcast.

Мы в Пентахо также использовали Infinispan с большим успехом.

Как должно быть реализовано устройство SegmentHeaders?

Опять же, взгляните на реализацию по умолчанию в памяти. Вам просто нужно вернуть список всех известных SegmentHeader. Если вы не можете предоставить этот список по какой-либо причине, либо потому, что вы использовали UUID только, либо потому, что ваш бэкэнд для хранения не поддерживает получение списка, например memcached, вы возвращаете пустой список. Mondrian не сможет использовать накопительный пакет в памяти и не сможет делиться сегментами, если только он не попадает в нужные UUID в кеше.

Как использовать addListener и removeListener?

Mondrian должен быть уведомлен о появлении новых элементов в кеше. Они могут быть созданы другими узлами. Mondrian поддерживает индекс всех сегментов, о которых он должен знать (таким образом, позволяя выполнять операции в оперативной памяти), поэтому это способ распространения обновлений. Вам нужно свернуть бэкэнд с примерами Мондриана. Взгляните на how the Hazelcast implementation does it.

Идея заключается в том, что Mondrian поддерживает пространственный индекс известных в настоящее время ячеек и будет запрашивать только необходимые/отсутствующие ячейки из SQL, если это абсолютно необходимо. Это необходимо для достижения большей масштабируемости. Извлечение ячеек из SQL чрезвычайно медленное по сравнению с объектами, которые мы поддерживаем в сетке данных в памяти.

Как мы делаем SegmentCache повторно использовать существующие записи кэша при запуске

Это предостережение. В настоящее время это возможно, применяя this patch. Он не был перенесен на главную кодолинку, потому что это беспорядок и запутан с исправлениями для другого случая. Сообщалось, что он работает, но не был проверен нами внутренне. Соответствующие code is about here. Если вы обходитесь, чтобы проверить это, мы всегда приветствуем вклады. Сообщите нам, если вы заинтересованы в mailing list. Есть много людей, которые с радостью помогут.

Обходной способ заключается в обновлении локального индекса через слушателя при запуске вашей реализации кэша.

+0

Awesome. Благодарим вас за подробный ответ. Я обновлю этот вопрос, как только у меня появятся дополнительные сведения. –

+0

Я пытаюсь сделать что-то подобное, но я в замешательстве. Что вы понимаете под «обновлением локального индекса через слушателя при запуске вашей реализации кэша»? Благодарю. – agilefall

+0

Я имел в виду примерно следующее: https://github.com/webdetails/cdc/blob/master/src/pt/webdetails/cdc/mondrian/SegmentCacheHazelcast.java#L148 – Luc

Смежные вопросы