Java Memcached-缓存必须与数据库同步的信息

Java Memcached-缓存必须与数据库同步的信息,java,caching,asynchronous,memcached,block,Java,Caching,Asynchronous,Memcached,Block,我将其用作缓存系统和java客户端,以将对象存储在缓存中 Memcached put()/delete()是异步的。 对于特定对象,我需要缓存中的状态反映数据库的状态。 对于这些对象,我考虑在spyMemcachedClient.put()方法返回的将来阻塞线程,以确保缓存反映数据库的当前状态 差不多 changedObject -> block on Memcached.put() Future .. once it's finished -> writeToDB = ever

我将其用作缓存系统和java客户端,以将对象存储在缓存中

Memcached put()/delete()是异步的。
对于特定对象,我需要缓存中的状态反映数据库的状态。
对于这些对象,我考虑在spyMemcachedClient.put()方法返回的将来阻塞线程,以确保缓存反映数据库的当前状态

差不多

changedObject -> block on Memcached.put() Future .. once it's finished ->  writeToDB  = every subsequent Memcached.get() object is guaranteed to be in synch with the DB
如果我没有同步,并且用spyMemcachedClient.get()足够快地命中缓存,则可能是该对象没有反映当前的数据库状态

我想知道对几种对象阻塞put()是否正确,或者这是否会显著降低缓存系统的性能
我可以这样做吗?或者我真的不应该这样做


谢谢

在我看来,您使用的缓存是错误的。您假设put()实际上成功地将数据放入缓存,并且在对put()的调用被阻塞之后,您放入的数据就是使用get()返回的数据。这方面存在一些问题:

  • put()可能会失败(因为 网络错误,内存不足错误 等)
  • put()可能会成功,但是 您输入的数据可能会被刷新 因为更新的、优先级更高的数据 需要投入
  • 另一个过程 可能放置()数据,甚至可能是旧的 数据输入
  • 。。。举几个例子

    因此,基本上您应该了解并发性,而不要依赖缓存。这是一种可接受且安全的缓存使用方式:

    public String getArticleText(String uuid) {
    
     String cacheKey = "article_" + uuid;
     String text = cache.get(cacheKey);
     if (text == null) {
    
      text = fetch text from db...
      cache.put(cacheKey, text);
     }
    }
    
    使用这种方法,您可以确保缓存具有最新版本,只需在更新文章文本时删除缓存条目(在本例中):

    因此,基本上,您在请求时将数据放入缓存,而不是在数据更新时。因为如果你更新了这篇文章,然后必须重新启动缓存服务器(在分布式环境中,这对于memcached来说很常见),会发生什么?除非你更新系统中的每一篇文章,否则你的缓存永远不会被数据填满——你可能很少这样做


    好的,我希望这有帮助;)

    正如我提到的,设置/删除是同步的。。因此,如果在实际删除发生之前触发了针对缓存的get请求,我不明白delete如何解决这个问题。因为它们是异步的。在我看来,您的解决方案与使用另一个对象设置密钥有相同的问题。如果您需要更新缓存中的条目,然后应用程序执行才能继续正常运行,则可能意味着您的应用程序本身依赖于缓存中的数据,这是错误的操作方式。为什么需要等待数据被删除/设置后才能继续?我的应用程序不依赖于缓存中的数据。我正在以正常的方式使用缓存,但我想知道是否仍然可以以有效的方式使用它来存储应该始终与DB状态同步的对象。对于应用程序来说,很少有对象与数据库同步是至关重要的。由于put(或您建议的delete)是异步的,如果在实际操作发生之前不阻止,则无法保证这一点。确定。因此,如果需要在删除操作完成之前阻止线程,那么这意味着同一线程中的某个线程正在使用cache.get()获取数据?或者为什么需要阻止它以确保它同步?此外,正如我所写的,您根本不能依赖缓存中存在的数据-您唯一可以真正依赖的是,在调用cache.delete()之后,该条目将从缓存中删除。对于文章文本,如果它们与数据库不同步,则无所谓。。但对于其他对象,我需要它们同步。使用您的解决方案,如果我在缓存中有文章文本,然后使用updateArticleText更新它,并且速度足够快,可以再次命中缓存(在执行实际删除之前),我将获取文章的旧文本。在这种情况下,我们可以说没关系,我们不在乎,因为这只是一篇文章的描述。。但我说的是一种解决方案,当返回的信息需要始终与数据库同步时
    public void updateArticleText(String uuid, String text) {
    
     update article in db...
     cache.delete("article_" + uuid);
    }