本文提供有关如何管理 Azure Cache for Redis 的常见问题的解答。
如何制定基准和测试缓存的性能?
- 使用
redis-benchmark.exe对 Redis 服务器进行负载测试。 在编写自己的性能测试之前,使用redis-benchmark.exe来了解可能的吞吐量。 - 使用
redis-cli通过INFO命令监视缓存。 有关下载 Redis 工具的说明,请参阅如何运行 Redis 命令? - 如果在缓存实例上使用传输层安全性/安全套接字层 (TLS/SSL),请在 Redis 工具命令中添加
--tls参数,或者使用像stunnel这样的代理来启用 TLS/SSL。 -
默认情况下,
Redis-benchmark使用端口6379。 如果缓存使用的是 SSL/TLS 端口6380或企业版层级端口10000,请使用-p参数替代此设置。 - 如有必要,可以在运行负载测试前,通过 Azure 门户启用非 TLS 端口。
- 请确保用于测试的客户端虚拟机 (VM) 与 Azure Cache for 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.windows.net -a <yourAccesskey> -t SET -n 1000000 -d 1024 -P 50
运行 SET 测试后,使用 1k 有效负载运行管道化 GET 请求:
redis-benchmark.exe -h <yourcache>.redis.cache.windows.net -a <yourAccesskey> -t GET -n 1000000 -d 1024 -P 50
如何启用服务器 GC,以便在使用 StackExchange.Redis 时在客户端上获取更多吞吐量?
启用服务器 GC 可以在使用 StackExchange.Redis 时优化客户端并提供更好的性能和吞吐量。 有关服务器 GC 以及如何启用它的详细信息,请参阅以下文章:
是否应启用非 TLS/SSL 端口来连接 Redis?
Redis 服务器原生不支持传输层安全性 (TLS),但 Azure Cache for Redis 支持 TLS。 如果使用 StackExchange.Redis 等支持 TLS 的客户端连接到 Azure Cache for Redis,则应使用 TLS。
注意
默认情况下,为新的 Azure Redis 实例禁用了非 TLS 端口。 如果客户端不支持 TLS,请遵循访问端口中的说明启用非 TLS 端口。
如果缓存使用 TLS,则必须使用 Redis 工具(如 redis-cli)的 --tls 选项来启用 TLS。 还可以使用 stunnel 等实用工具,按照宣布推出适用于 Redis 预览版的 ASP.NET 会话状态提供程序博客文章中的说明,将工具安全连接到 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 Redis 缓存定价。 有关连接和其他默认配置的详细信息,请参阅默认 Redis 服务器配置。
生产的一些最佳做法是什么?
- 对生产系统使用标准层或高级层。 基本层是没有数据复制和没有服务级别协议 (SLA) 的单个节点系统。 此外,生产环境至少要使用 C1 缓存。 C0 缓存通常用于简单的开发/测试方案。
- 请注意,Redis 是内存中数据存储,在某些情况下可能会丢失数据。 有关详细信息,请参阅排查 Azure Cache for Redis 中的数据丢失问题。
- 开发系统以便处理由于修补和故障转移引起的连接故障。
- 使用高级层级的 Azure Redis 实例以获得更佳的网络延迟和吞吐量,因为这些实例的 CPU 和网络硬件性能更优。
StackExchange.Redis 的最佳做法
- 将
AbortConnect设置为 false,然后让ConnectionMultiplexer自动重新连接。 - 使用一个生存期长的
ConnectionMultiplexer实例,而不是为每个请求新建连接。 - 具有较小值的 Redis 工作性能最佳,因此请考虑将较大数据分成多个密钥。 例如,在 Redis 的理想值大小范围是多少?中,100 KB 被认为是大值。 有关更多信息,请参见考虑更多的键和更小的值。
- 配置 ThreadPool 设置,以免超时。
- 至少使用默认
connectTimeout5 秒。 出现网络故障时,此间隔可以给 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 设置,则在处理某些工作时会出现一定的延迟,因为线程池会等待发生以下两种情况之一:
- 一个现有线程释放,以便处理工作。
- 在 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 毫秒延迟,因为 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。 例如,如果你有一个四核虚拟机,并希望在运行时将 minWorkerThreads 和 minIoThreads 设置为每个 CPU 50,请使用 ThreadPool.SetMinThreads(200, 200)。
还可以通过在 Machine.config 中的 <processModel> 配置元素下使用 minIoThreads 或 minWorkerThreads配置设置来指定最小线程设置。Machine.config 通常位于 %SystemRoot%\Microsoft.NET\Framework<versionNumber>\CONFIG。
不建议以这种方式设置最小线程数,因为这是系统范围设置。 如果以这种方式设置最小线程数,则必须重启应用程序池。
注意
此方法指定的值是按核心设置。 例如,如果你有一台四核计算机,并希望在运行时将 minIoThreads 设置设为 200,请使用 <processModel minIoThreads="50">。
相关内容
- 请参阅其他 Azure Cache for Redis 常见问题解答。