Redis
 sql >> Baza danych >  >> NoSQL >> Redis

Wykonywanie równoległe za pomocą StackExchange.Redis?

Obecnie Twój kod korzysta z synchronicznego API (StringSet ) i jest ładowany przez 10 wątków jednocześnie. Nie będzie to stanowić dużego wyzwania dla SE.Redis - tutaj działa dobrze. podejrzewam że rzeczywiście jest to limit czasu, w którym serwer zabrał więcej czasu, niż chciałbyś przetworzyć niektóre dane, najprawdopodobniej również związane z alokatorem serwera. Jedną z opcji jest zatem po prostu nieznaczne zwiększenie limitu czasu . Niewiele... spróbuj 5 sekund zamiast domyślnej 1 sekundy. Prawdopodobnie większość operacji i tak działa bardzo szybko.

Jeśli chodzi o przyspieszenie:jedną z opcji jest nie czekać - tj. zachować dane dotyczące potoku. Jeśli nie chcesz sprawdzać każdej wiadomości pod kątem stanu błędu, jednym prostym sposobem, aby to zrobić, jest dodanie , flags: CommandFlags.FireAndForget na końcu twojego StringSet połączenie. W moich lokalnych testach przyspieszyło to przykład 1M o 25% (i podejrzewam, że większość czasu spędza się na serializacji ciągów).

Największym problemem, jaki miałem z przykładem 10M, był po prostu narzut związany z pracą z przykładem 10M - zwłaszcza, że ​​zajmuje to ogromne ilości pamięci zarówno dla redis-server oraz aplikacja, która (aby emulować twoją konfigurację) znajduje się na tym samym komputerze. Tworzy to konkurencyjne ciśnienie pamięci, z przerwami GC itp. w kodzie zarządzanym. Ale co może ważniejsze:po prostu potrzeba wieczności, aby zacząć cokolwiek robić . W związku z tym zrefaktorowałem kod, aby używał równoległego yield return generatory zamiast pojedynczej listy. Na przykład:

    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;
    }

z:

foreach (var element in InventPeople(PER_THREAD * counter1, PER_THREAD).Batchify(1000))

Tutaj cel Batchify jest zapewnienie, że nie pomagamy zbytnio serwerowi, poświęcając znaczną ilość czasu między każdą operacją - dane są tworzone w partiach po 1000, a każda partia jest udostępniana bardzo szybko.

Martwiłem się również o wydajność JSON, więc przerzuciłem się na JIL:

    public static string ToJSON<T>(this T obj)
    {
        return Jil.JSON.Serialize<T>(obj);
    }

a potem dla zabawy przeniosłem pracę JSON do przetwarzania wsadowego (tak, aby rzeczywiste pętle przetwarzania:

 foreach (var element in InventPeople(PER_THREAD * counter1, PER_THREAD)
     .Select(x => new { x.Id, Json = x.ToJSON() }).Batchify(1000))

To skróciło czasy nieco bardziej, więc mogę załadować 10M w 3 minuty i 57 sekund, w tempie 42 194 rzutów. Większość tego czasu to w rzeczywistości przetwarzanie lokalne w aplikacji. Jeśli zmienię to tak, że każdy wątek ładuje tak samo item ITEMS / THREADS razy, potem zmienia się to na 1 minutę 48 sekund – w tempie 92 592 skoków.

Nie jestem pewien, czy naprawdę na cokolwiek odpowiedziałem, ale krótka wersja może brzmieć po prostu „spróbuj dłuższego czasu oczekiwania; rozważ użycie opcji „uruchom i zapomnij”.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Wygaśnięcie RedisTemplate nie działa

  2. Redis nie aktualizuje się, gdy wiele żądań naraz

  3. Redis, słuchanie wydarzeń pubsub i przekształcanie ich w strumień w celu bardziej niezawodnej konsumpcji

  4. Redistogo i Sidekiq na Heroku:nie można się połączyć

  5. Jak magento wymyśla nazwy kluczy pamięci podręcznej?