java - OpenHFT/Chronicle map 失败

标签 java chronicle chronicle-map

我正在使用 VanillaChroncile 来临时存储和检索条目,并且一切都工作得很好,除非有巨大的负载。我收到 map 失败异常。尽管我有处理此异常的恢复逻辑,但我想知道为什么我首先会收到异常。任何帮助将不胜感激。

     public enum PreAuthEventChronicle {
INSTANCE;
private String basePath = PropertyUtilsEnum.INSTANCE.getChronicleDirPath();
private final Logger logger = Logger.getLogger(PreAuthEventChronicle.class);
private long indexBlockSize = 64L;
// Length of the excerpt.
private final int excerptLength = 1024;
private final int cycleLength = "yyyyMMddhhmmss";
// Number of entries that are stored in the chronicle queue.
private final long entriesPerCycle = 1L << 20;
// Format for the folder. Chronicle writes in GMT time zone.
private final String format = ApplicationConstants.CHRONICLE_FORMAT;
private Chronicle chronicle = null;
private List<PreAuthEventListener> listeners = new      ArrayList<PreAuthEventListener>();

public Chronicle getChr() {
    return chronicle;
}

/**
 * There can only be one chronicle built.
 */
private PreAuthEventChronicle() {
    if (basePath != null) {
        if (!basePath.endsWith(ApplicationConstants.FILE_SEP)) {
            basePath = basePath + ApplicationConstants.FILE_SEP + ApplicationConstants.CHRONICLE_DATA_PATH;
        }
        logger.debug("Starting from a clean state");
        cleanUp();
        logger.debug("Building a Vanilla Chronicle instance with path: " + basePath);
        buildChronicle();
    } else {
        throw new RuntimeException("No directory specified for chronicle to be built.");
    }
}

private void buildChronicle() {
    logger.debug("Begin-Starting to build a vanilla chronicle");
    try {
        if (chronicle != null) {
            chronicle.clear();
            chronicle = null;
        }
        chronicle = ChronicleQueueBuilder.vanilla(basePath).cycleLength(cycleLength, false).cycleFormat(format)
                .indexBlockSize(indexBlockSize).entriesPerCycle(entriesPerCycle).build();
    } catch (IOException e) {
        logger.error("Error building chronicle" + e.getMessage());
    }
    logger.debug("End-Finished building the vanilla chronicle");
}

/**
 * Clean up the resources
 */
public void cleanUp() {
    logger.debug("Begin-Cleaning up chronicle resources");
    File f = new File(basePath);
    if (f.exists() && f.isDirectory()) {
        File[] dirs = f.listFiles();
        for (File dir : dirs) {
            if (dir.isDirectory()) {
                try {
                    FileUtils.deleteDirectory(dir);
                } catch (IOException ignore) {
                }
            }
        }
    }
    buildChronicle();
    logger.debug("End-Done cleaning up chronicle resources");
}

/**
 * Write the object to the chronicle queue, and notify the listeners
 * 
 * @param event
 * @throws IOException
 */
public synchronized void writeObject(Object event) throws IOException {
    ExcerptAppender appender = INSTANCE.getChr().createAppender();
    if (appender != null && event != null) {
        logger.debug("Begin-Writing event to the chronicle queue");
        appender.startExcerpt(excerptLength);
        appender.writeObject(event);
        appender.finish();
        appender.clear();
        appender.close();
        notifyListeners();
        logger.debug("End-Done writing event to the chronicle queue.");
    }
}

/**
 * Read the object from the queue
 * 
 * @return
 * @throws IOException
 */
public synchronized Object readObject() throws IOException {
    ExcerptTailer reader = INSTANCE.getChr().createTailer().toStart();
    Object evt = null;
    while (reader != null && reader.nextIndex()) {
        logger.debug("Begin-Reading event from the chronicle queue");
        evt = reader.readObject();
        reader.finish();
        reader.clear();
        reader.close();
        logger.debug("End-Done reading the event from the chronicle queue.");
    }
    return evt;
}

/**
 * Attach a listener
 * 
 * @param listen
 */
public void attachListener(PreAuthEventListener listen) {
    listeners.add(listen);
}

/**
 * Notify the listeners that an event has been written.
 */
private void notifyListeners() {
    for (PreAuthEventListener listener : listeners) {
        logger.debug("Notification received from the chronicle queue. Performing action.");
        listener.perform();
    }
}

}

最佳答案

了解您遇到的异常是什么会很有用,但我敢打赌原因是 OutOfMemoryError。

关于您的代码:

  • 你想每秒滚动一次,这是可能的,但对于每次滚动来说效率不高,Chronicle-Queue 需要映射至少两个区域
  • readObject/writeObject 是同步方法,Va 不需要 nillaChronicle 是线程安全的
  • 在 readObject 中,您在每个循环中关闭尾部,这可能会导致每次迭代的映射区域取消映射/映射,最好在循环外调用 close()
  • 在 writeObject 中,您显式关闭摘录,如果您无法控制调用该方法的线程数量,这是可以的,但这可能不是最有效的方法,因为对于每个新线程,必须映射一个新区域
  • 无需调用 [tailer|appender].clear()

关于java - OpenHFT/Chronicle map 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31924285/

相关文章:

java - Admob 广告不会加载。错误2,之前还可以,突然就停止了

java - 引用与现有类型同名的类

java - 如何使用 Chronicle Map 在随机索引上使用 get/set 序列化/反序列化 long[] 值?

java - 历史记录 map 不支持的类版本错误

java - ChronicleMap 和 parallelStream

chronicle - 哪个是 ChronicleMap 的生产就绪版本?

java - Google 数据存储区实体不返回 ID。实体 ID 为空

java - 文件未找到异常错误

java - 使用 Chronicle Map 作为微服务之间数据共享的手段

redis - Chronicle Map vs Redis vs Koloboke