本文提供关于如何管理 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 是 内存中 数据存储区。 有关详细信息,请参阅排查 Azure 托管 Redis 中的数据丢失问题,了解可能发生数据丢失的情况。
- 开发系统以便处理由于修补和故障转移引起的连接故障。
性能测试
- 请参阅使用 Azure 托管 Redis 进行性能测试,获取在 Azure 托管 Redis 上运行自己的性能测试的示例基准和说明。
使用常见 Redis 命令时要注意哪些问题?
- 对于某些需要较长时间才能完成的 Redis 命令,除非完全了解这些命令的结果,否则请避免使用这些命令。 例如,请勿在生产中运行 KEYS 命令。 它可能需要很长时间才能返回,具体时间取决于键数。 每个 Redis 分片都是单线程的,每次只处理一个命令。 如果在 KEYS 后面发出了其他命令,则这些命令只会在处理完 KEYS 命令后才会得到处理。 redis.io 站点 具有关于其支持的每个操作的时间复杂性的详细信息。 选择每个命令以查看每个操作的复杂程度。
- 键大小 - 应使用小键/值还是大键/值? 这取决于方案。 如果方案需要较大的键,则可调整 ConnectionTimeout,然后重试值并调整重试逻辑。 从 Redis 服务器的角度来看,值越小,性能就越好。
- 这些考量并不意味着不能在 Redis 中存储较大值,只是要注意以下事项。 延迟较高。 如果采用一个较大的数据集和一个较小的数据集,则可以使用多个 ConnectionMultiplexer 实例。 根据 StackExchange.Redis 配置选项有什么作用部分中所述,为每个实例配置一组不同的超时和重试值。
如何进行基准检验和测试缓存的性能?
- 启用缓存诊断,以便可以监视缓存的运行状况。 可以在 Azure 门户中查看指标,也可以使用所选的工具下载和查看这些指标。
- 请参阅使用 Azure 托管 Redis 进行性能测试,获取在 Azure 托管 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 常见问题解答。