[REDIS] StackExchange.Redis와 병렬 실행?
REDISStackExchange.Redis와 병렬 실행?
나는 레디 스에 삽입하기 위해 직렬화하고있어 목록 <사람>에서 1M 항목 가게가 있습니다. (280)
각각 자신의 섹션을합니다 (10) 작업 <> 사이에 I의 분할 작업 (목록 <> 읽기 전용에 대한 스레드 안전 (그것은 목록에서 여러 읽기 작업을 수행하는 것이 안전합니다)
단순화 :
예:
항목 = 100, THREADS = 10의 경우, 각 작업은 관련 범위 자신의 페이지와 거래를 캡처합니다.
예를 들면 :
void Main()
{
var ITEMS=100;
var THREADS=10;
var PAGE=4;
List<int> lst = Enumerable.Range(0,ITEMS).ToList();
for (int i=0;i< ITEMS/THREADS ;i++)
{
lst[PAGE*(ITEMS/THREADS)+i].Dump();
}
}
다 괜찮아.
이제 다시 SE.redis합니다.
나는이 패턴을 구현하고 싶었다 그래서 내가 그랬어 : (항목 = 1,000,000로)
내 테스트 :
(여기서 각 제 dbsize를 검사)
당신이 볼 수 있듯이, 1M 기록은 10 개 스레드를 통해 추가되었습니다.
내가 10M에 1M에서 항목을 변경할 때 지금, 나는 그것이 빠른 있는지 모르겠지만 - 일이 정말 느려질 내가 예외를 얻을 :
예외는 대 루프에있다.
질문:
관련 정보 :
또한, (그렇지 않으면 난에서 OutOfMemoryException을 받고 있어요)의 App.config에 존재하는
해결법
-
==============================
1.현재 코드는 동기 API (StringSet)를 사용하고, 동시에 10 개 스레드에 의해로드되고있다. 이 SE.Redis에 뚜렷한 도전을 제시하지 않습니다 - 그것은 잘 여기에 작동합니다. 나는 그것이 진정으로 서버가 더 이상 당신이 가장 가능성 또한 서버의 할당에 관련된 데이터의 일부를 처리하려면보다 촬영하고있다 제한 시간이라고 생각한다. 하나의 옵션은, 다음, 단순히 시간 제한을 약간 증가시키는 것이다. 아니 많이 ... 오초 대신 기본 1 초보십시오. 가능성, 작업의 대부분은 어쨌든 매우 빠르게 노력하고 있습니다.
현재 코드는 동기 API (StringSet)를 사용하고, 동시에 10 개 스레드에 의해로드되고있다. 이 SE.Redis에 뚜렷한 도전을 제시하지 않습니다 - 그것은 잘 여기에 작동합니다. 나는 그것이 진정으로 서버가 더 이상 당신이 가장 가능성 또한 서버의 할당에 관련된 데이터의 일부를 처리하려면보다 촬영하고있다 제한 시간이라고 생각한다. 하나의 옵션은, 다음, 단순히 시간 제한을 약간 증가시키는 것이다. 아니 많이 ... 오초 대신 기본 1 초보십시오. 가능성, 작업의 대부분은 어쨌든 매우 빠르게 노력하고 있습니다.
그것을 속도에 관해서 - 즉 데이터를 파이프 라이닝 계속 여기에 하나의 옵션은 기다릴 것입니다. 콘텐츠 인 경우 오류 상태에 대한 모든 단일 메시지를 확인하지,이 작업을 수행 한 후 간단한 방법은, 플래그를 추가하는 것입니다 CommandFlags.FireAndForget은 StringSet 호출의 끝. 내 로컬 테스트에서,이 25 %로 1M 예를 질주 (그리고 나는 시간의 나머지의 많은 실제로 문자열 직렬화에 소요되는 의심).
이것이 레디 스 서버 및 (사용자의 설정을 모방하는) 같은 컴퓨터에있는 응용 프로그램, 모두 엄청난 양의 메모리를 필요 특히 이후 - 나는 10M 예제와 함께 한 가장 큰 문제는 10M 예 작업 단순히 오버 헤드이었다 . GC는 관리 코드 등이 일시에, 메모리 경쟁 압력을 생성한다. 그러나 아마 더 중요한 : 단순히 영원히 소요 아무것도 시작합니다. 따라서, 차라리 단일 목록보다 병렬 수율 복귀 생성기를 사용하는 코드를 리팩토링. 예를 들면 :
static IEnumerable<Person> InventPeople(int seed, int count) { for(int i = 0; i < count; i++) { int f = 1 + seed + i; var item = new Person { Id = f, Name = Path.GetRandomFileName().Replace(".", "").Substring(0, appRandom.Value.Next(3, 6)) + " " + Path.GetRandomFileName().Replace(".", "").Substring(0, new Random(Guid.NewGuid().GetHashCode()).Next(3, 6)), Age = f % 90, Friends = ParallelEnumerable.Range(0, 100).Select(n => appRandom.Value.Next(1, f)).ToArray() }; yield return item; } } static IEnumerable<T> Batchify<T>(this IEnumerable<T> source, int count) { var list = new List<T>(count); foreach(var item in source) { list.Add(item); if(list.Count == count) { foreach (var x in list) yield return x; list.Clear(); } } foreach (var item in list) yield return item; }
와:
foreach (var element in InventPeople(PER_THREAD * counter1, PER_THREAD).Batchify(1000))
데이터는 1000 일괄 발명되고 각 배치는 매우 빠르게 사용할 수 있습니다 - 여기, Batchify의 목적은 우리가 각 작업 사이에 상당한 시간을 고려하여 너무 많은 서버를 도움이되지 않습니다 있도록하는 것입니다.
내가 JIL로 전환 그래서 또한, JSON 성능에 대해 우려했다 :
public static string ToJSON<T>(this T obj) { return Jil.JSON.Serialize<T>(obj); }
그리고 그냥 재미, 나는 배치 (그래서 실제 처리 루프 있음에 JSON 작업을 이동 :
foreach (var element in InventPeople(PER_THREAD * counter1, PER_THREAD) .Select(x => new { x.Id, Json = x.ToJSON() }).Batchify(1000))
나는 3 분 57초, 42194 ROPS의 속도에 10M를로드 할 수 있도록이, 조금 더 아래로 시간을 얻었다. 이 시간의 대부분은 실제로 응용 프로그램 내부 지역의 처리이다. 나는 그래서 그것을 변경하는 경우 각 스레드로드 같은 항목 항목 / 스레드 시간 후 일분 48초이 변경 - 92,592 ROPS의 속도.
난 정말 아무것도 대답했는지 확실하지 않습니다,하지만 짧은 버전은 "간단하게 할 수 더 긴 시간 초과를 시도 할 수 있습니다, 파이어 앤 포겟)를 사용하는 것이 좋습니다.
from https://stackoverflow.com/questions/23605060/parallel-execution-with-stackexchange-redis by cc-by-sa and MIT license
'REDIS' 카테고리의 다른 글
[REDIS] 레디 스 소트 세트의 부분 키 이름을 사용하여 값을 찾기 (0) | 2020.01.15 |
---|---|
[REDIS] 푸른 레디 스 캐시의 최대 연결에 도달 (0) | 2020.01.15 |
[REDIS] 어떻게 ServiceStack PooledRedisClientManager 장애 조치 작동합니까? (0) | 2020.01.15 |
[REDIS] 실패와 자동화 된 페일 오버의 레디 스 / Jedis없이 단일 지점 (0) | 2020.01.15 |
[REDIS] Node.js를 - 세션) (res.redirect을 통해 지속되지 않습니다 (0) | 2020.01.15 |