O ile szybciej jest Redis niż mongoDB?

204

Powszechnie wspomniano, że Redis jest „Blazing Fast”, a mongoDB też jest szybki. Ale mam problem ze znalezieniem rzeczywistych liczb porównujących wyniki tych dwóch. Biorąc pod uwagę podobne konfiguracje, funkcje i operacje (i być może pokazując, jak zmienia się czynnik przy różnych konfiguracjach i operacjach) itd., Czy Redis jest 10 razy szybszy ?, 2x szybszy ?, 5 razy szybszy?

Mówię tylko o wydajności. Rozumiem, że mongoDB jest innym narzędziem i ma bogatszy zestaw funkcji. To nie jest debata „Czy mongoDB jest lepsza niż Redis”. Pytam, o jaką różnicę Redis przewyższa mongoDB?

W tym momencie nawet tanie testy porównawcze są lepsze niż brak testów porównawczych.

Homer6
źródło
10
Tanie testy porównawcze są zawsze lepsze niż brak testów porównawczych. Dzięki za kolego z pytań.
Maziyar
2
Ogólnie rzecz biorąc, dbanie o różnicę między 5000 operacji na sekundę a 10 000 operacji na sekundę jest często przypadkiem przedwczesnej optymalizacji. To powiedziawszy, to wciąż ciekawa odpowiedź :)
Kevin

Odpowiedzi:

238

Szorstkie wyniki z następującego testu porównawczego: 2x zapis, 3x odczyt .

Oto prosty test porównawczy w pythonie, który możesz dostosować do swoich celów. Sprawdzałem, jak dobrze każdy z nich wykona proste ustawienie / pobieranie wartości:

#!/usr/bin/env python2.7
import sys, time
from pymongo import Connection
import redis

# connect to redis & mongodb
redis = redis.Redis()
mongo = Connection().test
collection = mongo['test']
collection.ensure_index('key', unique=True)

def mongo_set(data):
    for k, v in data.iteritems():
        collection.insert({'key': k, 'value': v})

def mongo_get(data):
    for k in data.iterkeys():
        val = collection.find_one({'key': k}, fields=('value',)).get('value')

def redis_set(data):
    for k, v in data.iteritems():
        redis.set(k, v)

def redis_get(data):
    for k in data.iterkeys():
        val = redis.get(k)

def do_tests(num, tests):
    # setup dict with key/values to retrieve
    data = {'key' + str(i): 'val' + str(i)*100 for i in range(num)}
    # run tests
    for test in tests:
        start = time.time()
        test(data)
        elapsed = time.time() - start
        print "Completed %s: %d ops in %.2f seconds : %.1f ops/sec" % (test.__name__, num, elapsed, num / elapsed)

if __name__ == '__main__':
    num = 1000 if len(sys.argv) == 1 else int(sys.argv[1])
    tests = [mongo_set, mongo_get, redis_set, redis_get] # order of tests is significant here!
    do_tests(num, tests)

Wyniki dla mongodb 1.8.1 i redis 2.2.5 i najnowszego pymongo / redis-py:

$ ./cache_benchmark.py 10000
Completed mongo_set: 10000 ops in 1.40 seconds : 7167.6 ops/sec
Completed mongo_get: 10000 ops in 2.38 seconds : 4206.2 ops/sec
Completed redis_set: 10000 ops in 0.78 seconds : 12752.6 ops/sec
Completed redis_get: 10000 ops in 0.89 seconds : 11277.0 ops/sec

Weź oczywiście wyniki z odrobiną soli! Jeśli programujesz w innym języku, korzystasz z innych klientów / różnych implementacji itp., Wyniki będą się różnić. Nie wspominając o tym, że korzystanie z niego będzie zupełnie inne! Najlepszym rozwiązaniem jest ich samodzielne przetestowanie, dokładnie tak, jak zamierzasz ich używać. W następstwie prawdopodobnie wymyślisz najlepszy sposób wykorzystania każdego z nich. Zawsze porównuj dla siebie!

zeekay
źródło
3
Warto skomentować, że MongoDB i Redis mają różne struktury trwałości i że Redis obsługuje tylko schemat danych, który jest w stanie zmieścić się w pamięci. Chociaż RAM jest tani, jeśli potrzebujesz użyć / przechowywać więcej niż 12-16 GB danych, zobaczyłbym, jak wyglądają twoje opcje serwera.
Tracker1
53
@sivann ten post przechodzi od braku testów porównawczych do wyraźnie określonego „szorstkiego” testu porównawczego. Nie bądź trollem z nonsensem „benchmarki wprowadzają w błąd”. Oczywiście różne warunki mogą zmienić wyniki. Przekaż z powrotem i prześlij własne testy porównawcze, które testują twoją sprawę i link z tego postu, wtedy wszyscy skorzystamy z Twojej „przetestowanej” opinii.
Homer6
2
@sivann Domyślna (dostarczona) konfiguracja testowała ten test porównawczy. IMHO, domyślna konfiguracja określa, po której stronie ogrodzenia fsync znajduje się pakiet. W przypadku Redis jest reklamowany jako serwer pamięci, który zachęca ludzi do korzystania z innych alternatyw, gdy baza danych jest większa niż całkowita pamięć systemowa. W przypadku MongoDB jest reklamowany jako baza danych. Postgres nigdy nie wyłączyłby fsync, ponieważ wyraźnie znajdują się w obozie uporczywości. Większość ludzi nie modyfikuje konfiguracji, więc ten test porównawczy jest nieco dokładny w tych przypadkach.
Homer6
4
Zgadzam się z @sivann, opublikowany przez ciebie test jest fatalnie wadliwy. MongoDB jest wielowątkowy, a Redis nie. Jeśli twój test byłby wielowątkowy, zobaczysz, że MongoDb faktycznie ma wyższą przepustowość na maszynie wielordzeniowej.
ColinM,
2
@ Homer6 nawet dla DB zorientowanej na pamięć, powinieneś przetestować z włączoną funkcją WriteConcern (domyślnie wyłączona). Testowanie bez jest naprawdę nonsensem dla każdego rodzaju testu porównawczego. Podobne dla reddis. Bazy danych, które nie synchronizują na dysku wszystkich transakcji, utrzymują bezpieczeństwo, replikując dane do co najmniej 2 serwerów. Oznacza to, że Twoje zapisy nie czekają na synchronizację dysku, ale na replikację sieci przed powrotem. Nie czekanie na błędy nigdy nie jest robione na prod. jak brak wykrycia, czy kabel sieciowy jest podłączony podczas zapisu do sieci.
sivann
18

Sprawdź ten post na temat analizy wydajności wstawiania Redis i MongoDB:

Aż do 5000 wpisów mongodb $ push jest szybszy nawet w porównaniu z Redis RPUSH, wtedy staje się niesamowicie wolny, prawdopodobnie typ tablicy mongodb ma liniowy czas wstawiania, więc staje się coraz wolniejszy. mongodb może zyskać trochę na wydajności, ujawniając typ stałej listy wstawiania czasu, ale nawet z liniowym typem tablicy czasowej (co może zagwarantować ciągłe wyszukiwanie czasu) ma swoje zastosowanie do małych zestawów danych.

Andriej Andruszkiewicz
źródło
15

Dobry i prosty punkt odniesienia

Próbowałem ponownie przeliczyć wyniki przy użyciu bieżących wersji redis (2.6.16) i mongo (2.4.8) i oto wynik

Completed mongo_set: 100000 ops in 5.23 seconds : 19134.6 ops/sec
Completed mongo_get: 100000 ops in 36.98 seconds : 2703.9 ops/sec
Completed redis_set: 100000 ops in 6.50 seconds : 15389.4 ops/sec
Completed redis_get: 100000 ops in 5.59 seconds : 17896.3 ops/sec

Również ten post na blogu porównuje oba, ale używa node.js. Pokazuje efekt rosnącej liczby wpisów w bazie danych wraz z upływem czasu.

Tareq Salah
źródło
8

Trudno będzie znaleźć liczby, ponieważ nie są one w tej samej przestrzeni. Ogólna odpowiedź jest taka, że ​​Redis jest o 10–30% szybszy, gdy zestaw danych mieści się w pamięci roboczej pojedynczego komputera. Po przekroczeniu tej ilości danych Redis kończy się niepowodzeniem. Mongo zwolni w stopniu zależnym od rodzaju ładunku. W przypadku obciążenia tylko z wstawką jeden użytkownik niedawno zgłosił spowolnienie od 6 do 7 rzędów wielkości (10 000 do 100 000 razy), ale raport ten przyznał również, że wystąpiły problemy z konfiguracją i że było to bardzo nietypowe obciążenie robocze. Normalne odczytywanie dużych obciążeń anegdotycznie spowalnia około 10 razy, gdy niektóre dane muszą zostać odczytane z dysku.

Wniosek: Redis będzie szybszy, ale nie za bardzo.

John F. Miller
źródło
7

Oto doskonały artykuł o wydajności sesji w środowisku Tornado w wieku około 1 roku. Zawiera porównanie kilku różnych implementacji, w tym Redis i MongoDB. Wykres w artykule stwierdza, że ​​Redis stoi za MongoDB o około 10% w tym konkretnym przypadku użycia.

Redis jest wyposażony we wbudowany test porównawczy, który analizuje wydajność używanego komputera. Istnieje mnóstwo nieprzetworzonych danych na wiki Benchmark dla Redis. Ale może będziesz musiał rozejrzeć się trochę za Mongo. Jak tutaj , tutaj i kilka losowych liczb polskich (ale daje to punkt wyjścia do samodzielnego uruchomienia niektórych testów porównawczych MongoDB).

Uważam, że najlepszym rozwiązaniem tego problemu jest samodzielne wykonanie testów w oczekiwanych sytuacjach.

mistagrooves
źródło
Testy porównawcze Tornado dobrze pasują do moich własnych testów używania Redis i MongoDb jako backendu Zend_Cache. Bogatsza funkcjonalność MongoDb pozwala na użycie mniejszej liczby żądań, a wielowątkowy projekt skaluje się znacznie lepiej niż pojedynczy proces Redis, który nie jest wielowątkowy. Wniosek jest taki, że MongoDb skaluje się wyżej. Ponadto Redis nie obsługuje już pamięci wirtualnej.
ColinM,
3

W moim przypadku czynnikiem decydującym w porównaniu wydajności jest zastosowane narzędzie MongoDb WriteConcern. Obecnie większość sterowników mongo ustawia domyślną wartość WriteConcern na ACKNOWLEDGED, co oznacza „zapisany w pamięci RAM” ( Mongo2.6.3-WriteConcern ), pod tym względem był bardzo podobny do redis dla większości operacji zapisu.

Ale rzeczywistość zależy od potrzeb aplikacji i konfiguracji środowiska produkcyjnego, możesz zmienić tę kwestię na WriteConcern.JOURNALED (zapisany na oplog) lub WriteConcern.FSYNCED (zapisany na dysk) lub nawet zapisany na zestawach replik (kopie zapasowe) jeśli jest to potrzebne.

Wtedy możesz zacząć odczuwać spadek wydajności. Inne ważne czynniki obejmują również, jak zoptymalizowane są wzorce dostępu do danych, wskaźnik pominięcia% (patrz mongostat ) i indeksy w ogóle.

schwarz
źródło
0

Myślę, że 2-3X na pokazanym teście wprowadzają w błąd, ponieważ jeśli zależy to również od sprzętu, na którym go uruchomiłeś - z mojego doświadczenia wynika, że ​​„mocniejsza” jest maszyna, tym większa jest luka (na korzyść Redis) będzie, prawdopodobnie dlatego, że test porównawczy dość szybko przekroczy limit pamięci.

Jeśli chodzi o pojemność pamięci - jest to częściowo prawda, ponieważ istnieją również sposoby na obejście tego, istnieją (komercyjne) produkty, które zapisują dane Redis na dysku, a także rozwiązania klastrowe (wielodostępne), które pokonują rozmiar pamięci ograniczenie.

Elior Malul
źródło