【问题标题】:Ehcache multithreading scenarioEhcache 多线程场景
【发布时间】:2016-09-19 19:50:22
【问题描述】:

我需要一些关于以下多线程场景的建议。我有一个 xml 文件,其中包含一些 Web 应用程序的配置数据。当用户访问网站时,根据用户访问的 url,将读取 XML 文件中的数据以找出附加到该用户请求的一些属性。为了提高读取 xml 文件的性能,我使用了 Ehcache。我正在缓存缓存中来自 xml 的请求和相关配置。

所以,现在我面临的问题是。如果有人开始更新 xml 文件,我需要停止从缓存中读取,直到写入完成,一旦 xml 文件更新操作完成,我想清除缓存。然后缓存将再次重建。对于第二部分,我正在努力研究如何实现多线程来实现这一目标。文件更新可以通过两种方式完成,一种是用户使用 notepad++ 或其他工具直接编辑 xml 文件。另一种方法是使用相同的 Web 应用程序。

【问题讨论】:

  • 这个 XML 文件多久更新一次?
  • 可能每天一次或每天两次。它不经常
  • 所以我想真正的问题是您是否真的需要为此构建功能,或者这是一个 1% 的用例,您可能不会充分使用此功能以使其物有所值。如果您不会经常使用它,请编辑 XML 并在一天结束时或在维护窗口期间重新启动您的 Web 应用程序。
  • 是的,我同意你的看法。考虑到这是一个有效的场景。我将如何解决它
  • 您可以使用 JMX 接口在更新后重置 EHCache。这个线程上的这个人有同样的问题。 stackoverflow.com/questions/10912087/…

标签: java multithreading caching ehcache


【解决方案1】:

您可以使用从共享BlockingQueue 读取的工作线程池刷新缓存;当用户完成他们的编辑时,您将向队列发送一条消息,其中包含有关需要更新的 kv 对的信息。

public class RefreshRequest<K> {
    public final K key;
    public RefreshRequest(K key) { this.key = key; }
}

public final BlockingQueue<RefreshRequest<?>> requestQueue = new ArrayBlockingQueue<>(200);
public final int concurrency = 4;
public final ExecutorService executor = Executors.newFixedThreadPool(4);

for(int i = 0; i < concurrency; i++) {
    executor.execute(new Runnable() {
        public void run() {
            try {
                while(true) {
                    RefreshRequest<?> request = requestQueue.take();
                    // refresh key
                }
            } catch(InterruptedException e) {
                return; // maybe log the exception as well
            }
        }
    };
}

worker 会消费请求来刷新缓存键;您需要在队列中 put 来自完成对 xml 文件更改的代码的新请求。要终止工作人员调用executor.shutdownNow(),它将使用InterruptedException 打破while(true) 循环


关于当有人开始写入 xml 时如何停止从缓存中读取,您可以通过“乐观”读取来做到这一点。为每个 xml 文件分配一个版本号,并在写入文件时增加此版本。开始读取时,将文件的版本存储在局部变量中。读取完成后,将本地版本与文件的当前版本进行比较——如果匹配则返回读取值,如果不匹配则重复读取,包括将本地变量更新为当前文件版本。如果需要,您可以有一个“无效”版本(例如,“有效”版本从 0 开始并在每次写入时递增,而“无效”版本为负 1) - 如果读者读到文件“无效”然后它暂停例如5 秒,然后重试。所以一种算法可能是

public Object read(K key) {
    while(true) {
        int version = versionCache.get(key);
        if(version == -1) Thread.sleep(5000);
        else {
            Object returnVal = cache.get(key);
            if(version == versionCache.get(key)) 
                return returnVal;
        }
    }
}

【讨论】:

  • 这是我正在寻找的一种解决方案。但是我不知道“钥匙”。密钥是从访问网络的用户请求中生成的。 XML 文件没有密钥。从用户请求中,我将使用 xml 中的某个字段(字段以 regx 格式编写)从 xml 中找到匹配的条目。那些与用户请求的键匹配的元素被放入缓存中。所以我没有办法通知更新了哪个键值对
  • 另一个问题是当有人开始写入 xml 时,我需要阻止用户从缓存中读取。因为缓存可能有不正确的数据。
  • @KItis 您如何在 ehcache 中存储/访问/无论 XML,例如XML 字符串是否与文件名键或类似内容相关联?
  • @KItis 请参阅我的答案底部的编辑,了解在更新 xml 时停止从缓存读取的方法 - 解决方案不是打断读者,因为这可能非常复杂,而是让读者验证在读取过程中没有对文件进行任何更改。
  • 这是一个很好的解决方案,可以在文档正在更新时停止从缓存中读取。对于你的第二个问题。 xml中有一个字段,其中包含一些正则表达式。因此,当用户请求来到 Web 应用程序时,我将再次对 xml 中的所有条目执行正则表达式匹配用户 url 以找到匹配的条目。那么,关键是什么。关键是用户请求。有什么价值。值是来自 xml 的匹配条目。希望这能解决您关于我如何访问缓存中的条目的问题。
猜你喜欢
  • 2012-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多