这个问题专门与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作业,定期检查会话存储中是否有过期的会话,并移动数据。