-
Notifications
You must be signed in to change notification settings - Fork 21.8k
Expand file tree
/
Copy pathcache-management-faq.yml
More file actions
180 lines (131 loc) · 15.5 KB
/
cache-management-faq.yml
File metadata and controls
180 lines (131 loc) · 15.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
### YamlMime:FAQ
metadata:
title: Cache management FAQs
description: Learn the answers to common questions that help you manage Azure Cache for Redis.
ms.topic: faq
ms.custom: devx-track-csharp, ignite-2024
ms.date: 04/22/2025
appliesto:
- ✅ Azure Cache for Redis
title: Cache management FAQs
summary: |
This article provides answers to common questions about how to manage Azure Cache for Redis.
[!INCLUDE [cache-retirement-alert](includes/cache-retirement-alert.md)]
sections:
- name: Ignored
questions:
- question: |
How can I benchmark and test the performance of my cache?
answer: |
- Use `redis-benchmark.exe` to load test your Redis server. Use `redis-benchmark.exe` to get a feel for possible throughput before writing your own performance tests.
- Use `redis-cli` to monitor the cache using the `INFO` command. For instructions on downloading the Redis tools, see [How can I run Redis commands?](cache-development-faq.yml#how-can-i-run-redis-commands-)
- If you use Transport Layer Security/Secure Socket Layer (TLS/SSL) on your cache instance, add the `--tls` parameter to your Redis tools commands, or use a proxy like `stunnel` to enable TLS/SSL.
- `Redis-benchmark` uses port `6379` by default. Use the `-p` parameter to override this setting if your cache uses the SSL/TLS port `6380` or the Enterprise tier port `10000`.
- If necessary, you can [enable the non-TLS port through the Azure portal](cache-configure.md#access-ports) before you run the load test.
- Make sure the client virtual machine (VM) you use for testing is in the same region as your Azure Cache for Redis instance.
- Ensure that your client VM has at least as much computing and bandwidth capability as the cache you're testing. For best results, use D-series and E-series VMs for your clients.
- If you're on Windows, enable Virtual Receive-side Scaling (VRSS) on the client machine. For more information, see [Virtual Receive-side Scaling in Windows Server 2012 R2](/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/dn383582(v=ws.11)).
- Enable cache diagnostics so you can [monitor](../redis/monitor-cache.md) the health of your cache. You can view the metrics in the Azure portal, and you can also [download and review your metrics](https://github.com/rustd/RedisSamples/tree/master/CustomMonitoring) using the tools of your choice.
- If your load is causing high memory fragmentation, scale up to a larger cache size.
The following examples show how to use `redis-benchmark.exe`. Run these commands from a VM in the same region as your cache for accurate results.
First, test pipelined `SET` requests using a 1k payload:
`redis-benchmark.exe -h <yourcache>.redis.cache.windows.net -a <yourAccesskey> -t SET -n 1000000 -d 1024 -P 50`
After you run the `SET` test, run pipelined `GET` requests using a 1k payload:
`redis-benchmark.exe -h <yourcache>.redis.cache.windows.net -a <yourAccesskey> -t GET -n 1000000 -d 1024 -P 50`
- question: |
How can I enable server GC to get more throughput on the client when using StackExchange.Redis?
answer: |
Enabling server garbage collection (GC) can optimize the client and provide better performance and throughput when you use StackExchange.Redis. For more information on server GC and how to enable it, see the following articles:
- [The \<gcServer> element](/dotnet/framework/configure-apps/file-schema/runtime/gcserver-element)
- [Fundamentals of garbage collection](/dotnet/standard/garbage-collection/fundamentals)
- [Garbage collection and performance](/dotnet/standard/garbage-collection/performance)
- question: |
Should I enable the non-TLS/SSL port for connecting to Redis?
answer: |
Redis server doesn't natively support Transport Layer Security (TLS), but Azure Cache for Redis does support TLS. If you connect to Azure Cache for Redis with a client like StackExchange.Redis that supports TLS, then use TLS.
>[!NOTE]
>The non-TLS port is disabled by default for new Azure Redis instances. If your client doesn't support TLS, enable the non-TLS port by following the directions at [Access ports](cache-configure.md#access-ports).
>
If the cache uses TLS, you must enable TLS by using the `--tls` option for Redis tools like `redis-cli`. You can also use a utility such as `stunnel` to securely connect the tools to the TLS port by following the directions in the [Announcing ASP.NET Session State Provider for Redis Preview Release](https://devblogs.microsoft.com/aspnet/announcing-asp-net-session-state-provider-for-redis-preview-release/) blog post.
For instructions on downloading the Redis tools, see [How can I run Redis commands?](cache-development-faq.yml#how-can-i-run-redis-commands-)
- question: |
What are some considerations for using common Redis commands?
answer: |
- Avoid using certain Redis commands that take a long time to complete, unless you fully understand the result of these commands. For example, don't run the [KEYS](https://redis.io/commands/keys) command in production. Depending on the number of keys, it could take a long time to return. Redis is a single-threaded server that processes commands one at a time. If you issue the `KEYS` command, Redis doesn't process subsequent commands until it finishes processing the `KEYS` command.
The [redis.io](https://redis.io/commands/) site has time complexity details for each operation it supports. Select each command to see the complexity for each operation.
- What size keys to use depends on the scenario. If your scenario requires larger keys, you can adjust the `ConnectionTimeout`, then retry values and adjust your retry logic. From a Redis server perspective, smaller key values give better performance.
- These considerations don't mean that you can't store larger values in Redis, but latencies are higher. If you have one set of data that's larger than another, you can use multiple `ConnectionMultiplexer` instances, each configured with a different set of timeout and retry values. For more information, see [What do the StackExchange.Redis configuration options do?](cache-development-faq.yml#what-do-the-stackexchange-redis-configuration-options-do-)
- question: |
What are some performance considerations for connections?
answer: |
Each Azure Cache for Redis pricing tier has different limits for client connections, memory, and bandwidth. While each size of cache allows *up to* some number of connections, each connection to Redis involves associated overhead. An example of such overhead is CPU and memory usage because of TLS/SSL encryption.
The maximum connection limit for a given cache size assumes a lightly loaded cache. If load from connection overhead *plus* load from client operations exceeds capacity for the system, the cache can experience capacity issues even if you don't exceed the connection limit for the current cache size.
For more information about the connection limits for each tier, see [Azure Cache for Redis pricing](https://azure.microsoft.com/pricing/details/cache/). For more information about connections and other default configurations, see [Default Redis server configuration](cache-configure.md#default-redis-server-configuration).
- question: |
What are some production best practices?
answer: |
- Use Standard or Premium tier for Production systems. The Basic Tier is a single node system with no data replication and no service-level agreement (SLA). Also, use at least a C1 cache for Production. C0 caches are typically used for simple dev/test scenarios.
- Be aware that Redis is an *in-memory* data store, and data loss can occur in some scenarios. For more information, see [Troubleshoot data loss in Azure Cache for Redis](cache-troubleshoot-data-loss.md).
- Develop your system so it can handle connection blips caused by [patching and failover](cache-failover.md).
- Use Premium-tier Azure Redis instances for better network latency and throughput, because they have better hardware for both CPU and network.
### StackExchange.Redis best practices
- Set `AbortConnect` to false, then let the `ConnectionMultiplexer` reconnect automatically.
- Use a single, long-lived `ConnectionMultiplexer` instance rather than creating a new connection for each request.
- Redis works best with smaller values, so consider chopping up bigger data into multiple keys. For example, in [What is the ideal value size range for redis?](https://groups.google.com/forum/#!searchin/redis-db/size/redis-db/n7aa2A4DZDs/3OeEPHSQBAAJ), 100 kb is considered large. For more information, see [Consider more keys and smaller values](cache-best-practices-development.md#consider-more-keys-and-smaller-values).
- Configure your [ThreadPool settings](#important-details-about-threadpool-growth) to avoid timeouts.
- Use at least the default `connectTimeout` of 5 seconds. This interval gives StackExchange.Redis sufficient time to reestablish the connection if there's a network blip.
- Be aware of the performance costs associated with different operations you run. For instance, the `KEYS` command is an O(n) operation and should be avoided. The [redis.io](https://redis.io/commands/) site has details about the time complexity of each operation it supports. Select each command to see the complexity for each operation.
- question: |
Important details about ThreadPool growth
answer: |
The Common Language Runtime (CLR) ThreadPool has two types of threads, Worker and I/O Completion Port (IOCP).
- `WORKER` threads are used for things like processing the `Task.Run(…)`, or `ThreadPool.QueueUserWorkItem(…)` methods. Various components in the CLR also use these threads when work needs to happen on a background thread.
- `IOCP` threads are used for asynchronous I/O, such as when reading from the network.
The thread pool provides new worker threads or I/O completion threads on demand without any throttling until it reaches the `minimum` setting for each type of thread. By default, the minimum number of threads is set to the number of processors on a system.
Once the number of existing busy threads hits the `minimum` threads number, the ThreadPool throttles the rate at which it injects new threads to one thread per 500 milliseconds.
Typically, if your system gets a burst of work that needs an `IOCP` thread, it processes that work quickly. However, if the burst is more than the configured `minimum` setting, there's some delay in processing some of the work as the ThreadPool waits for one of two possibilities:
- An existing thread becomes free to process the work.
- No existing thread becomes free for 500 ms so a new thread is created.
Basically, when the number of `Busy` threads is greater than `Min` threads, you experience a 500-ms delay before the application processes the network traffic. Also, an existing thread that stays idle for longer than 15 seconds is cleaned up, and this cycle of growth and shrinkage can repeat.
Error messages from StackExchange.Redis build 1.0.450 or later print ThreadPool statistics, as shown in the following example.
```output
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)
```
The example shows that for the `IOCP` thread, there are six busy threads and the system is configured to allow four minimum threads. In this case, the client is likely to see two 500-ms delays, because 6 > 4.
> [!NOTE]
> StackExchange.Redis can hit timeouts if growth of either `IOCP` or `WORKER` threads is throttled.
It's best to set the minimum configuration value for `IOCP` and `WORKER` threads to something larger than the default value. There's no one-size-fits-all guidance on this value, because the right value for one application is likely too high or low for another application. This setting can also affect the performance of other parts of complicated applications. You need to fine-tune this setting to your specific needs. A good starting place is `200` or `300`. Then test and tweak as needed.
#### Configure the minimum threads setting
You can change this setting programmatically by using the [ThreadPool.SetMinThreads (...)](/dotnet/api/system.threading.threadpool.setminthreads#System_Threading_ThreadPool_SetMinThreads_System_Int32_System_Int32_) method.
For example, in NET Framework, you set this value in *Global.asax.cs* in the `Application_Start` method:
```csharp
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);
}
```
If you use .NET Core, you set the value in *Program.cs* just before the call to `WebApplication.CreateBuilder()`:
```csharp
const int minThreads = 200
ThreadPool.SetMinThreads(minThreads, minThreads);
var builder = WebApplication.CreateBuilder(args);
// rest of application setup
```
> [!NOTE]
> The value specified by this method is a global setting that affects the whole AppDomain. For example, if you have a four-core VM and want to set `minWorkerThreads` and `minIoThreads` to 50 per CPU during runtime, use `ThreadPool.SetMinThreads(200, 200)`.
It's also possible to specify the minimum threads setting by using the `minIoThreads` or `minWorkerThreads` [configuration setting](/previous-versions/dotnet/netframework-4.0/7w2sway1(v=vs.100)) under the `<processModel>` configuration element in *Machine.config*. *Machine.config* is typically located at *%SystemRoot%\\Microsoft.NET\\Framework\\\<versionNumber>\\CONFIG\\*.
Setting the number of minimum threads in this way isn't recommended because it's a system-wide setting. If you do set minimum threads this way, you must restart the application pool.
> [!NOTE]
> The value specified by this method is a _per-core_ setting. For example, if you have a four-core machine and want your `minIoThreads` setting to be 200 at runtime, use `<processModel minIoThreads="50">`.
>
additionalContent: |
## Related content
- See other [Azure Cache for Redis FAQs](../redis/faq.yml).