복붙노트

[REDIS] StackExchange.Redis와 병렬 실행?

REDIS

StackExchange.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에 존재하는 - 빌드를 x64bit, 나는) 16기가바이트, SSD 드라이브, i7의 CPU가 있습니다.

해결법

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

    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의 속도.

    난 정말 아무것도 대답했는지 확실하지 않습니다,하지만 짧은 버전은 "간단하게 할 수 더 긴 시간 초과를 시도 할 수 있습니다, 파이어 앤 포겟)를 사용하는 것이 좋습니다.

  2. from https://stackoverflow.com/questions/23605060/parallel-execution-with-stackexchange-redis by cc-by-sa and MIT license