快速入门:在 .NET Framework 中使用 Azure Cache for RedisQuickstart: Use Azure Cache for Redis in .NET Framework

在本快速入门中,会将 Azure Redis 缓存合并到 .NET Framework 应用中,以便能够访问 Azure 中的任何应用程序都可以访问的安全专用缓存。In this quickstart, you incorporate Azure Cache for Redis into a .NET Framework app to have access to a secure, dedicated cache that is accessible from any application within Azure. 你专门在 .NET 控制台应用中将 StackExchange.Redis 客户端与 C# 代码配合使用。You specifically use the StackExchange.Redis client with C# code in a .NET console app.

跳到 GitHub 上的代码Skip to the code on GitHub

如果要直接跳到代码,请参阅 GitHub 上的 .NET Framework 快速入门If you want to skip straight to the code, see the .NET Framework quickstart on GitHub.


创建缓存Create a cache

  1. 若要创建缓存,请登录到 Azure 门户并选择“创建资源” 。To create a cache, sign in to the Azure portal and select Create a resource.


  2. 在“新建”页上选择“数据库”,然后选择“Azure Cache for Redis”。On the New page, select Databases and then select Azure Cache for Redis.

    在“新建”中,突出显示了“数据库”和“Azure Cache for Redis”。

  3. 在“新建 Redis 缓存”页上配置新缓存的设置。On the New Redis Cache page, configure the settings for your new cache.

    设置Setting 建议的值Suggested value 说明Description
    DNS 名称DNS name 输入任何全局唯一的名称。Enter a globally unique name. 缓存名称必须是包含 1 到 63 个字符的字符串,只能包含数字、字母或连字符。The cache name must be a string between 1 and 63 characters that contains only numbers, letters, or hyphens. 该名称必须以数字或字母开头和结尾,且不能包含连续的连字符。The name must start and end with a number or letter, and can't contain consecutive hyphens. 缓存实例的主机名将是 <DNS name>.redis.cache.chinacloudapi.cnYour cache instance's host name will be <DNS name>.redis.cache.chinacloudapi.cn.
    订阅Subscription 单击下拉箭头并选择你的订阅。Drop down and select your subscription. 要在其下创建此新的 Azure Cache for Redis 实例的订阅。The subscription under which to create this new Azure Cache for Redis instance.
    资源组Resource group 单击下拉箭头并选择一个资源组,或者选择“新建”并输入新的资源组名称。Drop down and select a resource group, or select Create new and enter a new resource group name. 要在其中创建缓存和其他资源的资源组的名称。Name for the resource group in which to create your cache and other resources. 将所有应用资源放入一个资源组可以轻松地统一管理或删除这些资源。By putting all your app resources in one resource group, you can easily manage or delete them together.
    位置Location 单击下拉箭头并选择一个位置。Drop down and select a location. 选择与要使用该缓存的其他服务靠近的区域Select a region near other services that will use your cache.
    定价层Pricing tier 单击下拉箭头并选择一个定价层Drop down and select a Pricing tier. 定价层决定可用于缓存的大小、性能和功能。The pricing tier determines the size, performance, and features that are available for the cache. 有关详细信息,请参阅用于 Redis 的 Azure 缓存概述For more information, see Azure Cache for Redis Overview.
  4. 选择“网络”选项卡,或单击页面底部的“网络”按钮 。Select the Networking tab or click the Networking button at the bottom of the page.

  5. 在“网络”选项卡中,选择你的连接方法。In the Networking tab, select your connectivity method.

  6. 选择页面底部的“下一步:高级”选项卡,或者单击页面底部的“下一步:高级”按钮。Select the Next: Advanced tab or click the Next: Advanced button on the bottom of the page.

  7. 在基本或标准缓存实例的“高级”选项卡中,如果想要启用非 TLS 端口,请选择启用开关。In the Advanced tab for a basic or standard cache instance, select the enable toggle if you want to enable a non-TLS port. 还可以选择你想使用的 Redis 版本,4 或(预览版)6。You can also select which Redis version you would like use, either 4 or (PREVIEW) 6.

    Redis 版本 4 或 6。

  8. 在高级缓存实例的“高级”选项卡中,配置非 TLS 端口、群集和数据持久性的设置。In the Advanced tab for premium cache instance, configure the settings for non-TLS port, clustering, and data persistence. 还可以选择你想使用的 Redis 版本,4 或(预览版)6。You can also select which Redis version you would like use, either 4 or (PREVIEW) 6.

  9. 选择页面底部的“下一步:标记”选项卡,或者单击“下一步:标记”按钮。Select the Next: Tags tab or click the Next: Tags button at the bottom of the page.

  10. 或者,在“标记”选项卡中,如果希望对资源分类,请输入名称或值。Optionally, in the Tags tab, enter the name and value if you wish to categorize the resource.

  11. 选择“查看 + 创建” 。Select Review + create. 随后你会转到“查看 + 创建”选项卡,Azure 将在此处验证配置。You're taken to the Review + create tab where Azure validates your configuration.

  12. 显示绿色的“已通过验证”消息后,选择“创建”。After the green Validation passed message appears, select Create.

创建缓存需要花费片刻时间。It takes a while for the cache to create. 可以在 Azure Cache for Redis 的“概述”页上监视进度。 You can monitor progress on the Azure Cache for Redis Overview page. 如果“状态”显示为“正在运行”,则表示该缓存可供使用。 When Status shows as Running, the cache is ready to use.

从 Azure 门户检索主机名、端口和访问密钥Retrieve host name, ports, and access keys from the Azure portal

若要连接到某个 Azure Cache for Redis 实例,缓存客户端需要该缓存的主机名、端口和密钥。To connect to an Azure Cache for Redis instance, cache clients need the host name, ports, and a key for the cache. 在某些客户端中,这些项的名称可能略有不同。Some clients might refer to these items by slightly different names. 可以从 Azure 门户检索主机名、端口和访问密钥。You can get the host name, ports, and keys from the Azure portal.

  • 若要获取访问密钥,请在缓存的左侧导航中选择“访问密钥”。 To get the access keys, from your cache left navigation, select Access keys.

    Azure Redis 缓存密钥

  • 若要获取主机名和端口,请在缓存的左侧导航栏中选择“属性”。 To get the host name and ports, from your cache left navigation, select Properties. 主机名的格式为 <DNS 名称>.redis.cache.chinacloudapi.cn 。The host name is of the form <DNS name>.redis.cache.chinacloudapi.cn.

    Azure Redis 缓存属性

在计算机上创建名为 CacheSecrets.config 的文件,将其放到不会连同示例应用程序源代码一起签入的位置。Create a file on your computer named CacheSecrets.config and place it in a location where it won't be checked in with the source code of your sample application. 在本快速入门中,CacheSecrets.config 文件的路径为 C:\AppSecrets\CacheSecrets.configFor this quickstart, the CacheSecrets.config file is located here, C:\AppSecrets\CacheSecrets.config.

编辑 CacheSecrets.config 文件,添加以下内容:Edit the CacheSecrets.config file and add the following contents:

    <add key="CacheConnection" value="<host-name>,abortConnect=false,ssl=true,allowAdmin=true,password=<access-key>"/>

<host-name> 替换为缓存主机名。Replace <host-name> with your cache host name.

<access-key> 替换缓存的主密钥。Replace <access-key> with the primary key for your cache.

创建控制台应用Create a console app

在 Visual Studio 中,单击“文件” > “新建” > “项目” 。In Visual Studio, click File > New > Project.

选择“控制台应用(.NET Framework)” ,然后选择“下一步” 以配置应用。Select Console App (.NET Framework), and Next to configure your app. 键入 项目名称,验证是否已选择 .NET Framework 4.6.1 或更高版本,然后单击 创建 以创建新的控制台应用程序。Type a Project name, verify that .NET Framework 4.6.1 or higher is selected, and then click Create to create a new console application.

配置缓存客户端Configure the cache client

在本部分,请配置控制台应用程序,以便将 StackExchange.Redis 客户端用于 .NET。In this section, you will configure the console application to use the StackExchange.Redis client for .NET.

在 Visual Studio 中单击“工具” > “NuGet 包管理器” > “包管理器控制台”,然后在“包管理器控制台”窗口中运行以下命令。In Visual Studio, click Tools > NuGet Package Manager > Package Manager Console, and run the following command from the Package Manager Console window.

Install-Package StackExchange.Redis

完成安装后,StackExchange.Redis 缓存客户端可供与项目一起使用。Once the installation is completed, the StackExchange.Redis cache client is available to use with your project.

连接到缓存Connect to the cache

在 Visual Studio 中,打开 App.config 文件并将其更新为包含引用 CacheSecrets.config 文件的 appSettings file 属性。In Visual Studio, open your App.config file and update it to include an appSettings file attribute that references the CacheSecrets.config file.

<?xml version="1.0" encoding="utf-8" ?>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />

    <appSettings file="C:\AppSecrets\CacheSecrets.config"></appSettings>

在解决方案资源管理器中右键单击“引用”,然后单击“添加引用”。 In Solution Explorer, right-click References and click Add a reference. 添加对 System.Configuration 程序集的引用。Add a reference to the System.Configuration assembly.

将以下 using 语句添加到 Program.csAdd the following using statements to Program.cs:

using StackExchange.Redis;
using System.Configuration;

与 Azure Redis 缓存的连接由 ConnectionMultiplexer 类管理。The connection to the Azure Cache for Redis is managed by the ConnectionMultiplexer class. 应在整个客户端应用程序中共享和重复使用此类。This class should be shared and reused throughout your client application. 不要为每个操作创建新连接。Do not create a new connection for each operation.

切勿将凭据存储在源代码中。Never store credentials in source code. 为了使此示例简单明了,我将只使用外部机密配置文件。To keep this sample simple, I’m only using an external secrets config file. 更好的方法是将 Azure Key Vault 与证书配合使用A better approach would be to use Azure Key Vault with certificates.

Program.cs 中,将以下成员添加到控制台应用程序的 Program 类:In Program.cs, add the following members to the Program class of your console application:

private static Lazy<ConnectionMultiplexer> lazyConnection = CreateConnection();

public static ConnectionMultiplexer Connection
        return lazyConnection.Value;

private static Lazy<ConnectionMultiplexer> CreateConnection()
    return new Lazy<ConnectionMultiplexer>(() =>
        string cacheConnection = ConfigurationManager.AppSettings["CacheConnection"].ToString();
        return ConnectionMultiplexer.Connect(cacheConnection);

这种在应用程序中共享 ConnectionMultiplexer 实例的方法使用一个返回已连接实例的静态属性。This approach to sharing a ConnectionMultiplexer instance in your application uses a static property that returns a connected instance. 此代码提供了一种线程安全方法,它仅初始化单个已连接的 ConnectionMultiplexer 实例。The code provides a thread-safe way to initialize only a single connected ConnectionMultiplexer instance. abortConnect 设置为 false,这意味着即使未建立与 Azure Redis 缓存的连接,调用也会成功。abortConnect is set to false, which means that the call succeeds even if a connection to the Azure Cache for Redis is not established. ConnectionMultiplexer 的一个关键功能是,一旦解决网络问题和其他原因,它会自动还原缓存连接。One key feature of ConnectionMultiplexer is that it automatically restores connectivity to the cache once the network issue or other causes are resolved.

CacheConnection appSetting 的值用于将 Azure 门户中的缓存连接字符串作为密码参数引用。The value of the CacheConnection appSetting is used to reference the cache connection string from the Azure portal as the password parameter.

通过重新连接来处理 RedisConnectionException 和 SocketExceptionHandle RedisConnectionException and SocketException by reconnecting

ConnectionMultiplexer 上调用方法时,建议最佳做法是通过关闭并重新建立连接来尝试自动解析 RedisConnectionExceptionSocketException 异常。A recommended best practice when calling methods on ConnectionMultiplexer is to attempt to resolve RedisConnectionException and SocketException exceptions automatically by closing and reestablishing the connection.

将以下 using 语句添加到 Program.csAdd the following using statements to Program.cs:

using System.Net.Sockets;
using System.Threading;

Program.cs 中,将以下成员添加到 Program 类。In Program.cs, add the following members to the Program class:

private static long lastReconnectTicks = DateTimeOffset.MinValue.UtcTicks;
private static DateTimeOffset firstErrorTime = DateTimeOffset.MinValue;
private static DateTimeOffset previousErrorTime = DateTimeOffset.MinValue;

private static readonly object reconnectLock = new object();

// In general, let StackExchange.Redis handle most reconnects,
// so limit the frequency of how often ForceReconnect() will
// actually reconnect.
public static TimeSpan ReconnectMinFrequency => TimeSpan.FromSeconds(60);

// If errors continue for longer than the below threshold, then the
// multiplexer seems to not be reconnecting, so ForceReconnect() will
// re-create the multiplexer.
public static TimeSpan ReconnectErrorThreshold => TimeSpan.FromSeconds(30);

public static int RetryMaxAttempts => 5;

private static void CloseConnection(Lazy<ConnectionMultiplexer> oldConnection)
    if (oldConnection == null)

    catch (Exception)
        // Example error condition: if accessing oldConnection.Value causes a connection attempt and that fails.

/// <summary>
/// Force a new ConnectionMultiplexer to be created.
/// NOTES:
///     1. Users of the ConnectionMultiplexer MUST handle ObjectDisposedExceptions, which can now happen as a result of calling ForceReconnect().
///     2. Don't call ForceReconnect for Timeouts, just for RedisConnectionExceptions or SocketExceptions.
///     3. Call this method every time you see a connection exception. The code will:
///         a. wait to reconnect for at least the "ReconnectErrorThreshold" time of repeated errors before actually reconnecting
///         b. not reconnect more frequently than configured in "ReconnectMinFrequency"
/// </summary>
public static void ForceReconnect()
    var utcNow = DateTimeOffset.UtcNow;
    long previousTicks = Interlocked.Read(ref lastReconnectTicks);
    var previousReconnectTime = new DateTimeOffset(previousTicks, TimeSpan.Zero);
    TimeSpan elapsedSinceLastReconnect = utcNow - previousReconnectTime;

    // If multiple threads call ForceReconnect at the same time, we only want to honor one of them.
    if (elapsedSinceLastReconnect < ReconnectMinFrequency)

    lock (reconnectLock)
        utcNow = DateTimeOffset.UtcNow;
        elapsedSinceLastReconnect = utcNow - previousReconnectTime;

        if (firstErrorTime == DateTimeOffset.MinValue)
            // We haven't seen an error since last reconnect, so set initial values.
            firstErrorTime = utcNow;
            previousErrorTime = utcNow;

        if (elapsedSinceLastReconnect < ReconnectMinFrequency)
            return; // Some other thread made it through the check and the lock, so nothing to do.

        TimeSpan elapsedSinceFirstError = utcNow - firstErrorTime;
        TimeSpan elapsedSinceMostRecentError = utcNow - previousErrorTime;

        bool shouldReconnect =
            elapsedSinceFirstError >= ReconnectErrorThreshold // Make sure we gave the multiplexer enough time to reconnect on its own if it could.
            && elapsedSinceMostRecentError <= ReconnectErrorThreshold; // Make sure we aren't working on stale data (e.g. if there was a gap in errors, don't reconnect yet).

        // Update the previousErrorTime timestamp to be now (e.g. this reconnect request).
        previousErrorTime = utcNow;

        if (!shouldReconnect)

        firstErrorTime = DateTimeOffset.MinValue;
        previousErrorTime = DateTimeOffset.MinValue;

        Lazy<ConnectionMultiplexer> oldConnection = lazyConnection;
        lazyConnection = CreateConnection();
        Interlocked.Exchange(ref lastReconnectTicks, utcNow.UtcTicks);

// In real applications, consider using a framework such as
// Polly to make it easier to customize the retry approach.
private static T BasicRetry<T>(Func<T> func)
    int reconnectRetry = 0;
    int disposedRetry = 0;

    while (true)
            return func();
        catch (Exception ex) when (ex is RedisConnectionException || ex is SocketException)
            if (reconnectRetry > RetryMaxAttempts)
        catch (ObjectDisposedException)
            if (disposedRetry > RetryMaxAttempts)

public static IDatabase GetDatabase()
    return BasicRetry(() => Connection.GetDatabase());

public static System.Net.EndPoint[] GetEndPoints()
    return BasicRetry(() => Connection.GetEndPoints());

public static IServer GetServer(string host, int port)
    return BasicRetry(() => Connection.GetServer(host, port));

执行缓存命令Executing cache commands

为控制台应用程序的 Program 类的 Main 过程添加以下代码:Add the following code for the Main procedure of the Program class for your console application:

static void Main(string[] args)
    IDatabase cache = GetDatabase();

    // Perform cache operations using the cache object...

    // Simple PING command
    string cacheCommand = "PING";
    Console.WriteLine("\nCache command  : " + cacheCommand);
    Console.WriteLine("Cache response : " + cache.Execute(cacheCommand).ToString());

    // Simple get and put of integral data types into the cache
    cacheCommand = "GET Message";
    Console.WriteLine("\nCache command  : " + cacheCommand + " or StringGet()");
    Console.WriteLine("Cache response : " + cache.StringGet("Message").ToString());

    cacheCommand = "SET Message \"Hello! The cache is working from a .NET console app!\"";
    Console.WriteLine("\nCache command  : " + cacheCommand + " or StringSet()");
    Console.WriteLine("Cache response : " + cache.StringSet("Message", "Hello! The cache is working from a .NET console app!").ToString());

    // Demonstrate "SET Message" executed as expected...
    cacheCommand = "GET Message";
    Console.WriteLine("\nCache command  : " + cacheCommand + " or StringGet()");
    Console.WriteLine("Cache response : " + cache.StringGet("Message").ToString());

    // Get the client list, useful to see if connection list is growing...
    // Note that this requires allowAdmin=true in the connection string
    cacheCommand = "CLIENT LIST";
    Console.WriteLine("\nCache command  : " + cacheCommand);
    var endpoint = (System.Net.DnsEndPoint)GetEndPoints()[0];
    IServer server = GetServer(endpoint.Host, endpoint.Port);
    ClientInfo[] clients = server.ClientList();

    Console.WriteLine("Cache response :");
    foreach (ClientInfo client in clients)


Azure Redis 缓存具有可配置的数据库数量(默认为 16 个),因此可以通过逻辑方式隔离 Azure Redis 缓存中的数据。Azure Cache for Redis has a configurable number of databases (default of 16) that can be used to logically separate the data within an Azure Cache for Redis. 该代码连接到默认数据库 DB 0。The code connects to the default database, DB 0. 有关详细信息,请参阅什么是 Redis 数据库?默认 Redis 服务器配置For more information, see What are Redis databases? and Default Redis server configuration.

可以使用 StringSetStringGet 方法来存储和检索缓存项。Cache items can be stored and retrieved by using the StringSet and StringGet methods.

Redis 将大多数数据存储为 Redis 字符串,但这些字符串可能包含许多类型的数据,包括序列化的二进制数据,可在缓存中存储 .NET 对象时使用。Redis stores most data as Redis strings, but these strings can contain many types of data, including serialized binary data, which can be used when storing .NET objects in the cache.

Ctrl+F5 生成并运行控制台应用。Press Ctrl+F5 to build and run the console app.

在下面的示例中,可以看到 Message 键以前有一个缓存值,该值是使用 Azure 门户中的 Redis 控制台设置的。In the example below, you can see the Message key previously had a cached value, which was set using the Redis Console in the Azure portal. 应用更新了该缓存值。The app updated that cached value. 应用还执行了 PINGCLIENT LIST 命令。The app also executed the PING and CLIENT LIST commands.


处理缓存中的 .NET 对象Work with .NET objects in the cache

Azure Redis 缓存可以缓存 .NET 对象以及基元数据类型,但在缓存 .NET 对象之前,必须将其序列化。Azure Cache for Redis can cache both .NET objects and primitive data types, but before a .NET object can be cached it must be serialized. 此 .NET 对象序列化是应用程序开发人员的责任,同时赋与开发人员选择序列化程序的弹性。This .NET object serialization is the responsibility of the application developer, and gives the developer flexibility in the choice of the serializer.

将对象序列化的一种简单方式是使用 Newtonsoft.Json 中的 JsonConvert 序列化方法,并与 JSON 相互序列化。One simple way to serialize objects is to use the JsonConvert serialization methods in Newtonsoft.Json and serialize to and from JSON. 在本部分中,将向缓存中添加一个 .NET 对象。In this section, you will add a .NET object to the cache.

在 Visual Studio 中单击“工具” > “NuGet 包管理器” > “包管理器控制台”,然后在“包管理器控制台”窗口中运行以下命令。In Visual Studio, click Tools > NuGet Package Manager > Package Manager Console, and run the following command from the Package Manager Console window.

Install-Package Newtonsoft.Json

将以下 using 语句添加到 Program.cs 的顶部:Add the following using statement to the top of Program.cs:

using Newtonsoft.Json;

将以下 Employee 类定义添加到 Program.csAdd the following Employee class definition to Program.cs:

class Employee
    public string Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }

    public Employee(string employeeId, string name, int age)
        Id = employeeId;
        Name = name;
        Age = age;

Program.cs 中的 Main() 过程的底部,在对 CloseConnection() 的调用之前,添加以下代码行来缓存和检索已序列化的 .NET 对象:At the bottom of Main() procedure in Program.cs, and before the call to CloseConnection(), add the following lines of code to cache and retrieve a serialized .NET object:

    // Store .NET object to cache
    Employee e007 = new Employee("007", "Davide Columbo", 100);
    Console.WriteLine("Cache response from storing Employee .NET object : " + 
    cache.StringSet("e007", JsonConvert.SerializeObject(e007)));

    // Retrieve .NET object from cache
    Employee e007FromCache = JsonConvert.DeserializeObject<Employee>(cache.StringGet("e007"));
    Console.WriteLine("Deserialized Employee .NET object :\n");
    Console.WriteLine("\tEmployee.Name : " + e007FromCache.Name);
    Console.WriteLine("\tEmployee.Id   : " + e007FromCache.Id);
    Console.WriteLine("\tEmployee.Age  : " + e007FromCache.Age + "\n");

Ctrl+F5 生成并运行控制台应用,以便测试 .NET 对象的序列化。Press Ctrl+F5 to build and run the console app to test serialization of .NET objects.


清理资源Clean up resources

如果想要继续学习下一篇教程,可以保留本快速入门中创建的资源,以便重复使用。If you will be continuing to the next tutorial, you can keep the resources created in this quickstart and reuse them.

如果已完成快速入门示例应用程序,可以删除本快速入门中创建的 Azure 资源,以免产生费用。Otherwise, if you are finished with the quickstart sample application, you can delete the Azure resources created in this quickstart to avoid charges.


删除资源组的操作不可逆,资源组以及其中的所有资源将被永久删除。Deleting a resource group is irreversible and that the resource group and all the resources in it are permanently deleted. 请确保不会意外删除错误的资源组或资源。Make sure that you do not accidentally delete the wrong resource group or resources. 如果在现有资源组(其中包含要保留的资源)中为托管此示例而创建了相关资源,可从各自的边栏选项卡逐个删除这些资源,而不要删除资源组。If you created the resources for hosting this sample inside an existing resource group that contains resources you want to keep, you can delete each resource individually from their respective blades instead of deleting the resource group.

登录到 Azure 门户,并单击“资源组”。Sign in to the Azure portal and click Resource groups.

在“按名称筛选...”文本框中键入资源组的名称。In the Filter by name... textbox, type the name of your resource group. 本文的说明使用了名为 TestResources 的资源组。The instructions for this article used a resource group named TestResources. 在结果列表中的资源组上,单击“...”,然后单击“删除资源组” 。On your resource group in the result list, click ... then Delete resource group.


系统会要求确认是否删除资源组。You will be asked to confirm the deletion of the resource group. 键入资源组的名称进行确认,然后单击“删除”。Type the name of your resource group to confirm, and click Delete.

片刻之后,将会删除该资源组及其包含的所有资源。After a few moments, the resource group and all of its contained resources are deleted.

后续步骤Next steps

本快速入门介绍了如何通过 .NET 应用程序使用 Azure Redis 缓存。In this quickstart, you learned how to use Azure Cache for Redis from a .NET application. 请继续学习下一个快速入门,将 Azure Redis 缓存与 ASP.NET Web 应用配合使用。Continue to the next quickstart to use Azure Cache for Redis with an ASP.NET web app.