带有 Azure Redis 的 StackExchange.Redis 速度慢得无法使用或引发超时错误 [英] StackExchange.Redis with Azure Redis is unusably slow or throws timeout errors

查看:18
本文介绍了带有 Azure Redis 的 StackExchange.Redis 速度慢得无法使用或引发超时错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将所有现有的 Azure 角色内缓存使用转移到 Redis 并决定使用 Azure Redis 预览版和 StackExchange.Redis 库 (https://github.com/StackExchange/StackExchange.Redis).我为它编写了所有代码,没有太大问题,但运行时它绝对慢得无法使用,并且不断抛出超时错误(我的超时时间设置为 15 秒).

I'm moving all of my existing Azure In-Role cache use to Redis and decided to use the Azure Redis preview along with the StackExchange.Redis library (https://github.com/StackExchange/StackExchange.Redis). I wrote all the code for it without much problem, but when running it is absolutely unusably slow and constantly throws timeout errors (my timeout period is set to 15 seconds).

这是我如何设置Redis连接并将其用于简单操作的相关代码:

Here is the relevant code for how I am setting up the Redis connection and using it for simple operations:

    private static ConnectionMultiplexer _cacheService;
    private static IDatabase _database;
    private static object _lock = new object();

    private void Initialize()
    {
        if (_cacheService == null)
        {
            lock (_lock)
            {
                if (_cacheService == null)
                {
                    var options = new ConfigurationOptions();
                    options.EndPoints.Add("{my url}", 6380);
                    options.Ssl = true;
                    options.Password = "my password";
                    // needed for FLUSHDB command
                    options.AllowAdmin = true;

                    // necessary?
                    options.KeepAlive = 30;
                    options.ConnectTimeout = 15000;
                    options.SyncTimeout = 15000;

                    int database = 0;

                    _cacheService = ConnectionMultiplexer.Connect(options);
                    _database = _cacheService.GetDatabase(database);
                }
            }
        }

    }

    public void Set(string key, object data, TimeSpan? expiry = null)
    {
        if (_database != null)
        {
            _database.Set(key, data, expiry: expiry);
        }
    }

    public object Get(string key)
    {
        if (_database != null)
        {
            return _database.Get(key);
        }
        return null;
    }

执行 Get 和 Set 等非常简单的命令通常会超时或需要 5-10 秒才能完成.如果它比从我的数据库中实际获取真实数据慢得多,那么它似乎否定了将其用作缓存的全部目的:)

Performing very simple commands like Get and Set often time out or take 5-10 seconds to complete. Seems like it kind of negates the whole purpose of using it as a cache if it's WAY slower than actually fetching the real data from my database :)

我是否明显做错了什么?

Am I doing anything obviously incorrect?

编辑:以下是我从服务器(使用 Redis 桌面管理器)提取的一些统计数据,以防万一.

Edit: here are some stats that I pulled from the server (using Redis Desktop Manager) in case that sheds some light on anything.

Server
redis_version:2.8.12
redis_mode:standalone
os:Windows  
arch_bits:64
multiplexing_api:winsock_IOCP
gcc_version:0.0.0
process_id:2876

tcp_port:6379
uptime_in_seconds:109909
uptime_in_days:1
hz:10
lru_clock:16072421
config_file:C:Resourcesdirectoryxxxx.Kernel.localStore1
edis_2092_port6379.conf

Clients
connected_clients:5
client_longest_output_list:0
client_biggest_input_buf:0
client_total_writes_outstanding:0
client_total_sent_bytes_outstanding:0
blocked_clients:0

Memory
used_memory:4256488
used_memory_human:4.06M
used_memory_rss:67108864
used_memory_rss_human:64.00M
used_memory_peak:5469760
used_memory_peak_human:5.22M
used_memory_lua:33792
mem_fragmentation_ratio:15.77
mem_allocator:dlmalloc-2.8

Persistence
loading:0
rdb_changes_since_last_save:72465
rdb_bgsave_in_progress:0
rdb_last_save_time:1408471440
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:-1
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok

Stats
total_connections_received:25266
total_commands_processed:123389
instantaneous_ops_per_sec:10
bytes_received_per_sec:275
bytes_sent_per_sec:65
bytes_received_per_sec_human:

编辑 2:以下是我用于 Get/Set 的扩展方法——它们是非常简单的方法,只需将对象转换为 JSON 并调用 StringSet.

Edit 2: Here are the extension methods I'm using for Get/Set -- they are very simple methods that just turn an object into JSON and call StringSet.

    public static object Get(this IDatabase cache, string key)
    {
        return DeserializeJson<object>(cache.StringGet(key));
    }

    public static void Set(this IDatabase cache, string key, object value, TimeSpan? expiry = null)
    {
        cache.StringSet(key, SerializeJson(value), expiry: expiry);
    }

编辑 3:以下是一些错误消息示例:

Edit 3: here are a couple example error messages:

    A first chance exception of type 'System.TimeoutException' occurred in StackExchange.Redis.dll
    Timeout performing GET MyCachedList, inst: 11, queue: 1, qu=1, qs=0, qc=0, wr=0/1, in=0/0

    A first chance exception of type 'System.TimeoutException' occurred in StackExchange.Redis.dll
    Timeout performing GET MyCachedList, inst: 1, queue: 97, qu=0, qs=97, qc=0, wr=0/0, in=3568/0

推荐答案

这里是推荐的模式,来自 Azure Redis 缓存文档:

Here is the recommended pattern, from the Azure Redis Cache documentation:

private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => {
    return ConnectionMultiplexer.Connect("mycache.redis.cache.windows.net,abortConnect=false,ssl=true,password=...");
});

public static ConnectionMultiplexer Connection {
    get {
        return lazyConnection.Value;
    }
}

几个要点:

  • 它使用 Lazy<T>处理线程安全的初始化
  • 它设置了abortConnect=false",这意味着如果初始连接尝试失败,ConnectionMultiplexer 将在后台静默重试而不是抛出异常.
  • 检查 IsConnected 属性,因为如果连接断开,ConnectionMultiplexer 将在后台自动重试.
  • It uses Lazy<T> to handle thread-safe initialization
  • It sets "abortConnect=false", which means if the initial connect attempt fails, the ConnectionMultiplexer will silently retry in the background rather than throw an exception.
  • It does not check the IsConnected property, since ConnectionMultiplexer will automatically retry in the background if the connection is dropped.

这篇关于带有 Azure Redis 的 StackExchange.Redis 速度慢得无法使用或引发超时错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆