[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."그냥"매우 상대적인 용어입니다, 정말 특히, 더 문맥없이 이해가되지 않습니다 :이 페이로드가 얼마나 큰입니까?
"그냥"매우 상대적인 용어입니다, 정말 특히, 더 문맥없이 이해가되지 않습니다 :이 페이로드가 얼마나 큰입니까?
그러나, 당신이 조사 할 수 있도록 몇 가지 점을 명확히 :
그래서; 내가 할 것이 우선 몇 가지 코드를 제거하는 것입니다 :
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.이 두 번째 대답은 좀 접선하지만, 주요 비용은 직렬화 인 것처럼 소리 토론을 기반으로합니다 :
이 두 번째 대답은 좀 접선하지만, 주요 비용은 직렬화 인 것처럼 소리 토론을 기반으로합니다 :
당신이 할 수있는 한 가지 저장 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를 통해 직렬화를 실행하는 것이 좋습니다; 데이터가 텍스트에 의해 지배되는 경우, 그것은 아주 잘 압축됩니다.
from https://stackoverflow.com/questions/44585100/batch-set-data-from-dictionary-into-redis by cc-by-sa and MIT license
'REDIS' 카테고리의 다른 글
[REDIS] 파이썬 3.5 json.loads 및 레디 스 (0) | 2020.01.21 |
---|---|
[REDIS] resque 장애 조치 레디 스를위한 솔루션 (0) | 2020.01.21 |
[REDIS] Socket.io, 레디 스 저장 및 IE (0) | 2020.01.21 |
[REDIS] 레디 스 2.6.11에서 구독 취소 명령을 사용하는 방법 (0) | 2020.01.21 |
[REDIS] 동시에 여러 프로그램 레디 스 동작은 읽기 / 일을 같은 해시 키 델 (0) | 2020.01.21 |