使用Memcache API兼容存储在移除/逐出后持久化缓存的数据



这个问题专门与Couchbase有关,但我相信它适用于任何带有memcached api的东西。

比方说,我正在创建一个客户端/服务器聊天应用程序,在我的服务器上,我将每个用户的聊天会话信息存储在一个数据桶中。聊天会话结束后,我将从数据桶中删除会话对象,但同时我也想将其持久化到一个永久的NoSQL数据存储中,用于报告和分析目的。我还希望会话对象在缓存逐出、会话超时等情况下保持不变。

是否有某种"最佳实践"(甚至是我缺少的Couchbase功能)使我能够高效地做到这一点,并保持内存缓存系统的最佳性能?

使用CouchbaseServer2.0,您可以设置两个bucket(如果您想分离物理资源,则可以设置两个子集群)。在会话集群上,您可以存储JSON文档(键值对中的值),可能如下所示:

{ 
  "sessionId" : "some-guid",
  "users" : [ "user1", "user2" ],
  "chatData" : [ "message1", "message2"],
  "isActive" : true,
  "timestamp" : [2012, 8, 6, 11, 57, 00]
}

然后,您可以在会话数据库中编写一个Map/Reduce视图,该视图为您提供所有过期项目的列表(请注意,下面带有元参数的示例需要CouchbaseServer2.0的最新版本,而不是DP4。

function(doc, meta) {
  if (doc.sessionId && ! doc.isActive) {
    emit(meta.id, null);
  }
}

然后,使用您喜欢的Couchbase客户端库,您可以有一个任务来查询视图,获取项目并将它们移动到分析集群(或bucket)中。所以在C#中,这看起来像:

var view = sessionClient.GetView("sessions", "all_inactive");
foreach(var item in view) 
{
   var doc = sessionClient.Get(item.ItemId);
   analyticsClient.Store(StoreMode.Add, item.ItemId, doc);
   sessionClient.Remove(item.ItemId);
}

如果您想使用明确的时间戳或到期,您的视图可以根据时间戳进行索引:

function(doc) {
   if (doc.sessionId && ! doc.isActive) {
      emit(timestamp, null);
   }
}

然后,您的任务可以通过包含startkey来查询视图,以返回x天内未接触的所有文档。

var view = sessionClient.GetView("sessions", "all_inactive").StartKey(new int[] { DateTime.Now.Year, DateTime.Now.Months, DateTime.Now.Days-1);
foreach(var item in view)
{
   var doc = sessionClient.Get(item.ItemId);
   analyticsClient.Store(StoreMode.Add, item.ItemId, doc);
   sessionClient.Remove(item.ItemId);
}

签出http://www.couchbase.com/couchbase-server/next有关CouchbaseServer2.0的更多信息,如果您需要对这种方法进行任何澄清,请在本线程中告诉我。

--John

CouchDB存储(最终)是持久的,没有内置的过期机制,所以无论你存储在其中的什么,都将保持存储状态,直到你删除它——这不像Memcached中那样,你可以为存储的数据设置超时。因此,如果您将会话存储在CouchDB中,当它们过期时,您将不得不自己删除它们,因为这不是一种自动机制,而是您自己做的事情,所以您没有理由不将数据同时保存在任何您想要的地方。

顺便说一句,我认为在会话存储中使用Persistent NoSQL与SQL相比没有任何优势(反之亦然)——两者的性能都将受到IO的限制。纯内存密钥存储或混合解决方案则完全不同。

至于你的问题:在你的应用程序会话到期/会话关闭机制中移动数据,和/或运行一个cron作业,定期检查会话存储中是否有过期的会话,并移动数据。

最新更新