你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Azure 托管 Redis(预览版)管理常见问题解答

本文提供关于如何管理 Azure 托管 Redis 的常见问题解答。

何时应启用非 TLS/SSL 端口来连接 Redis?

在几乎所有 Redis 用例中,都建议使用 TLS 作为最佳做法。 为了向后兼容,包含了不使用 TLS 进行连接的选项。

注意

默认情况下,为新的 Azure 托管 Redis(预览版)实例禁用了非 TLS 端口。 如果客户端不支持 TLS,则必须根据在 Azure 托管 Redis 中配置缓存一文的访问端口部分中的说明启用非 TLS 端口。

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

StackExchange.Redis 最佳做法

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

配置和概念

性能测试

使用常见 Redis 命令时要注意哪些问题?

  • 对于某些需要较长时间才能完成的 Redis 命令,除非完全了解这些命令的结果,否则请避免使用这些命令。 例如,请勿在生产中运行 KEYS 命令。 它可能需要很长时间才能返回,具体时间取决于键数。 每个 Redis 分片都是单线程的,每次只处理一个命令。 如果在 KEYS 后面发出了其他命令,则这些命令只会在处理完 KEYS 命令后才会得到处理。 redis.io 站点 具有关于其支持的每个操作的时间复杂性的详细信息。 选择每个命令以查看每个操作的复杂程度。
  • 键大小 - 应使用小键/值还是大键/值? 这取决于方案。 如果方案需要较大的键,则可调整 ConnectionTimeout,然后重试值并调整重试逻辑。 从 Redis 服务器的角度来看,值越小,性能就越好。
  • 这些考量并不意味着不能在 Redis 中存储较大值,只是要注意以下事项。 延迟较高。 如果采用一个较大的数据集和一个较小的数据集,则可以使用多个 ConnectionMultiplexer 实例。 根据 StackExchange.Redis 配置选项有什么作用部分中所述,为每个实例配置一组不同的超时和重试值。

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

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

CLR 线程池具有两种类型的线程 -“辅助角色”和“I/O 完成端口”(IOCP) 线程。

  • 对于诸如处理 Task.Run(…)ThreadPool.QueueUserWorkItem(…) 方法这类事务,请使用辅助角色线程。 需要在后台线程上进行工作时,CLR 中的各种组件也会使用这些线程。
  • 进行异步 IO(例如从网络进行读取)时,使用 IOCP 线程。

线程池按需提供新的辅助角色线程或 I/O 完成线程(没有任何限制),直到它达到每种线程类型的“最小值”设置。 默认情况下,最小线程数设置为系统上的处理器数。

一旦现有(忙碌)线程数达到“最小”线程数,ThreadPool 便会将注入新线程的速率限制为每 500 毫秒一个线程。 通常,如果系统中出现需要 IOCP 线程的突发工作,则它会快速处理该工作。 但是,如果突发多于配置的“最小值”设置,则在处理某些工作时会出现一定的延迟,因为线程池会等待发生以下两种情况之一:

  • 一个现有线程释放,以便处理工作。
  • 在 500 毫秒内没有任何现有线程释放,并会创建一个新线程。

基本上,当忙碌线程数大于最小线程数时,在应用程序处理网络流量之前可能需要付出 500 毫秒延迟。 此外,当现有线程保持空闲状态的时间超过 15 秒时,系统会清理它,并且这种增长和收缩的循环可能会重复。

如果我们考虑一个来自 StackExchange.Redis(内部版本 1.0.450 或更高版本)的示例错误消息,会看到它现在会打印线程池统计信息。 请参阅下面的 IOCP 和辅助角色的详细信息。

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 毫秒延迟,因为 6 > 4。

注意

如果 IOCP 或辅助角色线程受到限制,则 StackExchange.Redis 可以会超时。

建议

考虑到此信息,我们强烈建议客户将 IOCP 和辅助角色线程的最小配置值设置为大于默认值。 我们无法提供有关此值应是多少的通用指导,因为适合一个应用程序的值对于另一个应用程序可能太高或太低。 此设置还可能会影响复杂应用程序其他部分的性能,因此每个客户需要按照其特定需求来微调此设置。 开始时设置为 200 或 300 会比较好,随后可进行测试并根据需要进行调整。

如何配置此设置:

  • 建议使用 global.asax.cs 中的 ThreadPool.SetMinThreads (...) 方法,以编程方式更改此设置。 例如:

    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);
    }
    

    注意

    此 方法指定的值是全局设置,将影响整个 AppDomain。 例如,如果已有 4 核计算机,并想要在运行时将 minWorkerThreads 和 minIoThreads 设置为 50(每个 CPU),请使用 ThreadPool.SetMinThreads(200, 200)

  • 还可以使用 Machine.config<processModel> 配置元素下的 minIoThreads 或 minWorkerThreads 配置设置来指定最小线程设置。 Machine.config 通常位于 %SystemRoot%\Microsoft.NET\Framework\[versionNumber]\CONFIG\。 不建议以这种方式设置最小线程数,因为这是系统范围设置。

    注意

    此配置元素中指定的值是按核心设置。 例如,如果使用 4 核计算机,并且希望 minIoThreads 设置在运行时为 200,则使用 <processModel minIoThreads="50"/>

启用服务器 GC,以便在使用 StackExchange.Redis 时在客户端上获取更多吞吐量

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

围绕连接的性能注意事项

不同的 SKU 可能有不同的客户端连接、内存和带宽限制。 虽然每个缓存大小最多允许一定数量的连接,但与 Redis 的每个连接都具有其关联的开销。 此类开销的一个示例是,由于 TLS/SSL 加密而导致的 CPU 和内存使用。 给定缓存大小的最大连接限制假定轻负载缓存。 如果连接开销的负载加上客户端操作的负载超出了系统容量,那么即使未超出当前缓存大小的连接限制,缓存也可能会遇到容量问题。

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

后续步骤

了解其他 Azure 托管 Redis 常见问题解答