打开与Redis的连接有时需要很长时间。看起来它取决于连接线程的数量,也许还有PC配置。我在两个带有4核CPU的工作站上运行50个线程的测试,打开连接需要70-100ms,在8核工作站和8核登台服务器上需要1000-1500ms,有时甚至更多。奇怪的依赖,但它'可再现。 当IIS应用程序池重新启动,并且所有线程都尝试重新连接时,会导致缓存停机等。我需要改变什么来获得合理的连接时间?
我使用BookSleeve客户端,这里是代码示例:
static void Main(string[] args)
{
for (var i = 0; i < threadCount; i++)
threads.Add(new Thread(RunThread));
foreach (var thread in threads)
thread.Start();
foreach (var thread in threads)
thread.Join();
}
static void RunThread()
{
var connection = TryGetConnection();
while (connection == null)
{
connection = TryGetConnection();
}
}
static RedisConnection TryGetConnection()
{
var connection = currentConnection;
if ((connection != null) && (connection.State == RedisConnectionBase.ConnectionState.Open))
return connection;
lock (syncRoot)
{
if ((currentConnection != null) && (currentConnection.State == RedisConnectionBase.ConnectionState.Open))
return currentConnection;
if ((connectionTask != null) && connectionTask.IsCompleted)
connectionTask = null;
if (connectionTask == null)
{
if ((currentConnection != null) && (currentConnection.State == RedisConnectionBase.ConnectionState.Closed))
{
currentConnection.Dispose();
currentConnection = null;
}
if (currentConnection == null)
{
currentConnection = new RedisConnection(
serverAddress,
serverPort,
ioTimeout: (int) operationTimeout.TotalMilliseconds,
syncTimeout: (int) operationTimeout.TotalMilliseconds);
}
if (currentConnection.State == RedisConnectionBase.ConnectionState.New)
currentConnection.Open();
}
}
return null;
}
答案 0 :(得分:2)
让我们看看;我们在这里有一个循环:
var connection = TryGetConnection();
while (connection == null)
{
connection = TryGetConnection();
}
在你获得连接之前,你要做一个紧密的循环,你也可以大大简化。您可以做的第一件事就是等待执行任务(显然是超时),而不是使用热循环。泛化:
TryGetConnection
上面的var task = connection.Open();
connection.Wait(task);
使用了连接的指定超时,并为您简化了例外工作。
但是,在这个特定的情况下,你可能只使用类似的东西:
Wait
使用:
var connection = TryGetConnection();
// no loop here
其中static RedisConnection TryGetConnection()
{
var connection = currentConnection;
if ((connection != null) && (connection.State == RedisConnectionBase.ConnectionState.Open))
return connection;
lock (syncRoot)
{ // double-checked
if ((connection != null) && (connection.State == RedisConnectionBase.ConnectionState.Open))
return connection;
connection = ConnectionUtils.Connect(config);
return connection;
}
}
是值的组合;基本上是这样的:
config
此配置字符串也可能更复杂,包括多个redis服务器(主/从等),服务名称(用于sentinel),客户端名称(用于myserver:6389,syncTimeout=1000
)等
我怀疑你方法中的一些复杂性导致了一些额外的循环。看看它是否更加可靠。