your programing

스택 익스체인지Azure Redis를 사용한 Redis가 비정상적으로 느리거나 타임아웃 오류를 발생시킨다.

lovepro 2023. 4. 22. 22:30
반응형

스택 익스체인지Azure Redis를 사용한 Redis가 비정상적으로 느리거나 타임아웃 오류를 발생시킨다.

기존 Azure In-Role 캐시 사용을 모두 Redis로 옮기고 Stack Exchange와 함께 Azure Redis 미리보기를 사용하기로 결정했습니다.Redis 라이브러리(https://github.com/StackExchange/StackExchange.Redis))별 문제 없이 코드를 모두 작성했지만 실행 시 매우 느리고 타임아웃 오류가 계속 발생합니다(타임아웃 기간은 15초로 설정되어 있습니다).

다음은 Redis 연결을 설정하고 간단한 작업에 사용하는 방법에 대한 관련 코드입니다.

    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초가 걸립니다.실제로 데이터베이스에서 실제 데이터를 가져오는 것보다 속도가 느리면 캐시로 사용하는 전체 목적을 부정하는 것 같습니다.

제가 분명히 잘못된 일을 하고 있나요?

편집: 이 서버(Redis Desktop Manager 사용)에서 얻은 몇 가지 통계정보가 있습니다.

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:

편집 2: Get/Set에서 사용하는 확장 메서드는 다음과 같습니다.개체를 JSON으로 변환하여 호출하는 매우 간단한 메서드입니다.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: 다음은 오류 메시지의 몇 가지 예입니다.

    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 Cache 매뉴얼에서 권장하는 패턴입니다.

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를 사용합니다.스레드 세이프 초기화 처리
  • "abortConnect=false"를 설정합니다.즉, 초기 연결 시도가 실패하면 ConnectionMultiplexer가 예외를 발생시키지 않고 백그라운드에서 자동으로 재시도합니다.
  • 연결이 끊어지면 ConnectionMultiplexer가 백그라운드에서 자동으로 재시도하므로 IsConnected 속성은 확인하지 않습니다.

저도 비슷한 문제가 있었어요.Redis 캐시는 비정상적으로 느리지만 확실히 캐시를 하고 있었습니다.페이지를 로드하는 데 20~40초가 걸린 경우도 있습니다.

캐시 서버가 사이트와 다른 위치에 있다는 것을 알았습니다.웹 사이트와 같은 장소에 상주하도록 캐시 서버를 업데이트하여 모든 것이 예상대로 작동합니다.

같은 페이지가 4~6초 후에 로딩됩니다.

이런 문제를 겪고 있는 다른 사람에게 행운을 빌어요.

문제는 connection 객체의 작성 및 사용방법입니다.처음에는 정확한 문제에 직면했고 모든 웹 요청에서 단일 연결 개체를 사용하여 수정되었습니다.세션 시작 시 오브젝트를 정상적으로 다시 작성하기 위해 늘인지 연결되었는지 확인합니다.문제가 해결되었습니다.

주의: 또한 Redis Cache 인스턴스가 실행 중인 Azure 영역과 웹 서버가 존재하는 영역도 확인하십시오.둘 다 같은 존으로 유지하는 것이 좋습니다.

Global.ascx.cs 파일

public static ConnectionMultiplexer RedisConnection;
public static IDatabase RedisCacheDb;

protected void Session_Start(object sender, EventArgs e)
    {
        if (ConfigurationManager.ConnectionStrings["RedisCache"] != null)
        {
            if (RedisConnection == null || !RedisConnection.IsConnected)
            {
                RedisConnection = ConnectionMultiplexer.Connect(ConfigurationManager.ConnectionStrings["RedisCache"].ConnectionString);
            }
            RedisCacheDb = RedisConnection.GetDatabase();
        }
    }

내 경우엔 효과가 있었어Sync Timeout을 늘리는 것을 잊지 마십시오.기본값은 1초입니다.

private static Lazy<ConnectionMultiplexer> ConnectionMultiplexerItem = new Lazy<ConnectionMultiplexer>(() =>
{
    var redisConfig = ConfigurationOptions.Parse("mycache.redis.cache.windows.net,abortConnect=false,ssl=true,password=...");

    redisConfig.SyncTimeout = 3000;

    return ConnectionMultiplexer.Connect(redisConfig);
});

Azure Redis 캐시와 클라이언트가 Azure의 같은 지역에 있는지 확인합니다.예를 들어 캐시가 미국 동부에 있지만 클라이언트가 미국 서부에 있을 때 요청이 동기화 시간 내에 완료되지 않거나 로컬 개발 기계에서 디버깅할 때 시간 초과가 발생할 수 있습니다.캐시와 클라이언트는 같은 Azure 지역에 두는 것이 좋습니다.지역간 콜을 실행하는 시나리오가 있는 경우 synctimeout을 더 높은 값으로 설정할 수 있습니다.

상세내용 : https://azure.microsoft.com/en-us/blog/investigating-timeout-exceptions-in-stackexchange-redis-for-azure-redis-cache/

이 경우 SSL 연결을 사용할 때 문제가 발생합니다.데스크톱 관리자가 SSL이 아닌 포트에서 실행 중이지만 코드가 SSL을 사용하고 있음을 나타냅니다.

하지 않는 는 Azure redis를 하여 약 .LRANGE.net "StackExchange " " " 입니다.redis)의 instand.SSL 27일

  • WebApp: 표준 S2

  • Redis: 표준1 GB

:: " "SLOWLOGRedis 자체는 행을 취득하는 데 14밀리초 정도의 시간이 걸리기 때문에 실제로는 slowlog에 도달하고 있는 것처럼 보이지만 SSL을 유효하게 하고 있는 경우의 실제 전송과는 거리가 있습니다.우리는 Redis와 Web Apps 사이에 일종의 보안을 확보하기 위해 프리미엄 Redis를 갖게 되었습니다.

언급URL : https://stackoverflow.com/questions/25416562/stackexchange-redis-with-azure-redis-is-unusably-slow-or-throws-timeout-errors

반응형