Thousands of TimeoutExceptions after switching to Redis Enterprise

Viewed 632

We recently attempted to switch from Azure Redis to Redis Enterprise, unfortunately after about an hour we were forced to roll back due to performance issues. We're looking for advice on how to get to the root cause and proceed. Here's what I've figured out so far, but I'm happy to add any more details as necessary.

First off, the client is a .NET Framework app using StackExchange.Redis version 2.1.30. The Azure Redis instance is using 4 shards, and the Redis Enterprise instance is also configured for 4 shards.

When we switched over to Redis Enterprise, we would immediately see several thousand of these exceptions per 5 minute interval:

Timeout performing GET (5000ms), next: GET [Challenges]::306331, inst: 1, qu: 0, qs: 3079, aw: False, rs: ReadAsync, ws: Idle, in: 0, serverEndpoint: xxxxxxx:17142, mc: 1/1/0, mgr: 9 of 10 available, clientName: API, IOCP: (Busy=2,Free=998,Min=400,Max=1000), WORKER: (Busy=112,Free=32655,Min=2000,Max=32767), Local-CPU: 4.5%, v: 2.1.30.38891 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)

Looking at this error message, it appears there's tons of things in the WORKER thread pool (things waiting on a response from Redis Enterprise), but nearly nothing in the IOCP thread pool (responses from Redis waiting to be processed by our client code). So, there's some sort of bottleneck on the Redis side.

Using AppInsights, I created a graph of the busy worker threads (dark blue), busy IO threads (red), and CPU usage (light blue). We see something like this:

enter image description here

The CPU never really goes above 20% or so, the IO threads are barely a blip (I think the max is like 2 busy), but the worker threads kinda grow and grow until eventually everything times out and the process starts over again. A little after 7pm is when we decided to roll back to Azure Redis, so everything is great at that point. So, everything points to Redis being some sort of bottleneck. So, let's look at the Redis side of things.

During this time, Redis reported a max of around 5% CPU usage. Incoming traffic topped out around 1.4MB/s, and outgoing traffic topped out around 9.5MB/s. Ops/sec were around 4k. Latency around this time was 0.05ms, and the slowest thing in the SLOWLOG was like 15ms or so. In other words, the Redis Enterprise node was barely breaking a sweat and was easily able to keep up with the traffic being sent to it. In fact, we had 4 other nodes in the cluster that weren't even being used since Redis didn't even see the need to send anything to other nodes. Redis was basically just yawning.

From here, I was thinking maybe there were network bandwidth contraints. All of our VMs are configured for accelerated networking, and we should have 10gig connections to these machines. I decided to run an iperf between the client and the server:

enter image description here

I can transfer easily over 700Mbit/sec between the client and the Redis Enterprise server, yet the server is processing 9.5MB/sec easily. So, it doesn't appear the problem is network bandwidth.

So, here's where we stand:

  • The same code works great with Azure Redis, yet causes thousands of timeouts when we switch over to Redis Enterprise.
  • Redis Enterprise is handling 4,000 operations per second and sending out 9 megs a second, and can usually handle a single operation in a fraction of a ms, with the very longest being 15ms.
  • I can send 700+ Mb/sec between the client and server.
  • Yet, the WORKER thread pool builds up with pending requests to Redis and eventually times out.

I'm pretty stuck here. What's a good next step to diagnose this issue? Thanks!

0 Answers
Related