当前位置: 首页 > 面试题库 >

在Windows Azure中使用Redis实现进程外缓存

甘祺
2023-03-14
问题内容

我一直在研究一个网页,该网页显示我在天蓝色云中的数据库中的表。为了减少直接调用数据库以提高性能,我想为页面建立一个缓存。当前,我为表的 读取
保留了一个内存中的缓存(进程内)。现在,我要创建一个进程外缓存,该缓存应在进行
操作时进行更新,这意味着插入或更新(因为在更新或添加了一个值之后,内存中缓存将不再有效)。

我被推荐使用Redis,尤其是Book Sleeve,我的问题是在哪里可以找到一些代码示例来帮助我弄清楚如何开始使用它构建进程外缓存并将其组合到当前项目中。

提前致谢


问题答案:

如果你想 单纯 外的过程,那么它是非常简单的-类似于以下,但指出对于BookSleeve被设计为 共享的 :它完全线程安全的,作为一部多路复用器-
你不应该创建/在每次通话时都要处理它们。还要注意,在这种情况下,我假设您将单独处理序列化,因此我只是公开一个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 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级高速缓存是 进程外的高速缓存,因为现在你需要缓存失效。发布/订阅很方便-
下面显示了这一点。可能并不明显,但这将减少对redis的调用(您可以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");
    }
}

请注意,在完整的实现中,您可能希望处理偶尔断开的连接,稍微延迟的重新连接等。



 类似资料:
  • 本文向大家介绍SpringBoot使用Redis缓存的实现方法,包括了SpringBoot使用Redis缓存的实现方法的使用技巧和注意事项,需要的朋友参考一下 (1)pom.xml引入jar包,如下:   (2)修改项目启动类,增加注解@EnableCaching,开启缓存功能,如下:   (3)application.properties中配置Redis连接信息,如下:   (4)新建Redis

  • 本文向大家介绍详解Spring Boot使用redis实现数据缓存,包括了详解Spring Boot使用redis实现数据缓存的使用技巧和注意事项,需要的朋友参考一下 基于spring Boot 1.5.2.RELEASE版本,一方面验证与Redis的集成方法,另外了解使用方法。 集成方法 1、配置依赖 修改pom.xml,增加如下内容。 2、配置Redis 修改application.yml,增

  • 本文向大家介绍在Python中实现最少使用的缓存的程序,包括了在Python中实现最少使用的缓存的程序的使用技巧和注意事项,需要的朋友参考一下 假设我们要为最不常用(LFU)缓存系统实现数据结构。它应支持以下操作: get(key) −如果密钥存在于高速缓存中,则这有助于获取密钥的值,否则返回-1。 set(key, value) −如果密钥不存在,将用于设置或插入值。 当缓存达到最大容量时,它应

  • 本文向大家介绍如何在 Java 中实现一个 redis 缓存服务,包括了如何在 Java 中实现一个 redis 缓存服务的使用技巧和注意事项,需要的朋友参考一下 缓存服务的意义 为什么要使用缓存?说到底是为了提高系统的运行速度。将用户频繁访问的内容存放在离用户最近,访问速度最快的地方,提高用户的响应速度。一个 web 应用的简单结构如下图。 web 应用典型架构 在这个结构中,用户的请求通过用户

  • 我使用Redis作为内存中的数据存储,用于spring boot应用程序中的缓存目的。目前,我已经为我需要缓存的实体实现了基本CRUD功能的Redis支持[Scenario 1]。但突然间,我发现有很多资源使用额外的Spring Boot缓存注释,比如来实现Redis的缓存[Scenario 2]。我监控到,当我们开始在find(params)这样的操作中使用这些注释时,只有第一个方法调用会被调用

  • 本文向大家介绍集成Spring Redis缓存的实现,包括了集成Spring Redis缓存的实现的使用技巧和注意事项,需要的朋友参考一下 这里的缓存主要是用于 Service 层的,所以下面的配置,都是针对 service 模块的。 本文来自内部分享,对特殊信息进行了简单处理。 本文都是在以缓存来讲 Redis 的使用,实际上 Redis 不仅仅用于缓存,本身还是 NoSQL 数据库,大家可以自