也许我在这里有点离谱,但你为什么要每天从数据库中实际加载这个文档 10k 次呢?使用一些输出缓存可能会更好。
Raven 缓存也将对您有利。我必须承认,如果客户端发生缓存命中,我不确定读取触发器是否仍会在服务器上触发。如果您确实走触发器路径,我将首先验证这一点。
也许在客户端保持一个计数器会更好。即使您获得缓存命中并且不触摸 raven,您也可以增加计数器。然后,您可以定期将计数器刷新回服务器,以更新文档本身或单独的统计文档中的计数属性。
这确实有助于提高性能。假设您在 5 分钟内有 50 次观看。为什么每次增加 1,每 5 分钟增加 50。嗯,不完全是 50,而是你在那段时间在前端计量的任何东西。即使使用多个服务器,这也可以扩展,如果您只是将新计数添加到现有服务器,则可以通过 raven 的修补 API 应用更改。
更新
我整理了一个可能对你有帮助的例子。除了定期出现的一些计时器外,这具有您在客户端执行此操作所需的一切。希望这值得你的赏金。
public class Counter
{
// Uses the Multithreaded Singleton pattern
// See http://msdn.microsoft.com/en-us/library/ff650316.aspx
private Counter() { }
private static volatile Counter _instance;
private static readonly object SyncRoot = new object();
public static Counter Instance
{
get
{
if (_instance != null)
return _instance;
lock (SyncRoot)
{
if (_instance == null)
_instance = new Counter();
}
return _instance;
}
}
private readonly ConcurrentDictionary<string, long> _readCounts =
new ConcurrentDictionary<string, long>();
public void Increment(string documentId)
{
_readCounts.AddOrUpdate(documentId, k => 1, (k, v) => v + 1);
}
public long ReadAndReset(string documentId)
{
lock (SyncRoot)
{
long count;
return _readCounts.TryRemove(documentId, out count) ? count : 0;
}
}
public IDictionary<string, long> ReadAndResetAll()
{
var docs = _readCounts.Keys.ToList();
return docs.ToDictionary(x => x, ReadAndReset);
}
}
public class Story
{
public string Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public DateTime Published { get; set; }
public long ReadCount { get; set; }
public string Content { get; set; }
}
[TestClass]
public class Tests
{
[TestMethod]
public void TestCounter()
{
var documentStore = new DocumentStore { Url = "http://localhost:8080" };
documentStore.Initialize();
documentStore.DatabaseCommands.EnsureDatabaseExists("Test");
using (var session = documentStore.OpenSession("Test"))
{
var story = new Story
{
Id = "stories/1",
Title = "A long walk home",
Author = "Miss de Bus",
Published = new DateTime(2012, 1, 1),
Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
};
session.Store(story);
session.SaveChanges();
}
// This simulates many clients reading the document in separate sessions simultaneously
Parallel.For(0, 1000, i =>
{
using (var session = documentStore.OpenSession("Test"))
{
var story = session.Load<Story>("stories/1");
Counter.Instance.Increment(story.Id);
}
});
// This is what you will need to do periodically on a timer event
var counts = Counter.Instance.ReadAndResetAll();
var db = documentStore.DatabaseCommands.ForDatabase("Test");
foreach (var count in counts)
db.Patch(count.Key, new[]
{
new PatchRequest
{
Type = PatchCommandType.Inc,
Name = "ReadCount",
Value = count.Value
}
});
using (var session = documentStore.OpenSession("Test"))
{
var story = session.Load<Story>("stories/1");
Assert.AreEqual(1000, story.ReadCount);
}
}
}