2013-05-16 9 views
6

Azure bulutumda bulunan bir veritabanından bir tablo görüntüleyen bir web sayfasında çalışıyorum. Performans iyileştirme için doğrudan DB'ye yapılan çağrıları azaltmak amacıyla, sayfa için bir önbellek oluşturmak istiyorum. Şu anda, tablonun okumaları için bir bellek içi önbellek (in-process) tutuyorum. Şimdi, yazımının yapıldığı, yani eklerin veya güncelleştirmelerin yazıldığı zaman güncellenmesi gereken bir işlem dışı önbellek yapmak istiyorum (çünkü bir değer güncellendikten veya eklendikten sonra, bellek içi önbellek artık geçerli olmayacaktır).Redis pencereleri azure kullanarak işlem dışı önbelleği uygulama

Redis'te ve özellikle Book Sleeve'da önerildim, sorum, işlem dışı önbelleği nasıl oluşturmaya başladığımda yardımcı olacak bazı kod örneklerini bulabileceğim ve şu anki projemde birleştirebileceğim . Eğer tamamen, o zaman dışı süreci oldukça basittiristiyorsanız önceden

+0

Üzgünüm, bu bir varmak görmedim - Ben bir örnek ekleyeceğiz daha sonra bugün –

+0

Bazı iyi cevaplar var gibi görünüyor [burada] (http://stackoverflow.com/questions/10140669/howto-get-redis-running-on-azure) –

+0

Teşekkürler alot @MarcGravell, teşekkürler, Brian – DanielY

cevap

8

yılında

Teşekkür - aşağıdaki gibi bir şey, ama bir BookSleeve paylaşılan olacak şekilde tasarlanmıştır belirterek: tam olduğunu iş parçacığı güvenli ve çoklayıcı olarak çalışır - her çağrı için onları oluşturmamalı/imha etmemelisiniz. Şunu unutmayalım ki seni o kadar ben sadece bir byte[] API açığa ediyorum, ayrı ayrı seri idare edecek sanıyorum bu bağlamda: Bir 2 katmanlı önbellek istiyorsanız ilginç olduğunu alır Ne

class MyCache : IDisposable 
{ 
    public void Dispose() 
    { 
     var tmp = conn; 
     conn = null; 
     if (tmp != null) 
     { 
      tmp.Close(true); 
      tmp.Dispose(); 
     } 
    } 
    private RedisConnection conn; 
    private readonly int db; 
    public MyCache(string configuration = "127.0.0.1:6379", int db = 0) 
    { 
     conn = ConnectionUtils.Connect(configuration); 
     this.db = db; 
     if (conn == null) throw new ArgumentException("It was not possible to connect to redis", "configuration"); 
    } 
    public byte[] Get(string key) 
    { 
     return conn.Wait(conn.Strings.Get(db, key)); 
    } 
    public void Set(string key, byte[] value, int timeoutSeconds = 60) 
    { 
     conn.Strings.Set(db, key, value, timeoutSeconds); 
    } 
} 

- kullanarak yani Yerel bellek ve işlem dışı önbellek, şimdi önbellek geçersiz kılma gerekiyor. Pub/sub bunu kullanışlı hale getirir - aşağıdaki şudur. Açık olmayabilir, ancak bu redis için çok daha az çağrı yapıyor olurdu (bunu görmek için monitor kullanabilirsiniz) - çoğu istek yerel önbellekten dışarı işlenir çünkü. Tam uygulanmasında muhtemelen biraz gecikmeli yeniden bağlanma ile, ara sıra kırılmış bağlantılarını ele almak istedikleri

using BookSleeve; 
using System; 
using System.Runtime.Caching; 
using System.Text; 
using System.Threading; 

class MyCache : IDisposable 
{ 
    public void Dispose() 
    { 
     var tmp0 = conn; 
     conn = null; 
     if (tmp0 != null) 
     { 
      tmp0.Close(true); 
      tmp0.Dispose(); 
     } 

     var tmp1 = localCache; 
     localCache = null; 
     if (tmp1 != null) 
      tmp1.Dispose(); 

     var tmp2 = sub; 
     sub = null; 
     if (tmp2 != null) 
     { 
      tmp2.Close(true); 
      tmp2.Dispose(); 
     } 

    } 
    private RedisSubscriberConnection sub; 
    private RedisConnection conn; 
    private readonly int db; 
    private MemoryCache localCache; 
    private readonly string cacheInvalidationChannel; 
    public MyCache(string configuration = "127.0.0.1:6379", int db = 0) 
    { 
     conn = ConnectionUtils.Connect(configuration); 
     this.db = db; 
     localCache = new MemoryCache("local:" + db.ToString()); 
     if (conn == null) throw new ArgumentException("It was not possible to connect to redis", "configuration"); 
     sub = conn.GetOpenSubscriberChannel(); 
     cacheInvalidationChannel = db.ToString() + ":inval"; // note that pub/sub is server-wide; use 
                  // a channel per DB here 
     sub.Subscribe(cacheInvalidationChannel, Invalidate); 
    } 

    private void Invalidate(string channel, byte[] payload) 
    { 
     string key = Encoding.UTF8.GetString(payload); 
     var tmp = localCache; 
     if (tmp != null) tmp.Remove(key); 
    } 
    private static readonly object nix = new object(); 
    public byte[] Get(string key) 
    { 
     // try local, noting the "nix" sentinel value 
     object found = localCache[key]; 
     if (found != null) 
     { 
      return found == nix ? null : (byte[])found; 
     } 

     // fetch and store locally 
     byte[] blob = conn.Wait(conn.Strings.Get(db, key)); 
     localCache[key] = blob ?? nix; 
     return blob; 
    } 

    public void Set(string key, byte[] value, int timeoutSeconds = 60, bool broadcastInvalidation = true) 
    { 
     localCache[key] = value; 
     conn.Strings.Set(db, key, value, timeoutSeconds); 
     if (broadcastInvalidation) 
      conn.Publish(cacheInvalidationChannel, key); 
    } 
} 

static class Program 
{ 
    static void ShowResult(MyCache cache0, MyCache cache1, string key, string caption) 
    { 
     Console.WriteLine(caption); 
     byte[] blob0 = cache0.Get(key), blob1 = cache1.Get(key); 
     Console.WriteLine("{0} vs {1}", 
      blob0 == null ? "(null)" : Encoding.UTF8.GetString(blob0), 
      blob1 == null ? "(null)" : Encoding.UTF8.GetString(blob1) 
      ); 
    } 
    public static void Main() 
    { 
     MyCache cache0 = new MyCache(), cache1 = new MyCache(); 
     string someRandomKey = "key" + new Random().Next().ToString(); 
     ShowResult(cache0, cache1, someRandomKey, "Initially"); 
     cache0.Set(someRandomKey, Encoding.UTF8.GetBytes("hello")); 
     Thread.Sleep(10); // the pub/sub is fast, but not *instant* 
     ShowResult(cache0, cache1, someRandomKey, "Write to 0"); 
     cache1.Set(someRandomKey, Encoding.UTF8.GetBytes("world")); 
     Thread.Sleep(10); // the pub/sub is fast, but not *instant* 
     ShowResult(cache0, cache1, someRandomKey, "Write to 1"); 
    } 
} 

Not vb

+0

Buradaki 'Uyku'nın işinizi yapmaya devam etmenizi simüle etmek için olduğunu unutmayın; Buradaki nokta, düzenlemenin yaklaşık 0,5 milyonu içinde tüm düğümlerin bunu bilmesidir –

+0

Bu uygulama hakkında: geçersizleştirme iletilerini gönderiyorsunuz, veri değil. PubSub kanalındaki tüm verileri göndermek için herhangi bir sakınca var mı? Teşekkürler – Cybermaxs

+0

@ Cybermaxs-Betclic, istemciye ihtiyaç duyabilecek büyük veri parçaları gönderiyor olduğunuz anlamına gelir –