おそらく、私はここでベースから外れているかもしれませんが、実際にこのドキュメントをデータベースから 1 日に 10,000 回ロードする必要があるのはなぜですか? おそらく、出力キャッシュを使用したほうがよいでしょう。
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);
}
}
}