अगर आप चाहते हैं विशुद्ध रूप से आउट-ऑफ-प्रोसेस, तो यह बहुत आसान है - निम्न जैसा कुछ, लेकिन यह ध्यान में रखते हुए कि बुकस्लीव को साझा के लिए डिज़ाइन किया गया है :यह पूरी तरह से थ्रेड-सुरक्षित है और मल्टीप्लेक्सर के रूप में काम करता है - आपको प्रत्येक कॉल के लिए उन्हें बनाना/निपटाना नहीं चाहिए। यह भी ध्यान दें कि इस संदर्भ में मैं मान रहा हूं कि आप क्रमांकन को अलग से संभाल लेंगे, इसलिए मैं बस एक byte[]
को उजागर कर रहा हूं एपीआई:
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);
}
}
क्या मिलता है दिलचस्प यदि आप 2-टियर कैश चाहते हैं - यानी स्थानीय मेमोरी और . का उपयोग करना आउट-ऑफ-प्रोसेस कैश, जैसा कि अब आपको कैशे अमान्यकरण की आवश्यकता है। पब/उप इसे आसान बनाता है - निम्नलिखित इसे दिखाता है। यह स्पष्ट नहीं हो सकता है, लेकिन यह रेडिस को बहुत कम कॉल कर रहा होगा (आप monitor
का उपयोग कर सकते हैं इसे देखने के लिए) - चूंकि अधिकांश अनुरोधों को स्थानीय कैश से नियंत्रित किया जाता है।
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");
}
}
ध्यान दें कि एक पूर्ण कार्यान्वयन में आप शायद कभी-कभी टूटे हुए कनेक्शनों को संभालना चाहते हैं, थोड़ा विलंबित पुन:कनेक्ट, आदि के साथ।