StackExchange.Redis与Azure的Redis是unusably缓慢或引发超时错误 [英] StackExchange.Redis with Azure Redis is unusably slow or throws timeout errors

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

问题描述

我将所有我现有的Azure角色内缓存来使用Redis的,并决定使用Azure的Redis的preVIEW与StackExchange.Redis库一起(<一个href=\"https://github.com/StackExchange/StackExchange.Redis\">https://github.com/StackExchange/StackExchange.Redis).我写的所有code它没有太大的问题,但在运行时,它是绝对unusably缓慢,不断抛出超时错误(我的超时时间设置为15秒)。

下面是相关code代表我如何建立Redis的连接,并使用它的简单操作:

 私有静态ConnectionMultiplexer _cacheService;
    私有静态_database了IDatabase;
    私人静态对象_lock =新的对象();    私人无效初始化()
    {
        如果(_cacheService == NULL)
        {
            锁(_lock)
            {
                如果(_cacheService == NULL)
                {
                    VAR的选择=新ConfigurationOptions();
                    options.EndPoints.Add({我的URL},6380);
                    options.Ssl = TRUE;
                    options.Password =我的密码;
                    //需要FLUSHDB命令
                    options.AllowAdmin = TRUE;                    //必要吗?
                    options.KeepAlive = 30;
                    options.ConnectTimeout = 15000;
                    options.SyncTimeout = 15000;                    INT数据库= 0;                    _cacheService = ConnectionMultiplexer.Connect(选件);
                    _database = _cacheService.GetDatabase(数据库);
                }
            }
        }    }    公共无效集(字符串键,对象数据,时间跨度?到期= NULL)
    {
        如果(_database!= NULL)
        {
            _database.Set(键,数据,有效期:有效期);
        }
    }    公共对象获取(字符串键)
    {
        如果(_database!= NULL)
        {
            返回_database.Get(键);
        }
        返回null;
    }

表演非常喜欢简单的命令获取和设置经常超时或需要5-10秒即可完成。好像它那种否定,如果它的方式比实际从我的数据库中获取真实的数据慢用它作为缓存的全部目的:)

我是做任何事情显然是不正确?

修改:这里有一些统计数据,我是从(使用Redis的桌面管理器)的情况下揭示了一些东西光服务器拉

 服务器
redis_version:2.8.12
redis_mode:独立
操作系统:Windows
arch_bits:64
multiplexing_api:winsock_IOCP
gcc_version:0.0.0
PROCESS_ID:2876TCP_PORT:6379
uptime_in_seconds:109909
uptime_in_days:1
赫兹:10
lru_clock:16072421
CONFIG_FILE:C:\\资源\\目录\\ xxxx.Kernel.localStore \\ 1 \\ redis_2092_port6​​379.conf客户端
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记忆
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坚持
加载:0
rdb_changes_since_last_save:72465
rdb_bgsave_in_progress:0
rdb_last_save_time:1408471440
rdb_last_bgsave_status:确定
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:确定
aof_last_write_status:确定统计
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

 公共静态对象获取(此缓存了IDatabase,串键)
    {
        返回DeserializeJson&LT;对象&gt;(cache.StringGet(键));
    }    公共静态无效集(此缓存了IDatabase,串键,对象的值,时间跨度?到期= NULL)
    {
        cache.StringSet(键,SerializeJson(值),有效期:有效期);
    }

修改3 :这里有几个典型的错误信息:

 键入'System.TimeoutException的第一次机会异常出现在StackExchange.Redis.dll
    超时执行GET MyCachedList,研究所:11,队列:1,曲= 1,QS = 0,QC = 0,WR = 0/1,在= 0/0    类型的第一次机会异常'System.TimeoutException发生在StackExchange.Redis.dll
    超时执行GET MyCachedList,研究所:1,队列:97,曲= 0,QS = 97,QC = 0,WR = 0/0,在3568 = / 0


解决方案

下面是天蓝色的Redis缓存小组建议的模式:

 私有静态懒&LT; ConnectionMultiplexer&GT; lazyConnection =新懒人&LT; ConnectionMultiplexer&GT;(()=&GT; {
    返回ConnectionMultiplexer.Connect(\"mycache.redis.cache.windows.net,abortConnect=false,ssl=true,password=...\");
});公共静态ConnectionMultiplexer连接{
    获得{
        返回lazyConnection.Value;
    }
}

几个要点:


  • 它采用懒&LT; T&GT;处理线程安全的初始化

  • 它集abortConnect =假,这意味着如果初始连接尝试失败,将ConnectionMultiplexer默默地在后台重试,而不是抛出异常。

  • 它做的不可以检查IsConnected属性,因为如果连接中断ConnectionMultiplexer会在后台自动重试。

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).

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;
    }

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?

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:\Resources\directory\xxxx.Kernel.localStore\1\redis_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:

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);
    }

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

解决方案

Here is the pattern recommended by the Azure Redis Cache team:

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;
    }
}

A few important points:

  • 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.

这篇关于StackExchange.Redis与Azure的Redis是unusably缓慢或引发超时错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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