缓存管理常见问题解答

本文提供有关如何管理Azure Cache for Redis的常见问题的解答。

重要

Azure Cache for Redis公布了所有产品型号的停用时间表。 建议尽快将现有Azure Cache for Redis实例移动到Azure托管 Redis。

迁移指南:

有关停用的更多详细信息:

如何进行基准检验和测试缓存的性能?

  • 使用 redis-benchmark.exe 对 Redis 服务器进行负载测试。 在编写自己的性能测试之前,可以使用redis-benchmark.exe来了解预计的吞吐量。
  • 使用redis-cli通过INFO命令监视缓存。 有关下载 Redis 工具的说明,请参阅 如何运行 Redis 命令?
  • 如果在缓存实例上使用传输层安全性/安全套接字层(TLS/SSL),请将 --tls 参数添加到 Redis 工具命令,或使用类似于 stunnel 启用 TLS/SSL 的代理。
  • Redis-benchmark 默认情况下使用端口 6379-p如果缓存使用 SSL/TLS 端口6380,请使用参数替代此设置。
  • 如有必要,可以在运行负载测试之前通过 Azure 门户实现非 TLS 端口。
  • 确保用于测试的客户端虚拟机(VM)与Azure Cache for Redis实例位于同一区域。
  • 确保客户端 VM 的计算和带宽功能至少与要测试的缓存相同。 为了获得最佳效果,请将 D 系列和 E 系列 VM 用于客户端。
  • 如果您使用的是 Windows,请在客户端计算机上启用虚拟接收端缩放(VRSS)。 有关详细信息,请参阅 Windows Server 2012 R2 中的虚拟接收端缩放。
  • 启用缓存诊断,以便 可以监视 缓存的运行状况。 可以在Azure门户中查看指标,还可以使用所选的工具下载和查看指标
  • 如果负载导致内存碎片过高,请将缓存扩展到更大的大小。

以下示例演示如何使用 redis-benchmark.exe。 从缓存所在的同一区域中的 VM 运行这些命令,以获取准确的结果。

首先,使用 1千字节的有效负载测试管道 SET 请求:

redis-benchmark.exe -h <yourcache>.redis.cache.chinacloudapi.cn -a <yourAccesskey> -t SET -n 1000000 -d 1024 -P 50

运行 SET 测试后,使用 1千字节的有效负载运行流水线化 GET 请求:

redis-benchmark.exe -h <yourcache>.redis.cache.chinacloudapi.cn -a <yourAccesskey> -t GET -n 1000000 -d 1024 -P 50

如何使用 StackExchange.Redis 使服务器 GC 在客户端上获取更多吞吐量?

启用服务器垃圾回收(GC)可以优化客户端,并在使用 StackExchange.Redis 时提供更好的性能和吞吐量。 有关服务器 GC 以及如何启用它的详细信息,请参阅以下文章:

是否应启用非 TLS/SSL 端口以连接到 Redis?

Redis 服务器本身不支持传输层安全性(TLS),但Azure Cache for Redis支持 TLS。 如果使用支持 TLS 的 StackExchange.Redis 等客户端连接到 Azure Cache for Redis,请使用 TLS。

注意

对于新的 Azure Redis 实例,默认禁用非 TLS 端口。 如果客户端不支持 TLS,请遵循 Access 端口上的指示启用非 TLS 端口。

如果缓存使用 TLS,则必须通过使用 Redis 工具的 --tls 选项 redis-cli 来启用 TLS。 还可以按照 stunnel 博客文章中的说明,使用 等实用工具安全地将工具连接到 TLS 端口。

有关下载 Redis 工具的说明,请参阅 如何运行 Redis 命令?

使用常见 Redis 命令的一些注意事项是什么?

  • 对于某些需要较长时间才能完成的 Redis 命令,除非完全了解这些命令的结果,否则请避免使用这些命令。 例如,请勿在生产中运行 KEYS 命令。 它可能需要很长时间才能返回,具体时间取决于键数。 Redis 是一个单线程服务器,一次处理一个命令。 如果发出 KEYS 命令,则 Redis 在处理 KEYS 完命令之前不会处理后续命令。

    redis.io 站点提供它支持的每个操作的时间复杂度的详细信息。 选择每个命令以查看每个操作的复杂程度。

  • 要使用的键大小取决于具体的情境。 如果方案需要较大的密钥,可以调整 ConnectionTimeout、重试值并调整重试逻辑。 从 Redis 服务器的角度来看,较小的键值可提供更好的性能。

  • 这些注意事项并不意味着无法在 Redis 中存储更大的值,但延迟更高。 如果你有一组大于另一组的数据,则可以使用多个 ConnectionMultiplexer 实例,每个实例都配置了一组不同的超时和重试值。 有关详细信息,请参阅 StackExchange.Redis 配置选项的作用?

连接有哪些性能注意事项?

每个Azure Cache for Redis定价层对客户端连接、内存和带宽有不同的限制。 虽然每个缓存大小允许一定数量的连接,但与 Redis 的每个连接都涉及相关的开销。 此类开销的一个示例是由于 TLS/SSL 加密而使用的 CPU 和内存使用率。

给定缓存大小的最大连接限制假定轻负载缓存。 如果来自连接开销 的负载加上 客户端作的负载超过系统的容量,则即使未超过当前缓存大小的连接限制,缓存也可能会遇到容量问题。

有关每个层的连接限制的详细信息,请参阅 Azure Cache for Redis 定价。 有关连接和其他默认配置的详细信息,请参阅默认 Redis 服务器配置

生产的一些最佳做法是什么?

  • 对生产系统使用标准层或高级层。 基本层是一个没有数据复制且没有服务级别协议(SLA)的单节点系统。 此外,在生产环境中至少使用 C1 缓存。 C0 缓存通常用于简单的开发/测试方案。
  • 请注意,Redis 是 内存中 数据存储,在某些情况下可能会丢失数据。 有关详细信息,请参阅 Azure Cache for Redis 中的数据丢失故障排除
  • 确保你的系统可以应对修补和故障转移导致的短暂的连接中断。
  • 使用高级层Azure Redis 实例提供更好的网络延迟和吞吐量,因为它们具有更好的 CPU 和网络硬件。

StackExchange.Redis 最佳做法

  • AbortConnect设置为false,然后让ConnectionMultiplexer自动重新连接。
  • 使用一个生存期长的 ConnectionMultiplexer 实例,而不是为每个请求新建连接。
  • 具有较小值的 Redis 工作性能最佳,因此请考虑将较大数据分成多个密钥。 有关详细信息,请参阅 考虑更多键和较小值
  • 配置 ThreadPool 设置 ,以免超时。
  • 至少使用默认值 connectTimeout 5 秒。 此间隔为 StackExchange.Redis 提供足够的时间来重新建立连接(如果有网络故障)。
  • 请注意与您运行的不同操作相关的性能成本。 例如,KEYS 命令是 O(n) 操作,应当避免。 redis.io 站点提供了关于其支持的每个操作时间复杂度的详细信息。 选择每个命令以查看每个操作的复杂程度。

有关线程池增长的重要详细信息

公共语言运行时(CLR)线程池有两种类型的线程:工作线程和I/O完成端口(IOCP)。

  • WORKER 线程用于处理 Task.Run(…)ThreadPool.QueueUserWorkItem(…) 方法等作。 当工作需要在后台线程上发生时,CLR 中的各种组件也会使用这些线程。
  • IOCP 线程用于异步 I/O,例如从网络读取时。

线程池按需提供新的工作线程或 I/O 完成线程,且不会加以限制,直到达到每种类型线程的 minimum 设置。 默认情况下,最小线程数设置为系统上的处理器数。

一旦现有繁忙线程数达到 minimum 线程数,ThreadPool 会限制将新线程每 500 毫秒注入一个线程的速率。

通常,如果系统突然有需要 IOCP 线程的工作负载增加,系统会快速处理这些任务。 但是,如果突发流量超过配置的 minimum 设置,这样处理一些任务时会有延迟,因为 ThreadPool 等待以下两种可能性之一:

  • 一个现有线程释放,以便处理工作。
  • 没有现有线程在 500 毫秒内变为可用,因此会创建一个新线程。

基本上,当线程数 Busy 大于 Min 线程时,在应用程序处理网络流量之前遇到 500 毫秒的延迟。 此外,将清理空闲时间超过 15 秒的现有线程,并且这种增长和收缩的循环可能会重复发生。

来自 StackExchange.Redis 版本 1.0.450 或更高的编译版本的错误消息会输出 ThreadPool 的统计信息,示例如下。

System.TimeoutException: Timeout performing GET MyKey, inst: 2, mgr: Inactive,
queue: 6, qu: 0, qs: 6, qc: 0, wr: 0, wq: 0, in: 0, ar: 0,
IOCP: (Busy=6,Free=994,Min=4,Max=1000),
WORKER: (Busy=3,Free=997,Min=4,Max=1000)

该示例显示, IOCP 对于线程,有六个繁忙线程,系统配置为允许四个最小线程。 在这种情况下,由于 6 > 4,客户端可能会观察到两次 500 毫秒的延迟。

注意

如果任一 IOCPWORKER 线程的增长受到限制,StackExchange.Redis 可能会发生超时。

最好将最小配置值 IOCPWORKER 线程设置为大于默认值的值。 对于此值,没有通用的建议,因为适合一个应用程序的数值可能对另一个应用程序而言过高或过低。 此设置还可能会影响复杂应用程序的其他部分的性能。 需要根据特定需求微调此设置。 一个很好的起点是 200300。 然后根据需要进行测试和调整。

配置最小线程设置

可以使用 ThreadPool.SetMinThreads (...) 方法以编程方式更改此设置。

例如,在 NET FrameworkGlobal.asax.cs 文件中,在 Application_Start 方法里设置此值。

    private readonly int minThreads = 200;
    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
        AreaRegistration.RegisterAllAreas();
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        ThreadPool.SetMinThreads(minThreads, minThreads);
    }

如果使用 .NET Core,在调用 之前,在 WebApplication.CreateBuilder() 中设置值:

    const int minThreads = 200
                  
    ThreadPool.SetMinThreads(minThreads, minThreads);
    
    var builder = WebApplication.CreateBuilder(args);
    // rest of application setup

注意

此方法指定的值是影响整个 AppDomain 的全局设置。 例如,如果有一个四核 VM,并且希望在运行时为每个 CPU 设置 minWorkerThreadsminIoThreads 50 个,请使用 ThreadPool.SetMinThreads(200, 200)

还可以通过使用 minIoThreadsminWorkerThreads配置设置<processModel> 配置元素之下在 Machine.config 中指定最小线程设置。Machine.config 通常位于 %SystemRoot%\Microsoft.NET\Framework\<versionNumber>\CONFIG\

不建议以这种方式设置最小线程数,因为它是系统范围的设置。 如果这样做设置了最小线程,则必须重启应用程序池。

注意

此方法指定的值是 按核心 设置。 例如,如果你有一台四核计算机,并且希望 minIoThreads 设置在运行时为 200,请使用 <processModel minIoThreads="50">