本文提供关于如何管理用于 Redis 的 Azure 缓存的常见问题解答。
- 用于
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 端口 。
- 请确保用于测试的客户端虚拟机与 Azure Redis 缓存实例位于同一区域。
- 确保客户端 VM 的计算和带宽功能至少与要测试的缓存相同。 为了获得最佳效果,请将 D 系列和 E 系列 VM 用于客户端。
- 如果使用的是 Windows,请在计算机上启用虚拟接收端缩放(VRSS)。 有关详细信息,请参阅 Windows Server 2012 R2 中的虚拟接收端缩放。
- 启用缓存诊断,以便 可以监视 缓存的运行状况。 可以在 Azure 门户中查看指标,还可以使用所选的工具 下载和查看指标 。
- 如果负载导致内存碎片过高,请纵向扩展到更大的缓存大小。
以下示例演示如何使用 redis-benchmark.exe
。 从缓存所在的同一区域中的 VM 运行这些命令,以获取准确的结果。
首先,使用 1k 有效负载测试管道 SET
请求:
redis-benchmark.exe -h <yourcache>.redis.cache.chinacloudapi.cn -a <yourAccesskey> -t SET -n 1000000 -d 1024 -P 50
运行 SET
测试后,使用 1k 有效负载运行管道 GET
请求:
redis-benchmark.exe -h <yourcache>.redis.cache.chinacloudapi.cn -a <yourAccesskey> -t GET -n 1000000 -d 1024 -P 50
启用服务器垃圾回收(GC)可以优化客户端,并在使用 StackExchange.Redis 时提供更好的性能和吞吐量。 有关服务器 GC 以及如何启用它的详细信息,请参阅以下文章:
Redis 服务器原生不支持传输层安全性(TLS),但 Azure Redis 缓存支持 TLS。 如果使用支持 TLS 的 StackExchange.Redis 等客户端连接到 Azure Redis 缓存,请使用 TLS。
注意
对于新的 Azure Redis 实例,默认禁用非 TLS 端口。 如果客户端不支持 TLS,请遵循 Access 端口上的指示启用非 TLS 端口。
如果缓存使用 TLS,则必须使用 --tls
Redis 工具 redis-cli
的选项来启用 TLS。 还可以使用实用工具(例如 stunnel
,按照 公告 ASP.NET 会话状态提供程序 for Redis 预览版发布 博客文章中的说明安全地将工具连接到 TLS 端口。
有关下载 Redis 工具的说明,请参阅 如何运行 Redis 命令?
对于某些需要较长时间才能完成的 Redis 命令,除非完全了解这些命令的结果,否则请避免使用这些命令。 例如,请勿在生产中运行 KEYS 命令。 它可能需要很长时间才能返回,具体时间取决于键数。 Redis 是一个单线程服务器,一次处理一个命令。 如果发出
KEYS
命令,则 Redis 在处理KEYS
完命令之前不会处理后续命令。redis.io 站点具有它支持的每个作的时间复杂性详细信息。 选择每个命令以查看每个操作的复杂程度。
要使用的键大小取决于方案。 如果方案需要较大的密钥,可以调整
ConnectionTimeout
、重试值并调整重试逻辑。 从 Redis 服务器的角度来看,较小的键值可提供更好的性能。这些注意事项并不意味着无法在 Redis 中存储更大的值,但延迟更高。 如果你有一组大于另一组的数据,则可以使用多个
ConnectionMultiplexer
实例,每个实例都配置了一组不同的超时和重试值。 有关详细信息,请参阅 StackExchange.Redis 配置选项执行的作?
每个 Azure Redis 缓存定价层对客户端连接、内存和带宽有不同的限制。 虽然每个缓存大小 最多 允许一些连接,但与 Redis 的每个连接都涉及关联的开销。 此类开销的一个示例是由于 TLS/SSL 加密而使用的 CPU 和内存使用率。
给定缓存大小的最大连接限制假定轻负载缓存。 如果来自连接开销 的负载加上 客户端作的负载超过系统的容量,则即使未超过当前缓存大小的连接限制,缓存也可能会遇到容量问题。
有关每个层的连接限制的详细信息,请参阅 Azure Redis 缓存定价。 有关连接和其他默认配置的详细信息,请参阅默认 Redis 服务器配置。
- 对生产系统使用标准层或高级层。 基本层是一个没有数据复制且没有服务级别协议(SLA)的单节点系统。 此外,至少使用 C1 缓存进行生产。 C0 缓存通常用于简单的开发/测试方案。
- 请注意,Redis 是 内存中 数据存储,在某些情况下可能会丢失数据。 有关详细信息,请参阅 排查 Azure Cache for Redis 中的数据丢失问题。
- 开发系统,以便它可以处理 修补和故障转移导致的连接故障。
- 使用高级层 Azure Redis 实例提供更好的网络延迟和吞吐量,因为它们具有更好的 CPU 和网络硬件。
- 设置为
AbortConnect
false,然后自动重新ConnectionMultiplexer
连接。 - 使用一个生存期长的
ConnectionMultiplexer
实例,而不是为每个请求新建连接。 - 具有较小值的 Redis 工作性能最佳,因此请考虑将较大数据分成多个密钥。 有关详细信息,请参阅 “考虑更多键”和较小值。
- 配置 ThreadPool 设置 ,以免超时。
- 至少使用默认值
connectTimeout
5 秒。 此间隔为 StackExchange.Redis 提供足够的时间来重新建立连接(如果有网络故障)。 - 请注意与运行的不同作相关的性能成本。 例如,
KEYS
命令是 O(n) 操作,应当避免。 redis.io 站点详细介绍了它支持的每个作的时间复杂性。 选择每个命令以查看每个操作的复杂程度。
公共语言运行时 (CLR) ThreadPool 有两种类型的线程:辅助角色和 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
对于线程,有六个繁忙线程,系统配置为允许四个最小线程。 在这种情况下,客户端可能会看到两个 500 毫秒的延迟,因为 6 > 4。
注意
如果任一增长 IOCP
或 WORKER
线程受到限制,StackExchange.Redis 可能会达到超时。
最好将最小配置值 IOCP
和 WORKER
线程设置为大于默认值的值。 对于此值,没有一个大小拟合的指南,因为一个应用程序的合适值对于另一个应用程序来说可能过高或太低。 此设置还可能会影响复杂应用程序的其他部分的性能。 需要根据特定需求微调此设置。 一个很好的起点是 200
或 300
。 然后根据需要进行测试和调整。
可以使用 ThreadPool.SetMinThreads (...) 方法以编程方式更改此设置。
例如,在 NET Framework 中, 在方法Global.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()
在Program.cs设置值:
const int minThreads = 200
ThreadPool.SetMinThreads(minThreads, minThreads);
var builder = WebApplication.CreateBuilder(args);
// rest of application setup
注意
此方法指定的值是影响整个 AppDomain 的全局设置。 例如,如果有一个四核 VM,并且希望在运行时为每个 CPU 设置 minWorkerThreads
minIoThreads
50 个,请使用 ThreadPool.SetMinThreads(200, 200)
。
还可以通过使用 minIoThreads
Machine.config中的配置元素下的<processModel>
或minWorkerThreads
配置设置来指定最小线程设置。Machine.config 通常位于 %SystemRoot%\Microsoft.NET\Framework\versionNumber>\<CONFIG\。
不建议以这种方式设置最小线程数,因为它是系统范围的设置。 如果这样做设置了最小线程,则必须重启应用程序池。
注意
此方法指定的值是 按核心 设置。 例如,如果你有一台四核计算机,并且希望 minIoThreads
设置在运行时为 200,请使用 <processModel minIoThreads="50">
。
- 请参阅其他 Azure Redis 缓存常见问题解答。