c# - implementing out-of-process cache using Redis in windows azure -


i've been working on webpage displays table database have in azure cloud. in order reduce calls db directly performance improvement build cache page. currently, hold in-memory cache (in-process) reads of table. make out-of-process cache, should updated when writes made, meaning inserts or updates (because after value updated or added, in-memory cache no longer valid).

i recommended on redis, , book sleeve, question can find code samples me figure out how start build out-of-process cache , combine in current project.

thanks in advance

if want purely out-of-process, pretty simple - following, noting booksleeve designed shared: thread-safe , works multiplexer - shouldn't create / dispose them every call. note in context i'm assuming handle serialization separately, i'm exposing byte[] api:

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 not possible connect 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);     } } 

what gets interesting if want 2-tier cache - i.e. using local memory and out-of-process cache, need cache invalidation. pub/sub makes handy - following shows this. might not obvious, doing lot fewer calls redis (you can use monitor see this) - since requests handled out of local cache.

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 not possible connect redis", "configuration");         sub = conn.getopensubscriberchannel();         cacheinvalidationchannel = db.tostring() + ":inval"; // note pub/sub server-wide; use                                                              // 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 "nix" sentinel value         object found = localcache[key];         if (found != null)         {             return found == nix ? null : (byte[])found;         }          // fetch , 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); // pub/sub fast, not *instant*         showresult(cache0, cache1, somerandomkey, "write 0");         cache1.set(somerandomkey, encoding.utf8.getbytes("world"));         thread.sleep(10); // pub/sub fast, not *instant*         showresult(cache0, cache1, somerandomkey, "write 1");     } } 

note in full implementation want handle occasional broken connections, delayed reconnect, etc.


Comments

Popular posts from this blog

SPSS keyboard combination alters encoding -

Add new record to the table by click on the button in Microsoft Access -

CSS3 Transition to highlight new elements created in JQuery -