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

Redis vs. MongoDB:porównywanie baz danych w pamięci za pomocą mechanizmu pamięci Percona

W tym poście porównujemy dwie najpopularniejsze bazy danych NoSQL:Redis (w pamięci) i MongoDB (silnik pamięci Percona).

Redis to popularny i bardzo szybki magazyn struktury bazy danych w pamięci, używany głównie jako pamięć podręczna lub broker wiadomości. Będąc w pamięci, jest to magazyn danych z wyboru, gdy czasy odpowiedzi są ważniejsze niż wszystko inne.

MongoDB to magazyn dokumentów na dysku, który zapewnia interfejs JSON do danych i ma bardzo bogaty język zapytań. Znana ze swojej szybkości, wydajności i skalowalności, jest obecnie najpopularniejszą obecnie używaną bazą danych NoSQL. Jednak będąc bazą danych na dysku, nie może być korzystnie w porównaniu z bazą danych w pamięci, taką jak Redis, pod względem bezwzględnej wydajności. Jednak dzięki dostępności silników pamięci masowej w pamięci dla MongoDB możliwe staje się bardziej bezpośrednie porównanie.

Silnik pamięci Percona dla MongoDB

Począwszy od wersji 3.0, MongoDB udostępnia interfejs API do podłączenia wybranego silnika pamięci. Silnik pamięci, z kontekstu MongoDB, jest składnikiem bazy danych odpowiedzialnym za zarządzanie sposobem przechowywania danych, zarówno w pamięci, jak i na dysku. MongoDB obsługuje silnik pamięci masowej, jednak obecnie jest ograniczony do wersji Enterprise produktu. W 2016 r. firma Percona wypuściła silnik in-memory o otwartym kodzie źródłowym dla MongoDB Community Edition o nazwie Percona Memory Engine dla MongoDB. Podobnie jak silnik pamięci wewnętrznej MonogDB, jest to również odmiana silnika pamięci masowej WiredTiger, ale bez utrwalania na dysku.

Dzięki wbudowanemu silnikowi pamięci masowej MongoDB mamy równe szanse między Redis i MongoDB. Dlaczego więc musimy je porównywać? Przyjrzyjmy się zaletom każdego z nich jako rozwiązania do buforowania.

Spójrzmy najpierw na Redis.

Zalety Redisa jako pamięci podręcznej

  • Dobrze znane rozwiązanie do buforowania, które się w nim wyróżnia.
  • Redis nie jest zwykłym rozwiązaniem pamięci podręcznej – ma zaawansowane struktury danych, które zapewniają wiele skutecznych sposobów zapisywania i sprawdzania danych, których nie można osiągnąć za pomocą waniliowej pamięci podręcznej klucz-wartość.
  • Redis jest dość prosty w konfiguracji, obsłudze i nauce.
  • Redis zapewnia trwałość, którą możesz skonfigurować, więc podgrzewanie pamięci podręcznej w przypadku awarii jest bezproblemowe.

Wady Redisa:

  • Nie ma wbudowanego szyfrowania w przewodzie.
  • Brak kontroli konta opartej na rolach (RBAC).
  • Nie ma jednolitego, dojrzałego rozwiązania do klastrowania.
  • Wdrożenie w chmurze na dużą skalę może być trudne.

Zalety MongoDB jako pamięci podręcznej

  •  MongoDB to bardziej tradycyjna baza danych z zaawansowanymi funkcjami manipulacji danymi (agregacja myśli i redukcja map) oraz bogatym językiem zapytań.
  • Wbudowane SSL, RBAC i skalowanie w poziomie.
  • Jeśli korzystasz już z MongoDB jako podstawowej bazy danych, koszty operacyjne i programistyczne spadają, ponieważ masz tylko jedną bazę danych do nauki i zarządzania.

Spójrz na ten post Petera Zajcewa, w którym dowiesz się, gdzie silnik MongoDB w pamięci może być dobrym rozwiązaniem.

Wady MongoDB:

  • Z silnikiem w pamięci nie zapewnia trwałości, dopóki nie zostanie wdrożony jako zestaw replik z trwałością skonfigurowaną na replikach do odczytu.

W tym poście skupimy się na ilościowym określeniu różnic w wydajności między Redis i MongoDB . Porównanie jakościowe i różnice operacyjne zostaną omówione w kolejnych postach.

Redis a MongoDB w pamięci

Wydajność

  • Redis działa znacznie lepiej w przypadku odczytów dla wszelkiego rodzaju obciążeń i lepiej dla zapisów w miarę wzrostu obciążenia.
  • Mimo że MongoDB wykorzystuje wszystkie rdzenie systemu, stosunkowo wcześnie wiąże się z CPU. Chociaż nadal miał dostępne obliczenia, był lepszy w zapisie niż Redis.
  • Obie bazy danych są ostatecznie powiązane z obliczeniami. Mimo że Redis jest jednowątkowy, (przeważnie) wykonuje więcej pracy na jednym rdzeniu niż MongoDB podczas nasycania wszystkich rdzeni.
  • Ponownie , w przypadku nietrywialnych zestawów danych, używa znacznie więcej pamięci RAM w porównaniu do MongoDB do przechowywania tej samej ilości danych.

Konfiguracja

Wykorzystaliśmy YCSB do pomiaru wydajności i używaliśmy go do porównywania i testowania wydajności MongoDB z różnymi dostawcami chmury i konfiguracjami w przeszłości. Zakładamy podstawową wiedzę na temat obciążeń i funkcji YCSB w opisie stanowiska testowego.

  • Typ instancji bazy danych:   AWS EC2 c4.xlarge z 4 rdzeniami, 7,5 GB pamięci i ulepszoną obsługą sieci, dzięki czemu nie mamy żadnych wąskich gardeł w sieci.
  • Maszyna klienta:   AWS EC2 c4.xlarge w tej samej wirtualnej chmurze prywatnej (VPC) co serwery baz danych.
  • Ponownie:  Wersja 3.2.8 z wyłączonymi AOF i RDB. Samodzielny.
  • MongoDB:  Percona Memory Engine oparty na MongoDB w wersji 3.2.12. Samodzielny.
  • Przepustowość sieci :  Mierzone przez iperf zgodnie z zaleceniami AWS:
    Test Complete. Summary Results:
    [ ID] Interval           Transfer     Bandwidth       Retr
    [  4]   0.00-60.00  sec  8.99 GBytes  1.29 Gbits/sec  146             sender
    [  4]   0.00-60.00  sec  8.99 GBytes  1.29 Gbits/sec                  receiver
    
  • Szczegóły zadania
    1. Wstaw zadanie: 100% zapisu – 2,5 miliona rekordów
    2. Zadanie A: Aktualizacja dużego obciążenia – 50%/50% odczytów/zapisów – 25 milionów operacji
    3. Zadanie B: Czytaj głównie obciążenie – 95%/5% odczytów/zapisów – 25 milionów operacji
  • Ładowanie klienta: Przepustowość i opóźnienia mierzone na przyrostowo rosnących obciążeniach generowanych przez klienta. Dokonano tego poprzez zwiększenie liczby wątków ładowania klienta YCSB, zaczynając od 8 i rosnąc w wielokrotności 2

Wyniki

Wydajność obciążenia B

Ponieważ podstawowym przypadkiem użycia baz danych w pamięci jest pamięć podręczna, spójrzmy najpierw na obciążenie B.

Oto liczby dotyczące przepustowości/opóźnień z 25 milionów operacji obciążenia, a stosunek odczytów/zapisów wyniósł 95%/5%. Byłoby to reprezentatywne obciążenie odczytu pamięci podręcznej:

Uwaga:przepustowość jest kreślona względem osi głównej (po lewej), a opóźnienie względem osi pomocniczej (po prawej).

Obserwacje podczas wykonywania zadania B:

  • W przypadku MongoDB procesor został nasycony przez 32 wątki wzwyż. Wykorzystanie ponad 300% z jednocyfrowymi wartościami procentowymi bezczynności.
  • W przypadku Redis wykorzystanie procesora nigdy nie przekroczyło 95%. Tak więc Redis konsekwentnie działał lepiej niż MongoDB podczas działania w jednym wątku, podczas gdy MongoDB nasycał wszystkie rdzenie maszyny.
  • W przypadku Redis, przy 128 wątkach, uruchomienia często kończyły się niepowodzeniem z wyjątkami dotyczącymi limitu czasu odczytu.

Wydajność obciążenia A

Oto liczby dotyczące przepustowości/opóźnień z obciążenia 25 milionami operacji. Stosunek odczytów/zapisów wyniósł 50%/50%:

Uwaga:przepustowość jest kreślona względem osi głównej (po lewej), a opóźnienie względem osi pomocniczej (po prawej).

Obserwacje podczas przebiegu Obciążenia A:

  • W przypadku MongoDB procesor został nasycony przez 32 wątki wzwyż. Wykorzystanie ponad 300% z jednocyfrowymi wartościami procentowymi bezczynności.
  • W przypadku Redis wykorzystanie procesora nigdy nie przekroczyło 95%.
  • W przypadku Redis, przez 64 wątki i więcej, uruchomienia często kończyły się niepowodzeniem z wyjątkami dotyczącymi limitu czasu odczytu.

Wstaw wydajność obciążenia

Na koniec podajemy dane dotyczące przepustowości/opóźnień z 2,5 miliona obciążenia wstawiania rekordów. Wybrano liczbę rekordów, aby zapewnić wykorzystanie całkowitej pamięci w zdarzeniu Redis, która nie przekroczyła 80% (ponieważ Redis jest świnią pamięci, patrz Dodatek B).

Uwaga:przepustowość jest kreślona względem osi głównej (po lewej), a opóźnienie względem osi pomocniczej (po prawej).

Obserwacje podczas uruchamiania wstawiania obciążenia:

  • W przypadku MongoDB procesor został nasycony przez 32 wątki wzwyż. Wykorzystanie ponad 300% z jednocyfrowymi wartościami procentowymi bezczynności.
  • W przypadku Redis wykorzystanie procesora nigdy nie przekroczyło 95%.

Załączniki

O:Wydajność w jednym wątku

Miałem wielką ochotę się tego dowiedzieć – mimo że nie jest to zbyt przydatne w rzeczywistych warunkach:kto byłby lepszy, gdyby przykładał to samo obciążenie do każdego z nich z jednego wątku. To znaczy, jak działałaby aplikacja jednowątkowa?

B:Rozmiar bazy danych

Domyślny format rekordów wstawianych przez YCSB to:każdy rekord składa się z 10 pól, a każde pole ma 100 bajtów. Zakładając, że każdy rekord ma około 1 KB, całkowity oczekiwany rozmiar w pamięci wyniesie ponad 2,4 GB. Rzeczywiste rozmiary widoczne w bazach danych były wyraźne.

MongoDB

> db.usertable.count()
2500000
> db.usertable.findOne()
{
    "_id" : "user6284781860667377211",
    "field1" : BinData(0,"OUlxLllnPC0sJEovLTpyL18jNjk6ME8vKzF4Kzt2OUEzMSEwMkBvPytyODZ4Plk7KzRmK0FzOiYoNFU1O185KFB/IVF7LykmPkE9NF1pLDFoNih0KiIwJU89K0ElMSAgKCF+Lg=="),
    "field0" : BinData(0,"ODlwIzg0Ll5vK1s7NUV1O0htOVRnMk53JEd3KiwuOFN7Mj5oJ1FpM11nJ1hjK0BvOExhK1Y/LjEiJDByM14zPDtgPlcpKVYzI1kvKEc5PyY6OFs9PUMpLEltNEI/OUgzIFcnNQ=="),
    "field7" : BinData(0,"N155M1ZxPSh4O1B7IFUzJFNzNEB1OiAsM0J/NiMoIj9sP1Y1Kz9mKkJ/OiQsMSk2OCouKU1jOltrMj4iKEUzNCVqIV4lJC0qIFY3MUo9MFQrLUJrITdqOjJ6NVs9LVcjNExxIg=="),
    "field6" : BinData(0,"Njw6JVQnMyVmOiZyPFxrPz08IU1vO1JpIyZ0I1txPC9uN155Ij5iPi5oJSIsKVFhP0JxM1svMkphL0VlNzdsOlQxKUQnJF4xPkk9PUczNiF8MzdkNy9sLjg6NCNwIy1sKTw6MA=="),
    "field9" : BinData(0,"KDRqP1o3KzwgNUlzPjwgJEgtJC44PUUlPkknKU5pLzkuLEAtIlg9JFwpKzBqIzo2MCIoKTxgNU9tIz84OFB/MzJ4PjwoPCYyNj9mOjY+KU09JUk1I0l9O0s/IEUhNU05NShiNg=="),
    "field8" : BinData(0,"NDFiOj9mJyY6KTskO0A/OVg/NkchKEFtJUprIlJrPjYsKT98JyI8KFwzOEE7ICR4LUF9JkU1KyRkKikoK0g3MEMxKChsL10pKkAvPFRxLkxhOlotJFZlM0N/LiR4PjlqJ0FtOw=="),
    "field3" : BinData(0,"OSYoJTR+JEp9K00pKj0iITVuIzVqPkBpJFN9Myk4PDhqOjVuP1YhPSM2MFp/Kz14PTF4Mlk3PkhzKlx3L0xtKjkqPCY4JF0vIic6LEx7PVBzI0U9KEM1KDV4NiEuKFx5MiZyPw=="),
    "field2" : BinData(0,"Njd8LywkPlg9IFl7KlE5LV83ISskPVQpNDYgMEprOkprMy06LlotMUF5LDZ0IldzLl0tJVkjMTdgJkNxITFsNismLDxuIyYoNDgsLTc+OVpzKkBlMDtoLyBgLlctLCxsKzl+Mw=="),
    "field5" : BinData(0,"OCJiNlI1O0djK1BtIyc4LEQzNj9wPyQiPT8iNE1pODI2LShqNDg4JF1jNiZiNjZuNE5lNzA8OCAgMDp2OVkjNVU3MzIuJTgkNDp0IyVkJyk6IEEvKzVyK1s9PEAhKUJvPDxyOw=="),
    "field4" : BinData(0,"OFN1I0B7N1knNSR2LFp7PjUyPlJjP15jIUdlN0AhNEkhMC9+Lkd5P10jO1B3K10/I0orIUI1NzYuME81I0Y1NSYkMCxyI0w/LTc8PCEgJUZvMiQiIkIhPCF4LyN6K14rIUJlJg==")
}
> db.runCommand({ dbStats: 1, scale: 1 })
{
    "db" : "ycsb",
    "collections" : 1,
    "objects" : 2500000,
    "avgObjSize" : 1167.8795252,
    "dataSize" : 2919698813,
    "storageSize" : 2919698813,
    "numExtents" : 0,
    "indexes" : 1,
    "indexSize" : 76717901,
    "ok" : 1
}

Tak więc zajęte miejsce wynosi ~2,7 GB, co jest dość zbliżone do tego, czego się spodziewaliśmy.

Ponownie

Spójrzmy teraz na Redis.

> info keyspace
# Keyspace
db0:keys=2500001,expires=0,avg_ttl=0
127.0.0.1:6379> RANDOMKEY
"user3176318471616059981"
127.0.0.1:6379> hgetall user3176318471616059981
 1) "field1"
 2) "#K/<No\"&l*M{,;f;]\x7f)Ss'+2<D}7^a8I/01&9.:)Q71T7,3r&\\y6:< Gk;6n*]-)*f>:p:O=?<:(;v/)0)Yw.W!8]+4B=8.z+*4!"
 3) "field2"
 4) "(9<9P5**d7<v((2-6*3Zg/.p4G=4Us;N+!C! I50>h=>p\"X9:Qo#C9:;z.Xs=Wy*H3/Fe&0`8)t.Ku0Q3)E#;Sy*C).Sg++t4@7-"
 5) "field5"
 6) "#1 %8x='l?5d38~&U!+/b./b;(6-:v!5h.Ou2R}./(*)4!8>\"B'!I)5U?0\" >Ro.Ru=849Im+Qm/Ai(;:$Z',]q:($%&(=3~5(~?"
 7) "field0"
 8) "+\"(1Pw.>*=807Jc?Y-5Nq#Aw=%*57r7!*=Tm!<j6%t3-45L5%Cs#/h;Mg:Vo690-/>-X}/X#.U) )f9-~;?p4;p*$< D-1_s!0p>"
 9) "field7"
10) ":]o/2p/3&(!b> |#:0>#0-9b>Pe6[}<Z{:S}9Uc*0<)?60]37'~'Jk-Li',x!;.5H'\"'|.!v4Y-!Hk=E\x7f2;8*9((-09*b#)x!Pg2"
11) "field3"
12) " C; ,f6Uq+^i Fi'8&0By\"^##Qg\":$+7$%Y;7Rs'\"d3Km'Es>.|33$ Vo*M%=\"<$&j%/<5]%\".h&Kc'5.46x5D35'0-3l:\"| !l;"
13) "field6"
14) "-5x6!22)j;O=?1&!:&.S=$;|//r'?d!W54(j!$:-H5.*n&Zc!0f;Vu2Cc?E{1)r?M'!Kg'-b<Dc*1d2M-9*d&(l?Uk5=8,>0.B#1"
15) "field9"
16) "(Xa&1t&Xq\"$((Ra/Q9&\": &>4Ua;Q=!T;(Vi2G+)Uu.+|:Ne;Ry3U\x7f!B\x7f>O7!Dc;V7?Eu7E9\"&<-Vi>7\"$Q%%A%1<2/V11: :^c+"
17) "field8"
18) "78(8L9.H#5N+.E5=2`<Wk+Pw?+j'Q=3\"$,Nk3O{+3p4K?0/ 5/r:W)5X}#;p1@\x7f\"+&#Ju+Z97#t:J9$'*(K).7&0/` 125O38O)0"
19) "field4"
20) "$F=)Ke5V15_)-'>=C-/Ka7<$;6r#_u F9)G/?;t& x?D%=Ba Zk+]) ($=I%3P3$<`>?*=*r9M1-Ye:S%%0,(Ns3,0'A\x7f&Y12A/5"
127.0.0.1:6379> info memory
# Memory
used_memory:6137961456
used_memory_human:5.72G
used_memory_rss:6275940352
used_memory_rss_human:5.84G
used_memory_peak:6145349904
used_memory_peak_human:5.72G
total_system_memory:7844429824
total_system_memory_human:7.31G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:7516192768
maxmemory_human:7.00G
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.02
mem_allocator:jemalloc-3.6.0

Wydaje się, że przy szczytowym wykorzystaniu Redis zajmuje około 5,72 GB pamięci, tj. dwa razy więcej pamięci niż zajmuje MongoDB. Teraz to porównanie może nie być idealne ze względu na różnice w dwóch bazach danych, ale ta różnica w użyciu pamięci jest zbyt duża, aby ją zignorować. YCSB wstawia rekord w hashu w Redis, a indeks jest utrzymywany w posortowanym zestawie. Ponieważ pojedynczy wpis jest większy niż 64, skrót jest kodowany normalnie i nie ma oszczędności miejsca. Wydajność Redis ma cenę zwiększonego zużycia pamięci.

Naszym zdaniem może to być ważny punkt danych przy wyborze między MongoDB a Redis – MongoDB może być preferowany dla użytkowników, którym zależy na zmniejszeniu kosztów pamięci.

C:Przepustowość sieci

Serwer bazy danych w pamięci może być powiązany z obliczeniami lub sieciowym wejściem/wyjściem, dlatego podczas całego zestawu tych testów ważne było upewnienie się, że nigdy nie zostaniemy powiązani z siecią. Pomiar przepustowości sieci podczas wykonywania testów przepustowości aplikacji niekorzystnie wpływa na ogólny pomiar przepustowości. Dlatego przeprowadziliśmy kolejne pomiary przepustowości sieci przy użyciu iftop przy liczbie wątków, gdzie zaobserwowano najwyższą przepustowość zapisu. Stwierdzono, że wynosi ona około 440 Mb/s zarówno dla Redis, jak i MongoDB przy ich szczytowej przepustowości. Biorąc pod uwagę nasz początkowy pomiar maksymalnej przepustowości sieci, który wynosi około 1,29 Gb/s, jesteśmy pewni, że nigdy nie osiągniemy granic sieci. W rzeczywistości potwierdza tylko wniosek, że gdyby Redis był wielordzeniowy, moglibyśmy uzyskać znacznie lepsze liczby.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Czy master zawsze redisuje instancję z najmniejszym priorytetem?

  2. Obraz dokowany strażnika Redis / plik Dockerfile

  3. Jak zdobyć wszystkie klucze z Redis za pomocą szablonu redis

  4. Uruchom redis w maratonie (mesos) pod jednym adresem URL

  5. Microsoft.Extensions.Caching.Redis wybierz inną bazę danych niż db0