복붙노트

[REDIS] 레디 스 사전에서 일괄 세트는 데이터

REDIS

레디 스 사전에서 일괄 세트는 데이터

나는 아래로 배치를 사용하여 키 값 쌍의 사전을 삽입 StackExchange 레디 스 DB를 사용하고 있습니다 :

private static StackExchange.Redis.IDatabase _database;
public void SetAll<T>(Dictionary<string, T> data, int cacheTime)
{
    lock (_database)
    {
        TimeSpan expiration = new TimeSpan(0, cacheTime, 0);
        var list = new List<Task<bool>>();
        var batch = _database.CreateBatch();               
        foreach (var item in data)
        {
            string serializedObject = JsonConvert.SerializeObject(item.Value, Formatting.Indented,
        new JsonSerializerSettings { ContractResolver = new SerializeAllContractResolver(), ReferenceLoopHandling = ReferenceLoopHandling.Ignore });

            var task = batch.StringSetAsync(item.Key, serializedObject, expiration);
            list.Add(task);
            serializedObject = null;
        }
        batch.Execute();

        Task.WhenAll(list.ToArray());
    }
}

내 문제는 : 그것은 사전의 단지 350 항목을 설정하기 위해 약 7 초 정도 걸립니다.

내 질문 :이 레디 스에 세트 대량 항목에 올바른 방법인가, 아니면이 작업을 수행하는 빠른 방법이있다? 어떤 도움에 감사드립니다. 감사.

해결법

  1. ==============================

    1."그냥"매우 상대적인 용어입니다, 정말 특히, 더 문맥없이 이해가되지 않습니다 :이 페이로드가 얼마나 큰입니까?

    "그냥"매우 상대적인 용어입니다, 정말 특히, 더 문맥없이 이해가되지 않습니다 :이 페이로드가 얼마나 큰입니까?

    그러나, 당신이 조사 할 수 있도록 몇 가지 점을 명확히 :

    그래서; 내가 할 것이 우선 몇 가지 코드를 제거하는 것입니다 :

    private static StackExchange.Redis.IDatabase _database;
    static JsonSerializerSettings _redisJsonSettings = new JsonSerializerSettings {
        ContractResolver = new SerializeAllContractResolver(),
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
    
    public void SetAll<T>(Dictionary<string, T> data, int cacheTime)
    {
        TimeSpan expiration = new TimeSpan(0, cacheTime, 0);
        var list = new List<Task<bool>>();
        foreach (var item in data)
        {
            string serializedObject = JsonConvert.SerializeObject(
                item.Value, Formatting.Indented, _redisJsonSettings);
    
            list.Add(_database.StringSetAsync(item.Key, serializedObject, expiration));
        }
        Task.WhenAll(list.ToArray());
    }
    

    내가 할 것이 두 번째 것은 레디 스 작업에 직렬화 별도로 시간이 될 것입니다.

    내가 할 것이 세 번째 것은 내가 대신 MemoryStream을에 직렬화 할 수 있다면 이상적 일 내가 할 수있는 재사용을 볼 수있을 것입니다 - 문자열 할당 및 UTF-8 인코딩을 피하기 위해 :

    using(var ms = new MemoryStream())
    {
        foreach (var item in data)
        {
            ms.Position = 0;
            ms.SetLength(0); // erase existing data
            JsonConvert.SerializeObject(ms,
                item.Value, Formatting.Indented, _redisJsonSettings);
    
            list.Add(_database.StringSetAsync(item.Key, ms.ToArray(), expiration));
        }
    }
    
  2. ==============================

    2.이 두 번째 대답은 좀 접선하지만, 주요 비용은 직렬화 인 것처럼 소리 토론을 기반으로합니다 :

    이 두 번째 대답은 좀 접선하지만, 주요 비용은 직렬화 인 것처럼 소리 토론을 기반으로합니다 :

    당신이 할 수있는 한 가지 저장 JSON 없습니다. JSON은 비교적 큰이며, 존재의 텍스트 기반의 직렬화 및 역 직렬화 모두를 처리 할 상대적으로 비싸다. 당신이 rejson를 사용하지 않는 한이 실제 값이 무엇인지 상관하지 않는다, 그래서 레디 스 다만, 불투명 한 덩어리로 데이터를 처리합니다. 따라서, 당신은보다 효율적인 형식을 사용할 수 있습니다.

    나는 상당히 편향 해요,하지만 우리는 우리의 레디 스 스토리지에 protobuf - 그물을 사용한다. protobuf - 그물에 최적화되어 있습니다 :

    나는 의미 protobuf - 그물보다는 때문에 마지막 글 머리의 구글의 자신의 C #을 protobuf 라이브러리를 제안 : 당신이 이미 가지고있는 데이터로 사용할 수 있습니다.

    이유를 설명하기 위해, 나는 https://aloiskraus.wordpress.com/2017/04/23/the-definitive-serialization-performance-guide/에서이 이미지를 사용합니다 :

    protobuf 그물의 출력의 크기가 Json.NET (대역폭 비용을 감소) 절반이고, 직렬화 타임 (로컬 CPU 비용 감소) 미만의 1/5에 해당 통지.

    당신은 (Protobuf 표준 POCO를 Google에 C #으로 기존의 POCO 클래스를 변환하는 방법에 따라) 도움말 protobuf - 그물 밖으로에 모델에 몇 가지 속성을 추가해야합니다,하지만 이것은 단지가 될 것입니다 :

    using(var ms = new MemoryStream())
    {
        foreach (var item in data)
        {
            ms.Position = 0;
            ms.SetLength(0); // erase existing data
            ProtoBuf.Serializer.Serialize(ms, item.Value);
    
            list.Add(_database.StringSetAsync(item.Key, ms.ToArray(), expiration));
        }
    }
    

    당신이 볼 수 있듯이, 당신의 레디 스 코드로 코드 변경을 최소화합니다. 분명히 당신은 데이터 등을 읽을 때 직렬화 를 사용해야합니다.

    데이터가 텍스트를 기반으로하는 경우, 당신은 또한 GZipStream 또는 DeflateStream를 통해 직렬화를 실행하는 것이 좋습니다; 데이터가 텍스트에 의해 지배되는 경우, 그것은 아주 잘 압축됩니다.

  3. from https://stackoverflow.com/questions/44585100/batch-set-data-from-dictionary-into-redis by cc-by-sa and MIT license