2

我正在使用 Chronicle 4.5.27 编写和读取市场数据。我有一个作家,但有多个读者。开发操作系统是 Windows,然后是 Linux,用于 Prod 部署。

如何实现以下用例?

  1. 如何从上次读取位置开始读取队列?例如,如果阅读器从一个有 100 条记录的文件中读取了 15 条记录并且崩溃/停止了如何从下一次重新启动时从第 16 条记录开始读取?CQ 中是否有内置的持久支持?
  2. 删除所有消费者读取的文件以节省磁盘空间。

为此,我已经实现了,但由于一些未解决的问题,文件似乎没有在 Windows 上删除。CQ 中是否有任何内置支持,只有所有感兴趣的消费者都可以删除文件?

public static long readMarketData(String pathForMarketDataFile, long indexFrom) {
SingleChronicleQueue queue = SingleChronicleQueueBuilder.binary(pathForMarketDataFile).rollCycle(RollCycles.MINUTELY).storeFileListener(new StoreFileListener() {
    @Override
    public void onReleased(int i, File file) {
        System.out.println("File is not in use and is ready for deletion: " + file.getName());
        try {
            file.delete();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ;
        System.out.println("File deleted:  " + file.getName() );
    }

    @Override
    public void onAcquired(int cycle, File file) {
        System.out.println("File is use for reading: " + file.getName());
    }
}).build();

我已经阅读了一些关于这个主题的博客和帖子,例如

https://vanilla-java.github.io/2016/03/29/Microservices-in-the-Chronicle-world-Part-4.html

https://groups.google.com/forum/#!topic/java-chronicle/0Nz5P-nvLgM

但仍然想知道是否有人实现了这个用例。

4

2 回答 2

2

使用 执行消费者高水位标记的跟踪MessageHistory,但是,这要求您的消费者也将输出写入编年史队列(本质上将消费者读取序列存储在输出队列中)。

或者,您需要实现自己的机制来记录每个消费者看到的最高序列(索引)。

在删除文件方面,可能有其他进程持有队列文件的打开文件句柄。如果 reader-A 不再使用队列文件 15.cq4,那么您的代码将尝试调用 file.delete(),但 reader-B 可能仍具有对该文件的引用,从而阻止它被删除。

更强大的策略是让每个阅读器向另一个服务/进程发送某种事件,该服务/进程负责在所有阅读器完成处理文件后删除文件。

于 2017-11-13T14:36:57.377 回答
-1

1) 如果您查看文档 https://github.com/OpenHFT/Chronicle-Queue#restartable-tailers,命名您的tailer 将自动处理此功能。

您需要为每个阅读尾巴提供唯一的名称,例如以下代码行中给出的“a”

 ExcerptTailer atailer = cq.createTailer("a");

Tailer 将他们的索引存储在队列本身中,并且维护该索引。当您的阅读服务重新启动时,索引将被拾取并从上次阅读位置继续。

2) 当您调用 file.delete() 时,该文件不会在 Windows 上被删除,并且功能在 Linux 上运行良好。Windows 锁定程序当前正在使用的文件。您不能删除您的应用程序当前正在使用的文件。

其他线程中提到了其他解决方案 Java 'file.delete()' Is not Deleting Specified File

于 2019-11-06T08:38:55.327 回答