1

我有一个在AWS ECS的linux容器中运行的ASP.Net Core Web API。此API主要从Redis获取数据,但如果数据库不在那里(我们设计了99.99%的数据位于Redis缓存中),它们将回退到数据库。我有一个相当高的负载进来约1-2K RPS(当然也许中到小到一些;-)。使用Stackexchange,负载下的MGET调用变得越来越慢。Redis

该API通过MGET(每个20-60的任何位置)查找几个密钥,以查找每个请求。一切都是异步的,没有同步代码或等待或其他死锁代码。 RPS越高,事情越慢,速度越慢。我也尝试过PreserveAsyncOrder = false,但那似乎更糟。

我不认为我的Redis服务器(在Elasticache中)是问题,指标显示CPU利用率几乎不到1%。另外,我创建的容器实例越多,延迟时间越长,我不希望看到服务器是否是瓶颈。

我听说TPL和SE.Redis有一个潜在的线程劫持问题(不知道它是否修复或者适用于.Net Core),所以我试着将所有东西都移动到同步而不是异步(虽然我的网络API调用仍然是异步的,但我对SE.Redis的调用是同步的)。这导致实际的超时而不是仅仅花费一段时间:

超时执行MGET,inst:5,队列:199,qu:0,qs:199,qc:0,wr:0,wq:0,in:150304 ,ar:0,客户端名称:,serverEndpoint:10.55.148.227:6379,keyHashSlot:-2

因为这是.Net Core超时异常似乎给予较少的信息比完整的堆栈,我看不到数量工作者线程或IOCP线程来查看是否存在瓶颈。

随着越来越多的超时发生,queue/qs:number和in:number一样增加。

这个数字让我相信我得到的回应只是没有足够快地处理它,我是否会陷入线程劫持问题?或者,也许我的客户端是网络绑定?

我也尝试为redis连接创建连接池,如SE.Redis超时页面所示。非常小的改进,但仍面临同样的问题。

任何帮助,将不胜感激。

回答

-1

Redis是单线程的。你正在增加单线程的负载,所以它的响应速度慢是有道理的。 MGET在单个批处理中只是多次GET操作,所以如果您为每个请求执行20-60 GET并且每秒执行2k个请求,那么Redis每秒处理大约30-120k操作。

要么达到云虚拟机CPU或网络饱和的最大吞吐量。

尝试使用随机密钥进行一些负载测试以首先查找最大容量,以便知道是否足以满足您的应用程序,然后您可以对其进行建模。

您可以使用散列将类似数据组合成单个键或使用更多服务器(或更多CPU上的实例)进行分片。 Redis集群执行自动分片。

+0

我相信这不是问题。 1.在上面的原始问题中,我提到Redis服务器似乎几乎没有出汗。事实上,如果我从不同的机器连接,一切仍然很快。 2.您可以看到有一个未处理的本地队列。这与服务器无关。 3。我写了我自己的图书馆,因为这似乎没有得到解决,也没有受到这个问题的困扰。 – Cleverguy25